/* * 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. */ #define LOG_TAG "AidlCameraDeviceCallbacks" #include #include #include #include #include namespace android::frameworks::cameraservice::device::implementation { // VNDK classes using SCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata; using SCaptureResultExtras = ::aidl::android::frameworks::cameraservice::device::CaptureResultExtras; using SPhysicalCaptureResultInfo = ::aidl::android::frameworks::cameraservice::device::PhysicalCaptureResultInfo; using SStatus = ::aidl::android::frameworks::cameraservice::common::Status; // NDK classes using UCaptureResultExtras = ::android::hardware::camera2::impl::CaptureResultExtras; using UPhysicalCaptureResultInfo = ::android::hardware::camera2::impl::PhysicalCaptureResultInfo; using ::android::hardware::cameraservice::utils::conversion::aidl::convertToAidl; using ::android::hardware::cameraservice::utils::conversion::aidl::filterVndkKeys; const char *AidlCameraDeviceCallbacks::kResultKey = "CaptureResult"; bool AidlCameraDeviceCallbacks::initializeLooper(int vndkVersion) { 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, vndkVersion); mCbLooper->registerHandler(mHandler); return true; } AidlCameraDeviceCallbacks::AidlCameraDeviceCallbacks( const std::shared_ptr& base): mBase(base), mDeathPipe(this, base->asBinder()) {} AidlCameraDeviceCallbacks::~AidlCameraDeviceCallbacks() { if (mCbLooper != nullptr) { if (mHandler != nullptr) { mCbLooper->unregisterHandler(mHandler->id()); } mCbLooper->stop(); } mCbLooper.clear(); mHandler.clear(); } binder::Status AidlCameraDeviceCallbacks::onDeviceError( int32_t errorCode, const CaptureResultExtras& resultExtras) { using hardware::cameraservice::utils::conversion::aidl::convertToAidl; SCaptureResultExtras cre = convertToAidl(resultExtras); auto ret = mBase->onDeviceError(convertToAidl(errorCode), cre); LOG_STATUS_ERROR_IF_NOT_OK(ret, "onDeviceError") return binder::Status::ok(); } binder::Status AidlCameraDeviceCallbacks::onClientSharedAccessPriorityChanged(bool primaryClient) { if (!flags::camera_multi_client()) { return binder::Status::ok(); } auto ret = mBase->onClientSharedAccessPriorityChanged(primaryClient); LOG_STATUS_ERROR_IF_NOT_OK(ret, "onClientSharedAccessPriorityChanged") return binder::Status::ok(); } binder::Status AidlCameraDeviceCallbacks::onDeviceIdle() { auto ret = mBase->onDeviceIdle(); LOG_STATUS_ERROR_IF_NOT_OK(ret, "onDeviceIdle") return binder::Status::ok(); } binder::Status AidlCameraDeviceCallbacks::onCaptureStarted( const CaptureResultExtras& resultExtras, int64_t timestamp) { using hardware::cameraservice::utils::conversion::aidl::convertToAidl; SCaptureResultExtras hCaptureResultExtras = convertToAidl(resultExtras); auto ret = mBase->onCaptureStarted(hCaptureResultExtras, timestamp); LOG_STATUS_ERROR_IF_NOT_OK(ret, "onCaptureStarted") return binder::Status::ok(); } void AidlCameraDeviceCallbacks::convertResultMetadataToAidl(const camera_metadata_t* src, SCaptureMetadataInfo* dst) { // First try writing to fmq. size_t metadata_size = get_camera_metadata_size(src); if ((metadata_size > 0) && (mCaptureResultMetadataQueue->availableToWrite() > 0)) { if (mCaptureResultMetadataQueue->write((int8_t *)src, metadata_size)) { dst->set(metadata_size); } else { ALOGW("%s Couldn't use fmq, falling back to hwbinder", __FUNCTION__); SCameraMetadata metadata; hardware::cameraservice::utils::conversion::aidl::cloneToAidl(src, &metadata); dst->set(std::move(metadata)); } } } void AidlCameraDeviceCallbacks::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; } } void AidlCameraDeviceCallbacks::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; SCaptureResultExtras convResultExtras = hardware::cameraservice::utils::conversion::aidl::convertToAidl(resultExtras); // Convert Metadata into HCameraMetadata; SCaptureMetadataInfo captureMetadataInfo; if (filterVndkKeys(mVndkVersion, result, /*isStatic*/false) != OK) { ALOGE("%s: filtering vndk keys from result failed, not sending onResultReceived callback", __FUNCTION__); return; } const camera_metadata_t *rawMetadata = result.getAndLock(); converter->convertResultMetadataToAidl(rawMetadata, &captureMetadataInfo); result.unlock(rawMetadata); auto &physicalCaptureResultInfos = resultWrapper->mPhysicalCaptureResultInfos; std::vector stableCaptureResInfo = convertToAidl(physicalCaptureResultInfos, converter->mCaptureResultMetadataQueue); auto ret = converter->mBase->onResultReceived(captureMetadataInfo, convResultExtras, stableCaptureResInfo); LOG_STATUS_ERROR_IF_NOT_OK(ret, "OnResultReceived") } binder::Status AidlCameraDeviceCallbacks::onResultReceived( const CameraMetadataInfo &resultInfo, const UCaptureResultExtras& resultExtras, const ::std::vector& physicalCaptureResultInfos) { // Wrap CameraMetadata, resultExtras and physicalCaptureResultInfos in on // sp-able structure and post it. // We modify metadata - since we want to filter out tags based on the vndk // version, and also this communication is an in process function call. // So we don't use FMQ for the shim layer. FMQ is still used for VNDK IPC. if (resultInfo.getTag() != CameraMetadataInfo::metadata) { ALOGE("Vendor callbacks got metadata in fmq ? "); return binder::Status::ok(); } const CameraMetadataNative &result = resultInfo.get(); 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 AidlCameraDeviceCallbacks::onPrepared(int32_t streamId) { auto ret = mBase->onPrepared(streamId); LOG_STATUS_ERROR_IF_NOT_OK(ret, "onPrepared") return binder::Status::ok(); } binder::Status AidlCameraDeviceCallbacks::onRepeatingRequestError( int64_t lastFrameNumber, int32_t repeatingRequestId) { auto ret = mBase->onRepeatingRequestError(lastFrameNumber, repeatingRequestId); LOG_STATUS_ERROR_IF_NOT_OK(ret, "onRepeatingRequestError") return binder::Status::ok(); } binder::Status AidlCameraDeviceCallbacks::onRequestQueueEmpty() { // not implemented return binder::Status::ok(); } status_t AidlCameraDeviceCallbacks::linkToDeath(const sp& recipient, void* cookie, uint32_t flags) { return mDeathPipe.linkToDeath(recipient, cookie, flags); } status_t AidlCameraDeviceCallbacks::unlinkToDeath(const wp& recipient, void* cookie, uint32_t flags, wp* outRecipient) { return mDeathPipe.unlinkToDeath(recipient, cookie, flags, outRecipient); } } // namespace android::frameworks::cameraservice::device::implementation