/* * 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 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& 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(hidlCamera); } else { mImpl = std::make_shared(hidlCameraV1); } } const ::android::sp AidlCamera::getHidlCamera() const { return mImpl->getHidlCamera(); } ScopedAStatus AidlCamera::doneWithFrame(const std::vector& buffers) { return mImpl->doneWithFrame(buffers); } ScopedAStatus AidlCamera::forcePrimaryClient(const std::shared_ptr& display) { return mImpl->forcePrimaryClient(display); } ScopedAStatus AidlCamera::getCameraInfo(CameraDesc* _aidl_return) { return mImpl->getCameraInfo(_aidl_return); } ScopedAStatus AidlCamera::getExtendedInfo(int32_t opaqueIdentifier, std::vector* value) { return mImpl->getExtendedInfo(opaqueIdentifier, value); } ScopedAStatus AidlCamera::getIntParameter(CameraParam id, std::vector* 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* _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& 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& opaqueValue) { return mImpl->setExtendedInfo(opaqueIdentifier, opaqueValue); } ScopedAStatus AidlCamera::setIntParameter(CameraParam id, int32_t value, std::vector* 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& listener) { return mImpl->startVideoStream(listener); } ScopedAStatus AidlCamera::stopVideoStream() { return mImpl->stopVideoStream(); } ScopedAStatus AidlCamera::unsetPrimaryClient() { return mImpl->unsetPrimaryClient(); } AidlCamera::ImplV0::ImplV0(const ::android::sp& 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& 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& 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* 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(value->data()); *p = hidlValue; return ScopedAStatus::ok(); } ScopedAStatus AidlCamera::ImplV0::getIntParameter(CameraParam /*id*/, std::vector* /*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* /*_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& /*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& opaqueValue) { if (opaqueValue.size() < sizeof(int32_t)) { return Utils::buildScopedAStatusFromEvsResult(EvsResult::INVALID_ARG); } int32_t v = *(reinterpret_cast(opaqueValue.data())); return Utils::buildScopedAStatusFromEvsResult( mHidlCamera->setExtendedInfo(opaqueIdentifier, v)); } ScopedAStatus AidlCamera::ImplV0::setIntParameter(CameraParam /*id*/, int32_t /*value*/, std::vector* /*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& 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& 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& 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 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& 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* 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& hwValue) { hidlStatus = status; *value = hwValue; }); return Utils::buildScopedAStatusFromEvsResult(hidlStatus); } ScopedAStatus AidlCamera::ImplV1::getIntParameter(CameraParam id, std::vector* 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& 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* _aidl_return) { if (!mHidlCamera) { return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE); } (void)mHidlCamera->getParameterList( [_aidl_return](const hidl_vec& 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& buffers, int32_t* _aidl_return) { if (!mHidlCamera) { return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE); } hidl_vec 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& opaqueValue) { if (!mHidlCamera) { return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE); } hidl_vec 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* 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& 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& 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