| /* |
| * 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 |