/* * Copyright (C) 2016 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_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H #define ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H #include #include #include #include #include #include #include #include #include #include "CameraMetadata.h" #include "HandleImporter.h" #include "hardware/camera3.h" #include "hardware/camera_common.h" #include "utils/Mutex.h" namespace android { namespace hardware { namespace camera { namespace device { namespace V3_2 { namespace implementation { using ::android::hardware::camera::device::V3_2::CaptureRequest; using ::android::hardware::camera::device::V3_2::HalStreamConfiguration; using ::android::hardware::camera::device::V3_2::StreamConfiguration; using ::android::hardware::camera::device::V3_2::ICameraDeviceSession; using ::android::hardware::camera::common::V1_0::Status; using ::android::hardware::camera::common::V1_0::helper::HandleImporter; using ::android::hardware::kSynchronizedReadWrite; using ::android::hardware::MessageQueue; using ::android::hardware::MQDescriptorSync; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::hardware::hidl_vec; using ::android::hardware::hidl_string; using ::android::sp; using ::android::Mutex; struct Camera3Stream; /** * Function pointer types with C calling convention to * use for HAL callback functions. */ extern "C" { typedef void (callbacks_process_capture_result_t)( const struct camera3_callback_ops *, const camera3_capture_result_t *); typedef void (callbacks_notify_t)( const struct camera3_callback_ops *, const camera3_notify_msg_t *); } struct CameraDeviceSession : public virtual RefBase, protected camera3_callback_ops { CameraDeviceSession(camera3_device_t*, const camera_metadata_t* deviceInfo, const sp&); virtual ~CameraDeviceSession(); // Call by CameraDevice to dump active device states void dumpState(const native_handle_t* fd); // Caller must use this method to check if CameraDeviceSession ctor failed bool isInitFailed() { return mInitFail; } // Used by CameraDevice to signal external camera disconnected void disconnect(); bool isClosed(); // Retrieve the HIDL interface, split into its own class to avoid inheritance issues when // dealing with minor version revs and simultaneous implementation and interface inheritance virtual sp getInterface() { return new TrampolineSessionInterface_3_2(this); } protected: // Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow Return constructDefaultRequestSettings( RequestTemplate type, ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb); Return configureStreams( const StreamConfiguration& requestedConfiguration, ICameraDeviceSession::configureStreams_cb _hidl_cb); Return getCaptureRequestMetadataQueue( ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb); Return getCaptureResultMetadataQueue( ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb); Return processCaptureRequest( const hidl_vec& requests, const hidl_vec& cachesToRemove, ICameraDeviceSession::processCaptureRequest_cb _hidl_cb); Return flush(); Return close(); // Helper methods Status constructDefaultRequestSettingsRaw(int type, CameraMetadata *outMetadata); bool preProcessConfigurationLocked(const StreamConfiguration& requestedConfiguration, camera3_stream_configuration_t *stream_list /*out*/, hidl_vec *streams /*out*/); void postProcessConfigurationLocked(const StreamConfiguration& requestedConfiguration); void postProcessConfigurationFailureLocked(const StreamConfiguration& requestedConfiguration); protected: // protecting mClosed/mDisconnected/mInitFail mutable Mutex mStateLock; // device is closed either // - closed by user // - init failed // - camera disconnected bool mClosed = false; // Set by CameraDevice (when external camera is disconnected) bool mDisconnected = false; struct AETriggerCancelOverride { bool applyAeLock; uint8_t aeLock; bool applyAePrecaptureTrigger; uint8_t aePrecaptureTrigger; }; camera3_device_t* mDevice; const uint32_t mDeviceVersion; const bool mFreeBufEarly; bool mIsAELockAvailable; bool mDerivePostRawSensKey; uint32_t mNumPartialResults; // Stream ID -> Camera3Stream cache std::map mStreamMap; mutable Mutex mInflightLock; // protecting mInflightBuffers and mCirculatingBuffers // (streamID, frameNumber) -> inflight buffer cache std::map, camera3_stream_buffer_t> mInflightBuffers; // (frameNumber, AETriggerOverride) -> inflight request AETriggerOverrides std::map mInflightAETriggerOverrides; ::android::hardware::camera::common::V1_0::helper::CameraMetadata mOverridenResult; std::map mInflightRawBoostPresent; ::android::hardware::camera::common::V1_0::helper::CameraMetadata mOverridenRequest; static const uint64_t BUFFER_ID_NO_BUFFER = 0; // buffers currently ciculating between HAL and camera service // key: bufferId sent via HIDL interface // value: imported buffer_handle_t // Buffer will be imported during process_capture_request and will be freed // when the its stream is deleted or camera device session is closed typedef std::unordered_map CirculatingBuffers; // Stream ID -> circulating buffers map std::map mCirculatingBuffers; static HandleImporter sHandleImporter; static buffer_handle_t sEmptyBuffer; bool mInitFail; bool mFirstRequest = false; common::V1_0::helper::CameraMetadata mDeviceInfo; using RequestMetadataQueue = MessageQueue; std::unique_ptr mRequestMetadataQueue; using ResultMetadataQueue = MessageQueue; std::shared_ptr mResultMetadataQueue; class ResultBatcher { public: ResultBatcher(const sp& callback); void setNumPartialResults(uint32_t n); void setBatchedStreams(const std::vector& streamsToBatch); void setResultMetadataQueue(std::shared_ptr q); void registerBatch(uint32_t frameNumber, uint32_t batchSize); void notify(NotifyMsg& msg); void processCaptureResult(CaptureResult& result); protected: struct InflightBatch { // Protect access to entire struct. Acquire this lock before read/write any data or // calling any methods. processCaptureResult and notify will compete for this lock // HIDL IPCs might be issued while the lock is held Mutex mLock; bool allDelivered() const; uint32_t mFirstFrame; uint32_t mLastFrame; uint32_t mBatchSize; bool mShutterDelivered = false; std::vector mShutterMsgs; struct BufferBatch { BufferBatch(uint32_t batchSize) { mBuffers.reserve(batchSize); } bool mDelivered = false; // This currently assumes every batched request will output to the batched stream // and since HAL must always send buffers in order, no frameNumber tracking is // needed std::vector mBuffers; }; // Stream ID -> VideoBatch std::unordered_map mBatchBufs; struct MetadataBatch { // (frameNumber, metadata) std::vector> mMds; }; // Partial result IDs that has been delivered to framework uint32_t mNumPartialResults; uint32_t mPartialResultProgress = 0; // partialResult -> MetadataBatch std::map mResultMds; // Set to true when batch is removed from mInflightBatches // processCaptureResult and notify must check this flag after acquiring mLock to make // sure this batch isn't removed while waiting for mLock bool mRemoved = false; }; // Get the batch index and pointer to InflightBatch (nullptrt if the frame is not batched) // Caller must acquire the InflightBatch::mLock before accessing the InflightBatch // It's possible that the InflightBatch is removed from mInflightBatches before the // InflightBatch::mLock is acquired (most likely caused by an error notification), so // caller must check InflightBatch::mRemoved flag after the lock is acquried. // This method will hold ResultBatcher::mLock briefly std::pair> getBatch(uint32_t frameNumber); static const int NOT_BATCHED = -1; // move/push function avoids "hidl_handle& operator=(hidl_handle&)", which clones native // handle void moveStreamBuffer(StreamBuffer&& src, StreamBuffer& dst); void pushStreamBuffer(StreamBuffer&& src, std::vector& dst); void sendBatchMetadataLocked( std::shared_ptr batch, uint32_t lastPartialResultIdx); // Check if the first batch in mInflightBatches is ready to be removed, and remove it if so // This method will hold ResultBatcher::mLock briefly void checkAndRemoveFirstBatch(); // The following sendXXXX methods must be called while the InflightBatch::mLock is locked // HIDL IPC methods will be called during these methods. void sendBatchShutterCbsLocked(std::shared_ptr batch); // send buffers for all batched streams void sendBatchBuffersLocked(std::shared_ptr batch); // send buffers for specified streams void sendBatchBuffersLocked( std::shared_ptr batch, const std::vector& streams); // End of sendXXXX methods // helper methods void freeReleaseFences(hidl_vec&); void notifySingleMsg(NotifyMsg& msg); void processOneCaptureResult(CaptureResult& result); void invokeProcessCaptureResultCallback(hidl_vec &results, bool tryWriteFmq); // Protect access to mInflightBatches, mNumPartialResults and mStreamsToBatch // processCaptureRequest, processCaptureResult, notify will compete for this lock // Do NOT issue HIDL IPCs while holding this lock (except when HAL reports error) mutable Mutex mLock; std::deque> mInflightBatches; uint32_t mNumPartialResults; std::vector mStreamsToBatch; const sp mCallback; std::shared_ptr mResultMetadataQueue; // Protect against invokeProcessCaptureResultCallback() Mutex mProcessCaptureResultLock; } mResultBatcher; std::vector mVideoStreamIds; bool initialize(); static bool shouldFreeBufEarly(); Status initStatus() const; // Validate and import request's input buffer and acquire fence virtual Status importRequest( const CaptureRequest& request, hidl_vec& allBufPtrs, hidl_vec& allFences); Status importRequestImpl( const CaptureRequest& request, hidl_vec& allBufPtrs, hidl_vec& allFences, // Optional argument for ICameraDeviceSession@3.5 impl bool allowEmptyBuf = false); Status importBuffer(int32_t streamId, uint64_t bufId, buffer_handle_t buf, /*out*/buffer_handle_t** outBufPtr, bool allowEmptyBuf); static void cleanupInflightFences( hidl_vec& allFences, size_t numFences); void cleanupBuffersLocked(int id); void updateBufferCaches(const hidl_vec& cachesToRemove); android_dataspace mapToLegacyDataspace( android_dataspace dataSpace) const; bool handleAePrecaptureCancelRequestLocked( const camera3_capture_request_t &halRequest, android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/, AETriggerCancelOverride *override /*out*/); void overrideResultForPrecaptureCancelLocked( const AETriggerCancelOverride &aeTriggerCancelOverride, ::android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/); Status processOneCaptureRequest(const CaptureRequest& request); /** * Static callback forwarding methods from HAL to instance */ static callbacks_process_capture_result_t sProcessCaptureResult; static callbacks_notify_t sNotify; // By default camera service uses frameNumber/streamId pair to retrieve the buffer that // was sent to HAL. Override this implementation if HAL is using buffers from buffer management // APIs to send output buffer. virtual uint64_t getCapResultBufferId(const buffer_handle_t& buf, int streamId); status_t constructCaptureResult(CaptureResult& result, const camera3_capture_result *hal_result); // Static helper method to copy/shrink capture result metadata sent by HAL // Temporarily allocated metadata copy will be hold in mds static void sShrinkCaptureResult( camera3_capture_result* dst, const camera3_capture_result* src, std::vector<::android::hardware::camera::common::V1_0::helper::CameraMetadata>* mds, std::vector* physCamMdArray, bool handlePhysCam); static bool sShouldShrink(const camera_metadata_t* md); static camera_metadata_t* sCreateCompactCopy(const camera_metadata_t* src); private: struct TrampolineSessionInterface_3_2 : public ICameraDeviceSession { TrampolineSessionInterface_3_2(sp parent) : mParent(parent) {} virtual Return constructDefaultRequestSettings( V3_2::RequestTemplate type, V3_2::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override { return mParent->constructDefaultRequestSettings(type, _hidl_cb); } virtual Return configureStreams( const V3_2::StreamConfiguration& requestedConfiguration, V3_2::ICameraDeviceSession::configureStreams_cb _hidl_cb) override { return mParent->configureStreams(requestedConfiguration, _hidl_cb); } virtual Return processCaptureRequest(const hidl_vec& requests, const hidl_vec& cachesToRemove, V3_2::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override { return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb); } virtual Return getCaptureRequestMetadataQueue( V3_2::ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) override { return mParent->getCaptureRequestMetadataQueue(_hidl_cb); } virtual Return getCaptureResultMetadataQueue( V3_2::ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) override { return mParent->getCaptureResultMetadataQueue(_hidl_cb); } virtual Return flush() override { return mParent->flush(); } virtual Return close() override { return mParent->close(); } private: sp mParent; }; }; } // namespace implementation } // namespace V3_2 } // namespace device } // namespace camera } // namespace hardware } // namespace android #endif // ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H