blob: cc37fa750845dd7a74bd4184ba3ecbae69e6be9d [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "AidlCamera.h"
#include "HidlDisplay.h"
#include "utils/include/Utils.h"
#include <android-base/logging.h>
namespace aidl::android::automotive::evs::implementation {
namespace hidlevs = ::android::hardware::automotive::evs;
using ::aidl::android::hardware::automotive::evs::BufferDesc;
using ::aidl::android::hardware::automotive::evs::CameraDesc;
using ::aidl::android::hardware::automotive::evs::CameraParam;
using ::aidl::android::hardware::automotive::evs::DisplayState;
using ::aidl::android::hardware::automotive::evs::EvsEventDesc;
using ::aidl::android::hardware::automotive::evs::EvsEventType;
using ::aidl::android::hardware::automotive::evs::EvsResult;
using ::aidl::android::hardware::automotive::evs::IEvsCameraStream;
using ::aidl::android::hardware::automotive::evs::IEvsDisplay;
using ::aidl::android::hardware::automotive::evs::ParameterRange;
using ::android::hardware::hidl_vec;
using ::ndk::ScopedAStatus;
AidlCamera::AidlCamera(const ::android::sp<hidlevs::V1_0::IEvsCamera>& hidlCamera, bool forceV1_0) {
auto hidlCameraV1 = hidlevs::V1_1::IEvsCamera::castFrom(hidlCamera).withDefault(nullptr);
if (forceV1_0 || !hidlCameraV1) {
// AidlCamera is initialized in V1_0::IEvsCamera support mode in below
// three conditions:
// 1. A given camera object is an implementation of V1_0::IEvsCamera
// (fails to upcast as V1_1::IEvsCamera).
// 2. A caller explicitly creates AidlCamera object in V1_0::IEvsCamera
// mode by setting forceV1_0 as true.
// 3. Or, A given camera object is invalid (nullptr).
mImpl = std::make_shared<ImplV0>(hidlCamera);
} else {
mImpl = std::make_shared<ImplV1>(hidlCameraV1);
}
}
const ::android::sp<hidlevs::V1_0::IEvsCamera> AidlCamera::getHidlCamera() const {
return mImpl->getHidlCamera();
}
ScopedAStatus AidlCamera::doneWithFrame(const std::vector<BufferDesc>& buffers) {
return mImpl->doneWithFrame(buffers);
}
ScopedAStatus AidlCamera::forcePrimaryClient(const std::shared_ptr<IEvsDisplay>& display) {
return mImpl->forcePrimaryClient(display);
}
ScopedAStatus AidlCamera::getCameraInfo(CameraDesc* _aidl_return) {
return mImpl->getCameraInfo(_aidl_return);
}
ScopedAStatus AidlCamera::getExtendedInfo(int32_t opaqueIdentifier, std::vector<uint8_t>* value) {
return mImpl->getExtendedInfo(opaqueIdentifier, value);
}
ScopedAStatus AidlCamera::getIntParameter(CameraParam id, std::vector<int32_t>* value) {
return mImpl->getIntParameter(id, value);
}
ScopedAStatus AidlCamera::getIntParameterRange(CameraParam id, ParameterRange* _aidl_return) {
return mImpl->getIntParameterRange(id, _aidl_return);
}
ScopedAStatus AidlCamera::getParameterList(std::vector<CameraParam>* _aidl_return) {
return mImpl->getParameterList(_aidl_return);
}
ScopedAStatus AidlCamera::getPhysicalCameraInfo(const std::string& deviceId,
CameraDesc* _aidl_return) {
return mImpl->getPhysicalCameraInfo(deviceId, _aidl_return);
}
ScopedAStatus AidlCamera::importExternalBuffers(const std::vector<BufferDesc>& buffers,
int32_t* _aidl_return) {
return mImpl->importExternalBuffers(buffers, _aidl_return);
}
ScopedAStatus AidlCamera::pauseVideoStream() {
return mImpl->pauseVideoStream();
}
ScopedAStatus AidlCamera::resumeVideoStream() {
return mImpl->resumeVideoStream();
}
ScopedAStatus AidlCamera::setExtendedInfo(int32_t opaqueIdentifier,
const std::vector<uint8_t>& opaqueValue) {
return mImpl->setExtendedInfo(opaqueIdentifier, opaqueValue);
}
ScopedAStatus AidlCamera::setIntParameter(CameraParam id, int32_t value,
std::vector<int32_t>* effectiveValue) {
return mImpl->setIntParameter(id, value, effectiveValue);
}
ScopedAStatus AidlCamera::setPrimaryClient() {
return mImpl->setPrimaryClient();
}
ScopedAStatus AidlCamera::setMaxFramesInFlight(int32_t bufferCount) {
return mImpl->setMaxFramesInFlight(bufferCount);
}
ScopedAStatus AidlCamera::startVideoStream(const std::shared_ptr<IEvsCameraStream>& listener) {
return mImpl->startVideoStream(listener);
}
ScopedAStatus AidlCamera::stopVideoStream() {
return mImpl->stopVideoStream();
}
ScopedAStatus AidlCamera::unsetPrimaryClient() {
return mImpl->unsetPrimaryClient();
}
AidlCamera::ImplV0::ImplV0(const ::android::sp<hidlevs::V1_0::IEvsCamera>& camera) :
IHidlCamera(camera) {
if (!camera) {
LOG(WARNING) << "AidlCamera object is instantiated with an invalid IEvsCamera object.";
return;
}
// Because android::hardware::automotive::evs::V1_0::BufferDesc does not
// contain a device id while it is required to handle received frames
// properly, we are retrieving it from the camera descriptor and store
// locally.
camera->getCameraInfo([this](const auto& read) { mId = read.cameraId; });
}
ScopedAStatus AidlCamera::ImplV0::doneWithFrame(const std::vector<BufferDesc>& buffers) {
if (!mHidlStream) {
LOG(WARNING) << "Ignores a request to return a buffer of an invalid HIDL camera stream";
return ScopedAStatus::ok();
}
hidlevs::V1_0::BufferDesc hidlBuffer;
if (mHidlStream->getHidlBuffer(buffers[0].bufferId, &hidlBuffer)) {
mHidlCamera->doneWithFrame(hidlBuffer);
}
return ScopedAStatus::ok();
}
ScopedAStatus AidlCamera::ImplV0::forcePrimaryClient(
[[maybe_unused]] const std::shared_ptr<IEvsDisplay>& display) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
}
ScopedAStatus AidlCamera::ImplV0::getCameraInfo(CameraDesc* _aidl_return) {
if (!mHidlCamera) {
LOG(ERROR) << "HIDL camera is not valid";
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
(void)mHidlCamera->getCameraInfo(
[_aidl_return](auto& desc) { *_aidl_return = std::move(Utils::makeFromHidl(desc)); });
return ScopedAStatus::ok();
}
ScopedAStatus AidlCamera::ImplV0::getExtendedInfo(int32_t opaqueIdentifier,
std::vector<uint8_t>* value) {
if (!mHidlCamera) {
LOG(ERROR) << "HIDL camera is not valid";
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
int32_t hidlValue = mHidlCamera->getExtendedInfo(opaqueIdentifier);
value->resize(sizeof(hidlValue));
int* p = reinterpret_cast<int*>(value->data());
*p = hidlValue;
return ScopedAStatus::ok();
}
ScopedAStatus AidlCamera::ImplV0::getIntParameter(CameraParam /*id*/,
std::vector<int32_t>* /*value*/) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
}
ScopedAStatus AidlCamera::ImplV0::getIntParameterRange(CameraParam /*id*/,
ParameterRange* /*_aidl_return*/) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
}
ScopedAStatus AidlCamera::ImplV0::getParameterList(std::vector<CameraParam>* /*_aidl_return*/) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
}
ScopedAStatus AidlCamera::ImplV0::getPhysicalCameraInfo(const std::string& /*deviceId*/,
CameraDesc* /*_aidl_return*/) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
}
ScopedAStatus AidlCamera::ImplV0::importExternalBuffers(const std::vector<BufferDesc>& /*buffers*/,
int32_t* /*_aidl_return*/) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
}
ScopedAStatus AidlCamera::ImplV0::pauseVideoStream() {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
}
ScopedAStatus AidlCamera::ImplV0::resumeVideoStream() {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
}
ScopedAStatus AidlCamera::ImplV0::setExtendedInfo(int32_t opaqueIdentifier,
const std::vector<uint8_t>& opaqueValue) {
if (opaqueValue.size() < sizeof(int32_t)) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::INVALID_ARG);
}
int32_t v = *(reinterpret_cast<const int32_t*>(opaqueValue.data()));
return Utils::buildScopedAStatusFromEvsResult(
mHidlCamera->setExtendedInfo(opaqueIdentifier, v));
}
ScopedAStatus AidlCamera::ImplV0::setIntParameter(CameraParam /*id*/, int32_t /*value*/,
std::vector<int32_t>* /*effectiveValue*/) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
}
ScopedAStatus AidlCamera::ImplV0::setPrimaryClient() {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
}
ScopedAStatus AidlCamera::ImplV0::setMaxFramesInFlight(int32_t bufferCount) {
if (!mHidlCamera) {
LOG(ERROR) << "HIDL camera is not valid";
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
return Utils::buildScopedAStatusFromEvsResult(mHidlCamera->setMaxFramesInFlight(bufferCount));
}
ScopedAStatus AidlCamera::ImplV0::startVideoStream(
const std::shared_ptr<IEvsCameraStream>& listener) {
if (!listener) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::INVALID_ARG);
} else if (mHidlStream) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::STREAM_ALREADY_RUNNING);
}
// Creates a wrapper object and requests a video stream
mHidlStream = new (std::nothrow) HidlCameraStream(mId, listener);
return Utils::buildScopedAStatusFromEvsResult(mHidlCamera->startVideoStream(mHidlStream));
}
ScopedAStatus AidlCamera::ImplV0::stopVideoStream() {
if (!mHidlStream) {
return ScopedAStatus::ok();
}
mHidlCamera->stopVideoStream();
mHidlStream = nullptr;
return ScopedAStatus::ok();
}
ScopedAStatus AidlCamera::ImplV0::unsetPrimaryClient() {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
}
AidlCamera::ImplV1::ImplV1(const ::android::sp<hidlevs::V1_1::IEvsCamera>& camera) :
IHidlCamera(camera), mHidlCamera(camera) {
if (!camera) {
LOG(WARNING) << "AidlCamera object is instantiated with an invalid IEvsCamera object.";
return;
}
camera->getCameraInfo_1_1([this](const auto& read) { mId = read.v1.cameraId; });
}
ScopedAStatus AidlCamera::ImplV1::doneWithFrame(const std::vector<BufferDesc>& buffers) {
if (!mHidlStream) {
LOG(WARNING) << "Ignores a request to return a buffer of an invalid HIDL camera stream";
return ScopedAStatus::ok();
}
const auto n = buffers.size();
hidl_vec<hidlevs::V1_1::BufferDesc> hidlBuffers(n);
for (auto i = 0; i < n; ++i) {
hidlevs::V1_1::BufferDesc buffer;
if (mHidlStream->getHidlBuffer(buffers[i].bufferId, &buffer)) {
hidlBuffers[i] = std::move(buffer);
}
}
mHidlCamera->doneWithFrame_1_1(hidlBuffers);
return ScopedAStatus::ok();
}
ScopedAStatus AidlCamera::ImplV1::forcePrimaryClient(const std::shared_ptr<IEvsDisplay>& display) {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::NOT_SUPPORTED);
}
return Utils::buildScopedAStatusFromEvsResult(
mHidlCamera->forceMaster(new HidlDisplay(display)));
}
ScopedAStatus AidlCamera::ImplV1::getCameraInfo(CameraDesc* _aidl_return) {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
(void)mHidlCamera->getCameraInfo_1_1(
[_aidl_return](auto& desc) { *_aidl_return = std::move(Utils::makeFromHidl(desc)); });
return ScopedAStatus::ok();
}
ScopedAStatus AidlCamera::ImplV1::getExtendedInfo(int32_t opaqueIdentifier,
std::vector<uint8_t>* value) {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
hidlevs::V1_0::EvsResult hidlStatus = hidlevs::V1_0::EvsResult::OK;
(void)mHidlCamera->getExtendedInfo_1_1(opaqueIdentifier,
[&hidlStatus, value](auto status,
const hidl_vec<uint8_t>& hwValue) {
hidlStatus = status;
*value = hwValue;
});
return Utils::buildScopedAStatusFromEvsResult(hidlStatus);
}
ScopedAStatus AidlCamera::ImplV1::getIntParameter(CameraParam id, std::vector<int32_t>* value) {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
hidlevs::V1_0::EvsResult hidlStatus = hidlevs::V1_0::EvsResult::OK;
(void)mHidlCamera->getIntParameter(Utils::makeToHidl(id),
[&hidlStatus, value](auto status,
const hidl_vec<int32_t>& hidlValues) {
hidlStatus = status;
*value = hidlValues;
});
return Utils::buildScopedAStatusFromEvsResult(hidlStatus);
}
ScopedAStatus AidlCamera::ImplV1::getIntParameterRange(CameraParam id,
ParameterRange* _aidl_return) {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
(void)mHidlCamera->getIntParameterRange(Utils::makeToHidl(id),
[_aidl_return](auto min, auto max, auto step) {
_aidl_return->min = min;
_aidl_return->max = max;
_aidl_return->step = step;
});
return ScopedAStatus::ok();
}
ScopedAStatus AidlCamera::ImplV1::getParameterList(std::vector<CameraParam>* _aidl_return) {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
(void)mHidlCamera->getParameterList(
[_aidl_return](const hidl_vec<hidlevs::V1_1::CameraParam>& list) {
_aidl_return->reserve(list.size());
for (auto i = 0; i < list.size(); ++i) {
_aidl_return->push_back(std::move(Utils::makeFromHidl(list[i])));
}
});
return ScopedAStatus::ok();
}
ScopedAStatus AidlCamera::ImplV1::getPhysicalCameraInfo(const std::string& deviceId,
CameraDesc* _aidl_return) {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
(void)mHidlCamera->getPhysicalCameraInfo(deviceId, [_aidl_return](const auto& hidlDesc) {
*_aidl_return = std::move(Utils::makeFromHidl(hidlDesc));
});
return ScopedAStatus::ok();
}
ScopedAStatus AidlCamera::ImplV1::importExternalBuffers(const std::vector<BufferDesc>& buffers,
int32_t* _aidl_return) {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
hidl_vec<hidlevs::V1_1::BufferDesc> hidlBuffers;
hidlBuffers.resize(buffers.size());
for (auto i = 0; i < buffers.size(); ++i) {
hidlBuffers[i] = std::move(Utils::makeToHidlV1_1(buffers[i]));
}
hidlevs::V1_0::EvsResult hidlStatus = hidlevs::V1_0::EvsResult::OK;
(void)mHidlCamera->importExternalBuffers(hidlBuffers,
[&hidlStatus, _aidl_return](auto status, auto delta) {
hidlStatus = status;
*_aidl_return = delta;
});
return Utils::buildScopedAStatusFromEvsResult(hidlStatus);
}
ScopedAStatus AidlCamera::ImplV1::pauseVideoStream() {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
return Utils::buildScopedAStatusFromEvsResult(mHidlCamera->pauseVideoStream());
}
ScopedAStatus AidlCamera::ImplV1::resumeVideoStream() {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
return Utils::buildScopedAStatusFromEvsResult(mHidlCamera->resumeVideoStream());
}
ScopedAStatus AidlCamera::ImplV1::setExtendedInfo(int32_t opaqueIdentifier,
const std::vector<uint8_t>& opaqueValue) {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
hidl_vec<uint8_t> value = opaqueValue;
hidlevs::V1_0::EvsResult hidlStatus = mHidlCamera->setExtendedInfo_1_1(opaqueIdentifier, value);
return Utils::buildScopedAStatusFromEvsResult(hidlStatus);
}
ScopedAStatus AidlCamera::ImplV1::setIntParameter(CameraParam id, int32_t value,
std::vector<int32_t>* effectiveValue) {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
hidlevs::V1_0::EvsResult hidlStatus = hidlevs::V1_0::EvsResult::OK;
(void)mHidlCamera->setIntParameter(Utils::makeToHidl(id), value,
[&hidlStatus,
&effectiveValue](auto status,
const hidl_vec<int32_t>& values) {
hidlStatus = status;
*effectiveValue = values;
});
return Utils::buildScopedAStatusFromEvsResult(hidlStatus);
}
ScopedAStatus AidlCamera::ImplV1::setPrimaryClient() {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
return Utils::buildScopedAStatusFromEvsResult(mHidlCamera->setMaster());
}
ScopedAStatus AidlCamera::ImplV1::setMaxFramesInFlight(int32_t bufferCount) {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
return Utils::buildScopedAStatusFromEvsResult(mHidlCamera->setMaxFramesInFlight(bufferCount));
}
ScopedAStatus AidlCamera::ImplV1::startVideoStream(
const std::shared_ptr<IEvsCameraStream>& listener) {
if (!listener) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::INVALID_ARG);
} else if (mHidlStream) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::STREAM_ALREADY_RUNNING);
}
// Creates a wrapper object and requests a video stream
mHidlStream = new (std::nothrow) HidlCameraStream(mId, listener);
return Utils::buildScopedAStatusFromEvsResult(mHidlCamera->startVideoStream(mHidlStream));
}
ScopedAStatus AidlCamera::ImplV1::stopVideoStream() {
if (!mHidlStream) {
return ScopedAStatus::ok();
}
mHidlCamera->stopVideoStream();
mHidlStream = nullptr;
return ScopedAStatus::ok();
}
ScopedAStatus AidlCamera::ImplV1::unsetPrimaryClient() {
if (!mHidlCamera) {
return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
}
return Utils::buildScopedAStatusFromEvsResult(mHidlCamera->unsetMaster());
}
} // namespace aidl::android::automotive::evs::implementation