/* * 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_1 { 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; using hardware::camera2::params::SessionConfiguration; 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() == V2_0::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) { return endConfigure_2_1(operatingMode, sessionParams, systemTime()); } Return HidlCameraDeviceUser::endConfigure_2_1(StreamConfigurationMode operatingMode, const hidl_vec& sessionParams, nsecs_t startTimeNs) { android::CameraMetadata cameraMetadata; if (!convertFromHidl(sessionParams, &cameraMetadata)) { return HStatus::ILLEGAL_ARGUMENT; } std::vector offlineStreamIds; binder::Status ret = mDeviceRemote->endConfigure(convertFromHidl(operatingMode), cameraMetadata, ns2ms(startTimeNs), &offlineStreamIds); 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); } Return HidlCameraDeviceUser::isSessionConfigurationSupported( const HSessionConfiguration& hSessionConfiguration, isSessionConfigurationSupported_cb _hidl_cb) { bool supported = false; SessionConfiguration sessionConfiguration = convertFromHidl(hSessionConfiguration); binder::Status ret = mDeviceRemote->isSessionConfigurationSupported( sessionConfiguration, &supported); HStatus status = B2HStatus(ret); _hidl_cb(status, supported); return Void(); } } // implementation } // V2_0 } // device } // cameraservice } // frameworks } // android