From 0c94727f29ed3702406a34662951bc307bac00d4 Mon Sep 17 00:00:00 2001 From: Jayant Chowdhary Date: Wed, 15 Aug 2018 14:42:04 -0700 Subject: [PATCH] cameraserver: Implement HIDL ICameraDeviceUser and ICameraDeviceCallbacks. Bug: 110364143 Test: (build) mm -j64 Change-Id: I2164b9ffacb3c00404a5a6506a4b6631663ee4c7 Signed-off-by: Jayant Chowdhary --- services/camera/libcameraservice/Android.bp | 5 +- .../hidl/AidlCameraDeviceCallbacks.cpp | 205 ++++++++++++++ .../hidl/AidlCameraDeviceCallbacks.h | 132 +++++++++ .../camera/libcameraservice/hidl/Convert.cpp | 37 +++ .../camera/libcameraservice/hidl/Convert.h | 7 + .../hidl/HidlCameraDeviceUser.cpp | 263 ++++++++++++++++++ .../hidl/HidlCameraDeviceUser.h | 128 +++++++++ .../hidl/HidlCameraService.cpp | 47 +++- 8 files changed, 818 insertions(+), 6 deletions(-) create mode 100644 services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp create mode 100644 services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h create mode 100644 services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp create mode 100644 services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp index c912f634cf..9f2515ebb0 100644 --- a/services/camera/libcameraservice/Android.bp +++ b/services/camera/libcameraservice/Android.bp @@ -53,9 +53,11 @@ cc_library_shared { "device3/DistortionMapper.cpp", "gui/RingBufferConsumer.cpp", "utils/CameraThreadState.cpp", + "hidl/AidlCameraDeviceCallbacks.cpp", "hidl/AidlCameraServiceListener.cpp", - "hidl/HidlCameraService.cpp", "hidl/Convert.cpp", + "hidl/HidlCameraDeviceUser.cpp", + "hidl/HidlCameraService.cpp", "utils/CameraTraces.cpp", "utils/AutoConditionLock.cpp", "utils/TagMonitor.cpp", @@ -82,6 +84,7 @@ cc_library_shared { "libhidltransport", "libjpeg", "libmemunreachable", + "libstagefright_foundation", "android.frameworks.cameraservice.common@2.0", "android.frameworks.cameraservice.service@2.0", "android.frameworks.cameraservice.device@2.0", diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp new file mode 100644 index 0000000000..e5e5024204 --- /dev/null +++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2018 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 + +#include +#include + +namespace android { +namespace frameworks { +namespace cameraservice { +namespace device { +namespace V2_0 { +namespace implementation { + +using hardware::hidl_vec; +using HCaptureResultExtras = android::frameworks::cameraservice::device::V2_0::CaptureResultExtras; +using HPhysicalCaptureResultInfo = android::frameworks::cameraservice::device::V2_0::PhysicalCaptureResultInfo; +using HCameraMetadata = android::frameworks::cameraservice::device::V2_0::CameraMetadata; + +const char *H2BCameraDeviceCallbacks::kResultKey = "CaptureResult"; + +H2BCameraDeviceCallbacks::H2BCameraDeviceCallbacks(const sp& base) : CBase(base) { } + +bool H2BCameraDeviceCallbacks::initializeLooper() { + mCbLooper = new ALooper; + mCbLooper->setName("cs-looper"); + status_t err = mCbLooper->start(/*runOnCallingThread*/ false, /*canCallJava*/ false, + PRIORITY_DEFAULT); + if (err !=OK) { + ALOGE("Unable to start camera device callback looper"); + return false; + } + mHandler = new CallbackHandler(this); + mCbLooper->registerHandler(mHandler); + return true; +} + +H2BCameraDeviceCallbacks::~H2BCameraDeviceCallbacks() { + if (mCbLooper != nullptr) { + if (mHandler != nullptr) { + mCbLooper->unregisterHandler(mHandler->id()); + } + mCbLooper->stop(); + } + mCbLooper.clear(); + mHandler.clear(); +} + +binder::Status H2BCameraDeviceCallbacks::onDeviceError( + int32_t errorCode, const CaptureResultExtras& resultExtras) { + using hardware::cameraservice::utils::conversion::convertToHidl; + HCaptureResultExtras hCaptureResultExtras = convertToHidl(resultExtras); + auto ret = mBase->onDeviceError(convertToHidl(errorCode), hCaptureResultExtras); + if (!ret.isOk()) { + ALOGE("%s OnDeviceError callback failed due to %s",__FUNCTION__, + ret.description().c_str()); + } + return binder::Status::ok(); +} + +binder::Status H2BCameraDeviceCallbacks::onDeviceIdle() { + auto ret = mBase->onDeviceIdle(); + if (!ret.isOk()) { + ALOGE("%s OnDeviceIdle callback failed due to %s",__FUNCTION__, + ret.description().c_str()); + } + return binder::Status::ok(); +} + +binder::Status H2BCameraDeviceCallbacks::onCaptureStarted( + const CaptureResultExtras& resultExtras, int64_t timestamp) { + using hardware::cameraservice::utils::conversion::convertToHidl; + HCaptureResultExtras hCaptureResultExtras = convertToHidl(resultExtras); + auto ret = mBase->onCaptureStarted(hCaptureResultExtras, timestamp); + if (!ret.isOk()) { + ALOGE("%s OnCaptureCallback failed due to %s",__FUNCTION__, + ret.description().c_str()); + } + return binder::Status::ok(); +} + +void H2BCameraDeviceCallbacks::convertResultMetadataToHidl(const camera_metadata_t *rawMetadata, + FmqSizeOrMetadata *hResultMetadata) { + // First try writing to fmq. + size_t metadata_size = get_camera_metadata_size(rawMetadata); + if ((metadata_size > 0) && + (mCaptureResultMetadataQueue->availableToWrite() > 0)) { + if (mCaptureResultMetadataQueue->write((uint8_t *)rawMetadata, metadata_size)) { + hResultMetadata->fmqMetadataSize(metadata_size); + } else { + ALOGW("%s Couldn't use fmq, falling back to hwbinder", __FUNCTION__); + HCameraMetadata metadata; + hardware::cameraservice::utils::conversion::convertToHidl(rawMetadata, &metadata); + hResultMetadata->metadata(std::move(metadata)); + } + } +} + +void H2BCameraDeviceCallbacks::CallbackHandler::onMessageReceived(const sp &msg) { + sp obj = nullptr; + sp resultWrapper = nullptr; + bool found = false; + switch (msg->what()) { + case kWhatResultReceived: + found = msg->findObject(kResultKey, &obj); + if (!found || obj == nullptr) { + ALOGE("Cannot find result object in callback message"); + return; + } + resultWrapper = static_cast(obj.get()); + processResultMessage(resultWrapper); + break; + default: + ALOGE("Unknown callback sent"); + break; + } + return; +} + +void H2BCameraDeviceCallbacks::CallbackHandler::processResultMessage( + sp &resultWrapper) { + sp converter = mConverter.promote(); + if (converter == nullptr) { + ALOGE("Callback wrapper has died, result callback cannot be made"); + return; + } + CameraMetadataNative &result = resultWrapper->mResult; + auto resultExtras = resultWrapper->mResultExtras; + auto &physicalCaptureResultInfos = resultWrapper->mPhysicalCaptureResultInfos; + HCaptureResultExtras hResultExtras = + hardware::cameraservice::utils::conversion::convertToHidl(resultExtras); + hidl_vec hPhysicalCaptureResultInfos = + hardware::cameraservice::utils::conversion::convertToHidl( + physicalCaptureResultInfos, converter->mCaptureResultMetadataQueue); + + // Convert Metadata into HCameraMetadata; + FmqSizeOrMetadata hResult; + const camera_metadata_t *rawMetadata = result.getAndLock(); + converter->convertResultMetadataToHidl(rawMetadata, &hResult); + result.unlock(rawMetadata); + auto ret = converter->mBase->onResultReceived(hResult, hResultExtras, + hPhysicalCaptureResultInfos); + if (!ret.isOk()) { + ALOGE("%s OnResultReceived callback failed due to %s",__FUNCTION__, + ret.description().c_str()); + } +} + +binder::Status H2BCameraDeviceCallbacks::onResultReceived( + const CameraMetadataNative& result, + const CaptureResultExtras& resultExtras, + const ::std::vector& physicalCaptureResultInfos) { + // Wrap CameraMetadata, resultExtras and physicalCaptureResultInfos in on + // sp-able structure and post it. + sp resultWrapper = new ResultWrapper(const_cast(result), + resultExtras, physicalCaptureResultInfos); + sp msg = new AMessage(kWhatResultReceived, mHandler); + msg->setObject(kResultKey, resultWrapper); + msg->post(); + return binder::Status::ok(); +} + +binder::Status H2BCameraDeviceCallbacks::onPrepared(int32_t streamId) { + // not implemented + // To silence Wunused-parameter. + (void) streamId; + return binder::Status::ok(); +} + +binder::Status H2BCameraDeviceCallbacks::onRepeatingRequestError( + int64_t lastFrameNumber, + int32_t repeatingRequestId) { + auto ret = + mBase->onRepeatingRequestError(lastFrameNumber, repeatingRequestId); + if (!ret.isOk()) { + ALOGE("%s OnRepeatingRequestEror callback failed due to %s",__FUNCTION__, + ret.description().c_str()); + } + return binder::Status::ok(); +} + +binder::Status H2BCameraDeviceCallbacks::onRequestQueueEmpty() { + // not implemented + return binder::Status::ok(); +} + +} // implementation +} // V2_0 +} // device +} // cameraservice +} // frameworks +} // android diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h new file mode 100644 index 0000000000..dbf520a0eb --- /dev/null +++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2018 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. + */ + +#ifndef ANDROID_FRAMEWORKS_AIDL_CAMERADEVICECALLBACKS_H +#define ANDROID_FRAMEWORKS_AIDL_CAMERADEVICECALLBACKS_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace frameworks { +namespace cameraservice { +namespace device { +namespace V2_0 { +namespace implementation { + +using camerahybrid::H2BConverter; +using HCameraDeviceCallback = cameraservice::device::V2_0::ICameraDeviceCallback; +using HPhysicalCaptureResultInfo = cameraservice::device::V2_0::PhysicalCaptureResultInfo; +using android::frameworks::cameraservice::device::V2_0::FmqSizeOrMetadata; + +using hardware::camera2::BnCameraDeviceCallbacks; +using hardware::camera2::ICameraDeviceCallbacks; +using hardware::camera2::impl::CaptureResultExtras; +using hardware::camera2::impl::CameraMetadataNative; +using hardware::camera2::impl::PhysicalCaptureResultInfo; +using hardware::kSynchronizedReadWrite; +using hardware::MessageQueue; +using CaptureResultMetadataQueue = MessageQueue; + +struct H2BCameraDeviceCallbacks : + public H2BConverter { + H2BCameraDeviceCallbacks(const sp& base); + + ~H2BCameraDeviceCallbacks(); + + bool initializeLooper(); + + virtual binder::Status onDeviceError(int32_t errorCode, + const CaptureResultExtras& resultExtras) override; + + virtual binder::Status onDeviceIdle() override; + + virtual binder::Status onCaptureStarted(const CaptureResultExtras& resultExtras, + int64_t timestamp) override; + + virtual binder::Status onResultReceived( + const CameraMetadataNative& result, const CaptureResultExtras& resultExtras, + const std::vector& physicalCaptureResultInfos) override; + + virtual binder::Status onPrepared(int32_t streamId) override; + + virtual binder::Status onRepeatingRequestError(int64_t lastFrameNumber, + int32_t repeatingRequestId) override; + + virtual binder::Status onRequestQueueEmpty() override; + + void setCaptureResultMetadataQueue(std::shared_ptr metadataQueue) { + mCaptureResultMetadataQueue = metadataQueue; + } + + private: + // Wrapper struct so that parameters to onResultReceived callback may be + // sent through an AMessage. + struct ResultWrapper : public RefBase { + CameraMetadataNative mResult; + CaptureResultExtras mResultExtras; + std::vector mPhysicalCaptureResultInfos; + ResultWrapper(CameraMetadataNative &result, + const CaptureResultExtras resultExtras, + const std::vector &physicalCaptureResultInfos) : + // TODO: make this std::movable + mResult(result), mResultExtras(resultExtras), mPhysicalCaptureResultInfos(physicalCaptureResultInfos) { } + }; + + struct CallbackHandler : public AHandler { + public: + void onMessageReceived(const sp &msg) override; + CallbackHandler(H2BCameraDeviceCallbacks *converter) : mConverter(converter) { } + private: + void processResultMessage(sp &resultWrapper); + wp mConverter = nullptr; + Mutex mMetadataQueueLock; + }; + + void convertResultMetadataToHidl(const camera_metadata *rawMetadata, + FmqSizeOrMetadata *resultMetadata); + enum { + kWhatResultReceived, + }; + + static const char *kResultKey; + + std::shared_ptr mCaptureResultMetadataQueue = nullptr; + sp mHandler = nullptr; + sp mCbLooper = nullptr; +}; + +} // implementation +} // V2_0 +} // device +} // cameraservice +} // frameworks +} // android +#endif // ANDROID_FRAMEWORKS_AIDL_CAMERADEVICECALLBACKS_H diff --git a/services/camera/libcameraservice/hidl/Convert.cpp b/services/camera/libcameraservice/hidl/Convert.cpp index 53097c31be..22e879e69a 100644 --- a/services/camera/libcameraservice/hidl/Convert.cpp +++ b/services/camera/libcameraservice/hidl/Convert.cpp @@ -220,6 +220,43 @@ HStatus B2HStatus(const binder::Status &bStatus) { return status; } +HPhysicalCaptureResultInfo convertToHidl( + const PhysicalCaptureResultInfo &physicalCaptureResultInfo, + std::shared_ptr &captureResultMetadataQueue) { + HPhysicalCaptureResultInfo hPhysicalCaptureResultInfo; + hPhysicalCaptureResultInfo.physicalCameraId = + String8(physicalCaptureResultInfo.mPhysicalCameraId).string(); + const camera_metadata_t *rawMetadata = + physicalCaptureResultInfo.mPhysicalCameraMetadata.getAndLock(); + // Try using fmq at first. + size_t metadata_size = get_camera_metadata_size(rawMetadata); + if ((metadata_size > 0) && (captureResultMetadataQueue->availableToWrite() > 0)) { + if (captureResultMetadataQueue->write((uint8_t *)rawMetadata, metadata_size)) { + hPhysicalCaptureResultInfo.physicalCameraMetadata.fmqMetadataSize(metadata_size); + } else { + ALOGW("%s Couldn't use fmq, falling back to hwbinder", __FUNCTION__); + HCameraMetadata metadata; + convertToHidl(rawMetadata, &metadata); + hPhysicalCaptureResultInfo.physicalCameraMetadata.metadata(std::move(metadata)); + } + } + physicalCaptureResultInfo.mPhysicalCameraMetadata.unlock(rawMetadata); + return hPhysicalCaptureResultInfo; +} + +hidl_vec convertToHidl( + const std::vector &physicalCaptureResultInfos, + std::shared_ptr &captureResultMetadataQueue) { + hidl_vec hPhysicalCaptureResultInfos; + hPhysicalCaptureResultInfos.resize(physicalCaptureResultInfos.size()); + size_t i = 0; + for (auto &physicalCaptureResultInfo : physicalCaptureResultInfos) { + hPhysicalCaptureResultInfos[i++] = convertToHidl(physicalCaptureResultInfo, + captureResultMetadataQueue); + } + return hPhysicalCaptureResultInfos; +} + } //conversion } // utils } //cameraservice diff --git a/services/camera/libcameraservice/hidl/Convert.h b/services/camera/libcameraservice/hidl/Convert.h index ba2849ea55..82937a30d6 100644 --- a/services/camera/libcameraservice/hidl/Convert.h +++ b/services/camera/libcameraservice/hidl/Convert.h @@ -28,7 +28,9 @@ #include #include #include +#include #include +#include namespace android { namespace hardware { @@ -39,6 +41,7 @@ namespace conversion { using hardware::camera2::impl::CaptureResultExtras; using hardware::camera2::impl::PhysicalCaptureResultInfo; +using CaptureResultMetadataQueue = MessageQueue; using HCameraMetadata = frameworks::cameraservice::service::V2_0::CameraMetadata; using HCameraDeviceStatus = frameworks::cameraservice::service::V2_0::CameraDeviceStatus; using HCameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId; @@ -79,6 +82,10 @@ HErrorCode convertToHidl(int32_t errorCode); HCaptureResultExtras convertToHidl(const CaptureResultExtras &captureResultExtras); +hidl_vec convertToHidl( + const std::vector &physicalCaptureResultInfos, + std::shared_ptr &captureResultMetadataQueue); + HStatus B2HStatus(const binder::Status &bStatus); } // conversion diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp new file mode 100644 index 0000000000..d22ba5aa61 --- /dev/null +++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2018 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 +#include +#include +#include + +#include +#include +#include +#include + +namespace android { +namespace frameworks { +namespace cameraservice { +namespace device { +namespace V2_0 { +namespace implementation { + +using hardware::cameraservice::utils::conversion::convertToHidl; +using hardware::cameraservice::utils::conversion::convertFromHidl; +using hardware::cameraservice::utils::conversion::B2HStatus; + +using hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer; +using hardware::hidl_vec; +using hardware::Return; +using hardware::Void; +using HSubmitInfo = device::V2_0::SubmitInfo; +using hardware::camera2::params::OutputConfiguration; + +static constexpr int32_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */; +static constexpr int32_t CAMERA_RESULT_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */; + +Return HidlCameraDeviceUser::disconnect() { + mDeviceRemote->disconnect(); + return Void(); +} + +HidlCameraDeviceUser::HidlCameraDeviceUser( + const sp &deviceRemote) + : mDeviceRemote(deviceRemote) { + mInitSuccess = initDevice(); +} + +bool HidlCameraDeviceUser::initDevice() { + // TODO: Get request and result metadata queue size from a system property. + int32_t reqFMQSize = CAMERA_REQUEST_METADATA_QUEUE_SIZE; + + mCaptureRequestMetadataQueue = + std::make_unique(static_cast(reqFMQSize), + false /* non blocking */); + if (!mCaptureRequestMetadataQueue->isValid()) { + ALOGE("%s: invalid request fmq", __FUNCTION__); + return false; + } + + int32_t resFMQSize = CAMERA_RESULT_METADATA_QUEUE_SIZE; + mCaptureResultMetadataQueue = + std::make_shared(static_cast(resFMQSize), + false /* non blocking */); + if (!mCaptureResultMetadataQueue->isValid()) { + ALOGE("%s: invalid result fmq", __FUNCTION__); + return false; + } + return true; +} + +Return HidlCameraDeviceUser::getCaptureRequestMetadataQueue( + getCaptureRequestMetadataQueue_cb _hidl_cb) { + if (mInitSuccess) { + _hidl_cb(*mCaptureRequestMetadataQueue->getDesc()); + } + return Void(); +} + +Return HidlCameraDeviceUser::getCaptureResultMetadataQueue( + getCaptureResultMetadataQueue_cb _hidl_cb) { + if (mInitSuccess) { + _hidl_cb(*mCaptureResultMetadataQueue->getDesc()); + } + return Void(); +} + +/** + * To be used only by submitRequestList implementation, since it requires + * clients to call this method serially, incase fmq is used to send metadata. + */ +bool HidlCameraDeviceUser::copyPhysicalCameraSettings( + const hidl_vec &hPhysicalCameraSettings, + std::vector *physicalCameraSettings) { + bool converted = false; + for (auto &e : hPhysicalCameraSettings) { + physicalCameraSettings->emplace_back(); + CaptureRequest::PhysicalCameraSettings &physicalCameraSetting = + physicalCameraSettings->back(); + physicalCameraSetting.id = e.id.c_str(); + + // Read the settings either from the fmq or straightaway from the + // request. We don't need any synchronization, since submitRequestList + // is guaranteed to be called serially by the client if it decides to + // use fmq. + if (e.settings.getDiscriminator() == + FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) { + /** + * Get settings from the fmq. + */ + HCameraMetadata settingsFmq; + settingsFmq.resize(e.settings.fmqMetadataSize()); + bool read = mCaptureRequestMetadataQueue->read(settingsFmq.data(), + e.settings.fmqMetadataSize()); + if (!read) { + ALOGE("%s capture request settings could't be read from fmq size", + __FUNCTION__); + converted = false; + } else { + converted = convertFromHidl(settingsFmq, &physicalCameraSetting.settings); + } + } else { + /** + * The settings metadata is contained in request settings field. + */ + converted = + convertFromHidl(e.settings.metadata(), + &physicalCameraSetting.settings); + } + if (!converted) { + ALOGE("%s: Unable to convert physicalCameraSettings from HIDL to AIDL.", __FUNCTION__); + return false; + } + } + return true; +} + +bool HidlCameraDeviceUser::convertRequestFromHidl(const HCaptureRequest &hRequest, + CaptureRequest *request) { + // No reprocessing support. + request->mIsReprocess = false; + for (const auto &streamAndWindowId : hRequest.streamAndWindowIds) { + request->mStreamIdxList.push_back(streamAndWindowId.streamId); + request->mSurfaceIdxList.push_back(streamAndWindowId.windowId); + } + return copyPhysicalCameraSettings(hRequest.physicalCameraSettings, + &(request->mPhysicalCameraSettings)); +} + +Return HidlCameraDeviceUser::submitRequestList(const hidl_vec& hRequestList, + bool streaming, + submitRequestList_cb _hidl_cb) { + hardware::camera2::utils::SubmitInfo submitInfo; + HSubmitInfo hSubmitInfo; + /** + * Create AIDL CaptureRequest from requestList and graphicBufferProducers. + */ + std::vector requests; + for (auto &hRequest : hRequestList) { + requests.emplace_back(); + auto &request = requests.back(); + if (!convertRequestFromHidl(hRequest, &request)) { + _hidl_cb(HStatus::ILLEGAL_ARGUMENT, hSubmitInfo); + return Void(); + } + } + mDeviceRemote->submitRequestList(requests, streaming, &submitInfo); + mRequestId = submitInfo.mRequestId; + convertToHidl(submitInfo, &hSubmitInfo); + _hidl_cb(HStatus::NO_ERROR, hSubmitInfo); + return Void(); +} + +Return HidlCameraDeviceUser::cancelRepeatingRequest(cancelRepeatingRequest_cb _hidl_cb) { + int64_t lastFrameNumber = 0; + binder::Status ret = mDeviceRemote->cancelRequest(mRequestId, &lastFrameNumber); + _hidl_cb(B2HStatus(ret), lastFrameNumber); + return Void(); +} + +Return HidlCameraDeviceUser::beginConfigure() { + binder::Status ret = mDeviceRemote->beginConfigure(); + return B2HStatus(ret); +} + +Return HidlCameraDeviceUser::endConfigure(StreamConfigurationMode operatingMode, + const hidl_vec& sessionParams) { + android::CameraMetadata cameraMetadata; + if (!convertFromHidl(sessionParams, &cameraMetadata)) { + return HStatus::ILLEGAL_ARGUMENT; + } + + binder::Status ret = mDeviceRemote->endConfigure(convertFromHidl(operatingMode), + cameraMetadata); + return B2HStatus(ret); +} + +Return HidlCameraDeviceUser::deleteStream(int32_t streamId) { + binder::Status ret = mDeviceRemote->deleteStream(streamId); + return B2HStatus(ret); +} + +Return HidlCameraDeviceUser::createStream(const HOutputConfiguration& hOutputConfiguration, + createStream_cb hidl_cb_) { + OutputConfiguration outputConfiguration = + convertFromHidl(hOutputConfiguration); + int32_t newStreamId = 0; + binder::Status ret = mDeviceRemote->createStream(outputConfiguration, &newStreamId); + HStatus status = B2HStatus(ret); + hidl_cb_(status, newStreamId); + return Void(); +} + +Return HidlCameraDeviceUser::createDefaultRequest(TemplateId templateId, + createDefaultRequest_cb _hidl_cb) { + android::CameraMetadata cameraMetadata; + binder::Status ret = mDeviceRemote->createDefaultRequest(convertFromHidl(templateId), + &cameraMetadata); + HStatus hStatus = B2HStatus(ret); + HCameraMetadata hidlMetadata; + const camera_metadata_t *rawMetadata = cameraMetadata.getAndLock(); + convertToHidl(rawMetadata, &hidlMetadata); + _hidl_cb(hStatus, hidlMetadata); + cameraMetadata.unlock(rawMetadata); + return Void(); +} + +Return HidlCameraDeviceUser::waitUntilIdle() { + binder::Status ret = mDeviceRemote->waitUntilIdle(); + return B2HStatus(ret); +} + +Return HidlCameraDeviceUser::flush(flush_cb _hidl_cb) { + int64_t lastFrameNumber = 0; + binder::Status ret = mDeviceRemote->flush(&lastFrameNumber); + _hidl_cb(B2HStatus(ret),lastFrameNumber); + return Void(); +} + +Return HidlCameraDeviceUser::updateOutputConfiguration( + int32_t streamId, + const HOutputConfiguration& hOutputConfiguration) { + OutputConfiguration outputConfiguration = convertFromHidl(hOutputConfiguration); + binder::Status ret = mDeviceRemote->updateOutputConfiguration(streamId, outputConfiguration); + return B2HStatus(ret); +} + +} // implementation +} // V2_0 +} // device +} // cameraservice +} // frameworks +} // android diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h new file mode 100644 index 0000000000..be8f1d63c5 --- /dev/null +++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2018 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. + */ + +#ifndef ANDROID_FRAMEWORKS_CAMERADEVICEUSER_V2_0_CAMERADEVICEUSER_H +#define ANDROID_FRAMEWORKS_CAMERADEVICEUSER_V2_0_CAMERADEVICEUSER_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace android { +namespace frameworks { +namespace cameraservice { +namespace device { +namespace V2_0 { +namespace implementation { + +using frameworks::cameraservice::device::V2_0::StreamConfigurationMode; +using hardware::camera2::CaptureRequest; +using hardware::hidl_vec; +using hardware::kSynchronizedReadWrite; +using hardware::MessageQueue; +using hardware::MQDescriptorSync; +using hardware::Return; +using CaptureResultMetadataQueue = MessageQueue; +using CaptureRequestMetadataQueue = MessageQueue; +using TemplateId = frameworks::cameraservice::device::V2_0::TemplateId; + +using HCameraDeviceUser = device::V2_0::ICameraDeviceUser; +using HCameraMetadata = cameraservice::service::V2_0::CameraMetadata; +using HCaptureRequest = device::V2_0::CaptureRequest; +using HOutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration; +using HPhysicalCameraSettings = frameworks::cameraservice::device::V2_0::PhysicalCameraSettings; +using HStatus = frameworks::cameraservice::common::V2_0::Status; + +static constexpr int32_t REQUEST_ID_NONE = -1; + +struct HidlCameraDeviceUser final : public HCameraDeviceUser { + HidlCameraDeviceUser(const sp &deviceRemote); + + ~HidlCameraDeviceUser() { } + + virtual Return disconnect() override; + + virtual Return getCaptureRequestMetadataQueue( + getCaptureRequestMetadataQueue_cb _hidl_cb) override; + + virtual Return getCaptureResultMetadataQueue( + getCaptureResultMetadataQueue_cb _hidl_cb) override; + + virtual Return submitRequestList(const hidl_vec& requestList, + bool streaming, submitRequestList_cb _hidl_cb) override; + + virtual Return cancelRepeatingRequest(cancelRepeatingRequest_cb _hidl_cb) override; + + virtual Return beginConfigure() override; + + virtual Return endConfigure(StreamConfigurationMode operatingMode, + const hidl_vec& sessionParams); + + virtual Return deleteStream(int32_t streamId) override; + + virtual Return createStream(const HOutputConfiguration& outputConfiguration, + createStream_cb _hidl_cb) override; + + Return createDefaultRequest(TemplateId templateId, + createDefaultRequest_cb _hidl_cb) override; + + virtual Return waitUntilIdle() override; + + virtual Return flush(flush_cb _hidl_cb) override; + + virtual Return updateOutputConfiguration( + int32_t streamId, const HOutputConfiguration& outputConfiguration) override; + + bool initStatus() { return mInitSuccess; } + + std::shared_ptr getCaptureResultMetadataQueue() { + return mCaptureResultMetadataQueue; + } + + private: + bool initDevice(); + + bool convertRequestFromHidl(const HCaptureRequest &hRequest, CaptureRequest *request); + + bool copyPhysicalCameraSettings( + const hidl_vec &hPhysicalCameraSettings, + std::vector *physicalCameraSettings); + + const sp mDeviceRemote; + std::unique_ptr mCaptureRequestMetadataQueue = nullptr; + std::shared_ptr mCaptureResultMetadataQueue = nullptr; + bool mInitSuccess = false; + int32_t mRequestId = REQUEST_ID_NONE; +}; + +} // implementation +} // V2_0 +} // device +} // cameraservice +} // frameworks +} // android +#endif // ANDROID_FRAMEOWORKS_CAMERADEVICEUSER_V2_0_CAMERADEVICEUSER_H diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp index f34f903bb2..31bdf6de20 100644 --- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp +++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp @@ -17,6 +17,9 @@ #include #include + +#include +#include #include #include @@ -34,6 +37,8 @@ using hardware::cameraservice::utils::conversion::convertToHidl; using hardware::cameraservice::utils::conversion::B2HStatus; using hardware::Void; +using device::V2_0::implementation::H2BCameraDeviceCallbacks; +using device::V2_0::implementation::HidlCameraDeviceUser; using service::V2_0::implementation::H2BCameraServiceListener; using HCameraMetadataType = android::frameworks::cameraservice::common::V2_0::CameraMetadataType; using HVendorTag = android::frameworks::cameraservice::common::V2_0::VendorTag; @@ -79,11 +84,43 @@ HidlCameraService::getCameraCharacteristics(const hidl_string& cameraId, Return HidlCameraService::connectDevice(const sp& hCallback, const hidl_string& cameraId, connectDevice_cb _hidl_cb) { - // To silence Wunused-parameter. - (void)hCallback; - (void)cameraId; - (void)_hidl_cb; - + // Here, we first get ICameraDeviceUser from mAidlICameraService, then save + // that interface in the newly created HidlCameraDeviceUser impl class. + if (mAidlICameraService == nullptr) { + _hidl_cb(HStatus::UNKNOWN_ERROR, nullptr); + return Void(); + } + sp deviceRemote = nullptr; + // Create a hardware::camera2::ICameraDeviceCallback object which internally + // calls callback functions passed through hCallback. + sp hybridCallbacks = new H2BCameraDeviceCallbacks(hCallback); + if (!hybridCallbacks->initializeLooper()) { + ALOGE("Unable to handle callbacks on device, cannot connect"); + _hidl_cb(HStatus::UNKNOWN_ERROR, nullptr); + return Void(); + } + sp callbacks = hybridCallbacks; + binder::Status serviceRet = mAidlICameraService->connectDevice( + callbacks, String16(cameraId.c_str()), String16(""), + hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote); + HStatus status = HStatus::NO_ERROR; + if (!serviceRet.isOk()) { + ALOGE("%s: Unable to connect to camera device", __FUNCTION__); + status = B2HStatus(serviceRet); + _hidl_cb(status, nullptr); + return Void(); + } + // Now we create a HidlCameraDeviceUser class, store the deviceRemote in it, + // and return that back. All calls on that interface will be forwarded to + // the AIDL interface. + sp hDeviceRemote = new HidlCameraDeviceUser(deviceRemote); + if (!hDeviceRemote->initStatus()) { + ALOGE("%s: Unable to initialize camera device HIDL wrapper", __FUNCTION__); + _hidl_cb(HStatus::UNKNOWN_ERROR, nullptr); + return Void(); + } + hybridCallbacks->setCaptureResultMetadataQueue(hDeviceRemote->getCaptureResultMetadataQueue()); + _hidl_cb(status, hDeviceRemote); return Void(); }