/* * 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 "Hidl-Camera3-OffLnSsn" #define ATRACE_TAG ATRACE_TAG_CAMERA //#define LOG_NDEBUG 0 #include #include #include #include "device3/hidl/HidlCamera3OfflineSession.h" #include "device3/Camera3OutputStream.h" #include "device3/hidl/HidlCamera3OutputUtils.h" #include "device3/Camera3InputStream.h" #include "device3/Camera3SharedOutputStream.h" #include "utils/CameraTraces.h" using namespace android::camera3; using namespace android::hardware::camera; namespace android { HidlCamera3OfflineSession::~HidlCamera3OfflineSession() { ATRACE_CALL(); ALOGV("%s: Tearing down hidl offline session for camera id %s", __FUNCTION__, mId.string()); HidlCamera3OfflineSession::disconnectSession(); } status_t HidlCamera3OfflineSession::initialize(wp listener) { ATRACE_CALL(); if (mSession == nullptr) { ALOGE("%s: HIDL session is null!", __FUNCTION__); return DEAD_OBJECT; } { std::lock_guard lock(mLock); mListener = listener; // setup result FMQ std::unique_ptr& resQueue = mResultMetadataQueue; auto resultQueueRet = mSession->getCaptureResultMetadataQueue( [&resQueue](const auto& descriptor) { resQueue = std::make_unique(descriptor); if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) { ALOGE("HAL returns empty result metadata fmq, not use it"); resQueue = nullptr; // Don't use resQueue onwards. } }); if (!resultQueueRet.isOk()) { ALOGE("Transaction error when getting result metadata queue from camera session: %s", resultQueueRet.description().c_str()); return DEAD_OBJECT; } mStatus = STATUS_ACTIVE; } mSession->setCallback(this); return OK; } hardware::Return HidlCamera3OfflineSession::processCaptureResult_3_4( const hardware::hidl_vec< hardware::camera::device::V3_4::CaptureResult>& results) { sp listener; { std::lock_guard lock(mLock); if (mStatus != STATUS_ACTIVE) { ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus); return hardware::Void(); } listener = mListener.promote(); } std::string activePhysicalId(""); HidlCaptureOutputStates states { {mId, mOfflineReqsLock, mLastCompletedRegularFrameNumber, mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber, mOfflineReqs, mOutputLock, mResultQueue, mResultSignal, mNextShutterFrameNumber, mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber, mNextResultFrameNumber, mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber, mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags, mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers, mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this, mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration, mIsFixedFps, /*overrideToPortrait*/false, activePhysicalId}, mResultMetadataQueue }; std::lock_guard lock(mProcessCaptureResultLock); for (const auto& result : results) { processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata); } return hardware::Void(); } hardware::Return HidlCamera3OfflineSession::processCaptureResult( const hardware::hidl_vec< hardware::camera::device::V3_2::CaptureResult>& results) { // TODO: changed impl to call into processCaptureResult_3_4 instead? // might need to figure how to reduce copy though. sp listener; { std::lock_guard lock(mLock); if (mStatus != STATUS_ACTIVE) { ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus); return hardware::Void(); } listener = mListener.promote(); } hardware::hidl_vec noPhysMetadata; std::string activePhysicalId(""); HidlCaptureOutputStates states { {mId, mOfflineReqsLock, mLastCompletedRegularFrameNumber, mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber, mOfflineReqs, mOutputLock, mResultQueue, mResultSignal, mNextShutterFrameNumber, mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber, mNextResultFrameNumber, mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber, mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags, mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers, mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this, mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration, mIsFixedFps, /*overrideToPortrait*/false, activePhysicalId}, mResultMetadataQueue }; std::lock_guard lock(mProcessCaptureResultLock); for (const auto& result : results) { processOneCaptureResultLocked(states, result, noPhysMetadata); } return hardware::Void(); } hardware::Return HidlCamera3OfflineSession::notify( const hardware::hidl_vec& msgs) { sp listener; { std::lock_guard lock(mLock); if (mStatus != STATUS_ACTIVE) { ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus); return hardware::Void(); } listener = mListener.promote(); } std::string activePhysicalId(""); HidlCaptureOutputStates states { {mId, mOfflineReqsLock, mLastCompletedRegularFrameNumber, mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber, mOfflineReqs, mOutputLock, mResultQueue, mResultSignal, mNextShutterFrameNumber, mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber, mNextResultFrameNumber, mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber, mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags, mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers, mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this, mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration, mIsFixedFps, /*overrideToPortrait*/false, activePhysicalId}, mResultMetadataQueue }; for (const auto& msg : msgs) { camera3::notify(states, msg); } return hardware::Void(); } hardware::Return HidlCamera3OfflineSession::requestStreamBuffers( const hardware::hidl_vec& bufReqs, requestStreamBuffers_cb _hidl_cb) { { std::lock_guard lock(mLock); if (mStatus != STATUS_ACTIVE) { ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus); return hardware::Void(); } } RequestBufferStates states { mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder, *this, mBufferRecords, *this}; camera3::requestStreamBuffers(states, bufReqs, _hidl_cb); return hardware::Void(); } hardware::Return HidlCamera3OfflineSession::returnStreamBuffers( const hardware::hidl_vec& buffers) { { std::lock_guard lock(mLock); if (mStatus != STATUS_ACTIVE) { ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus); return hardware::Void(); } } ReturnBufferStates states { mId, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder, mBufferRecords}; camera3::returnStreamBuffers(states, buffers); return hardware::Void(); } void HidlCamera3OfflineSession::disconnectSession() { // TODO: Make sure this locking is correct. std::lock_guard lock(mLock); if (mSession != nullptr) { mSession->close(); } mSession.clear(); } }; // namespace android