From 24810e7a6725e9c3275bd9a8115a3049a73685d1 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Mon, 18 Mar 2019 10:55:01 -0700 Subject: [PATCH] Camera: Add isSessionConfigurationSupported in NDK/VNDK Test: NativeCameraDeviceTest and AImageReaderVendorTest Bug: 128933069 Change-Id: I26ca4c0ca12f7bd1b872c2f33e8fa63a056ae068 --- camera/ndk/NdkCameraDevice.cpp | 13 +++++ camera/ndk/impl/ACameraDevice.cpp | 49 +++++++++++++++++++ camera/ndk/impl/ACameraDevice.h | 9 ++++ camera/ndk/include/camera/NdkCameraDevice.h | 37 ++++++++++++++ camera/ndk/include/camera/NdkCameraError.h | 8 ++- camera/ndk/libcamera2ndk.map.txt | 1 + camera/ndk/ndk_vendor/impl/ACameraDevice.cpp | 42 ++++++++++++++++ camera/ndk/ndk_vendor/impl/ACameraDevice.h | 8 +++ .../tests/AImageReaderVendorTest.cpp | 6 +++ .../camera/libcameraservice/hidl/Convert.cpp | 15 ++++++ .../camera/libcameraservice/hidl/Convert.h | 4 ++ .../hidl/HidlCameraDeviceUser.cpp | 13 +++++ .../hidl/HidlCameraDeviceUser.h | 5 ++ 13 files changed, 209 insertions(+), 1 deletion(-) diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp index 09b85d5490..691996bdbf 100644 --- a/camera/ndk/NdkCameraDevice.cpp +++ b/camera/ndk/NdkCameraDevice.cpp @@ -287,3 +287,16 @@ camera_status_t ACameraDevice_createCaptureSessionWithSessionParameters( } return device->createCaptureSession(outputs, sessionParameters, callbacks, session); } + +EXPORT +camera_status_t ACameraDevice_isSessionConfigurationSupported( + const ACameraDevice* device, + const ACaptureSessionOutputContainer* sessionOutputContainer) { + ATRACE_CALL(); + if (device == nullptr || sessionOutputContainer == nullptr) { + ALOGE("%s: Error: invalid input: device %p, sessionOutputContainer %p", + __FUNCTION__, device, sessionOutputContainer); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + return device->isSessionConfigurationSupported(sessionOutputContainer); +} diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp index 5e4fcd07fd..c9db01e0bd 100644 --- a/camera/ndk/impl/ACameraDevice.cpp +++ b/camera/ndk/impl/ACameraDevice.cpp @@ -227,6 +227,55 @@ CameraDevice::createCaptureSession( return ACAMERA_OK; } +camera_status_t CameraDevice::isSessionConfigurationSupported( + const ACaptureSessionOutputContainer* sessionOutputContainer) const { + Mutex::Autolock _l(mDeviceLock); + camera_status_t ret = checkCameraClosedOrErrorLocked(); + if (ret != ACAMERA_OK) { + return ret; + } + + SessionConfiguration sessionConfiguration(0 /*inputWidth*/, 0 /*inputHeight*/, + -1 /*inputFormat*/, CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE); + for (const auto& output : sessionOutputContainer->mOutputs) { + sp iGBP(nullptr); + ret = getIGBPfromAnw(output.mWindow, iGBP); + if (ret != ACAMERA_OK) { + ALOGE("Camera device %s failed to extract graphic producer from native window", + getId()); + return ret; + } + + String16 physicalId16(output.mPhysicalCameraId.c_str()); + OutputConfiguration outConfig(iGBP, output.mRotation, physicalId16, + OutputConfiguration::INVALID_SET_ID, true); + + for (auto& anw : output.mSharedWindows) { + ret = getIGBPfromAnw(anw, iGBP); + if (ret != ACAMERA_OK) { + ALOGE("Camera device %s failed to extract graphic producer from native window", + getId()); + return ret; + } + outConfig.addGraphicProducer(iGBP); + } + + sessionConfiguration.addOutputConfiguration(outConfig); + } + + bool supported = false; + binder::Status remoteRet = mRemote->isSessionConfigurationSupported( + sessionConfiguration, &supported); + if (remoteRet.serviceSpecificErrorCode() == + hardware::ICameraService::ERROR_INVALID_OPERATION) { + return ACAMERA_ERROR_UNSUPPORTED_OPERATION; + } else if (!remoteRet.isOk()) { + return ACAMERA_ERROR_UNKNOWN; + } else { + return supported ? ACAMERA_OK : ACAMERA_ERROR_STREAM_CONFIGURE_FAIL; + } +} + camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) { camera_status_t ret = checkCameraClosedOrErrorLocked(); if (ret != ACAMERA_OK) { diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h index 103efd5218..56741cef00 100644 --- a/camera/ndk/impl/ACameraDevice.h +++ b/camera/ndk/impl/ACameraDevice.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -77,6 +78,9 @@ class CameraDevice final : public RefBase { const ACameraCaptureSession_stateCallbacks* callbacks, /*out*/ACameraCaptureSession** session); + camera_status_t isSessionConfigurationSupported( + const ACaptureSessionOutputContainer* sessionOutputContainer) const; + // Callbacks from camera service class ServiceCallback : public hardware::camera2::BnCameraDeviceCallbacks { public: @@ -369,6 +373,11 @@ struct ACameraDevice { return mDevice->createCaptureSession(outputs, sessionParameters, callbacks, session); } + camera_status_t isSessionConfigurationSupported( + const ACaptureSessionOutputContainer* sessionOutputContainer) const { + return mDevice->isSessionConfigurationSupported(sessionOutputContainer); + } + /*********************** * Device interal APIs * ***********************/ diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h index cedf83a1a5..bc544e3034 100644 --- a/camera/ndk/include/camera/NdkCameraDevice.h +++ b/camera/ndk/include/camera/NdkCameraDevice.h @@ -845,6 +845,43 @@ camera_status_t ACameraDevice_createCaptureRequest_withPhysicalIds( const ACameraIdList* physicalIdList, /*out*/ACaptureRequest** request) __INTRODUCED_IN(29); +/** + * Check whether a particular {@ACaptureSessionOutputContainer} is supported by + * the camera device. + * + *

This method performs a runtime check of a given {@link + * ACaptureSessionOutputContainer}. The result confirms whether or not the + * passed CaptureSession outputs can be successfully used to create a camera + * capture session using {@link ACameraDevice_createCaptureSession}.

+ * + *

This method can be called at any point before, during and after active + * capture session. It must not impact normal camera behavior in any way and + * must complete significantly faster than creating a capture session.

+ * + *

Although this method is faster than creating a new capture session, it is not intended + * to be used for exploring the entire space of supported stream combinations.

+ * + * @param device the camera device of interest + * @param sessionOutputContainer the {@link ACaptureSessionOutputContainer} of + * interest. + * + * @return
    + *
  • {@link ACAMERA_OK} if the given {@link ACaptureSessionOutputContainer} + * is supported by the camera device.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if device, or sessionOutputContainer + * is NULL.
  • + *
  • {@link ACAMERA_ERROR_STREAM_CONFIGURE_FAIL} if the given + * {@link ACaptureSessionOutputContainer} + * is not supported by + * the camera + * device.
  • + *
  • {@link ACAMERA_ERROR_UNSUPPORTED_OPERATION} if the query operation is not + * supported by the camera device.
  • + */ +camera_status_t ACameraDevice_isSessionConfigurationSupported( + const ACameraDevice* device, + const ACaptureSessionOutputContainer* sessionOutputContainer) __INTRODUCED_IN(29); + #endif /* __ANDROID_API__ >= 29 */ __END_DECLS diff --git a/camera/ndk/include/camera/NdkCameraError.h b/camera/ndk/include/camera/NdkCameraError.h index 6b5815502b..fc618eee50 100644 --- a/camera/ndk/include/camera/NdkCameraError.h +++ b/camera/ndk/include/camera/NdkCameraError.h @@ -106,7 +106,8 @@ typedef enum { /** * Camera device does not support the stream configuration provided by application in - * {@link ACameraDevice_createCaptureSession}. + * {@link ACameraDevice_createCaptureSession} or {@link + * ACameraDevice_isSessionConfigurationSupported}. */ ACAMERA_ERROR_STREAM_CONFIGURE_FAIL = ACAMERA_ERROR_BASE - 9, @@ -130,6 +131,11 @@ typedef enum { * The application does not have permission to open camera. */ ACAMERA_ERROR_PERMISSION_DENIED = ACAMERA_ERROR_BASE - 13, + + /** + * The operation is not supported by the camera device. + */ + ACAMERA_ERROR_UNSUPPORTED_OPERATION = ACAMERA_ERROR_BASE - 14, } camera_status_t; #endif /* __ANDROID_API__ >= 24 */ diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt index 946a98eff3..b6f1553ee3 100644 --- a/camera/ndk/libcamera2ndk.map.txt +++ b/camera/ndk/libcamera2ndk.map.txt @@ -14,6 +14,7 @@ LIBCAMERA2NDK { ACameraDevice_createCaptureRequest_withPhysicalIds; # introduced=29 ACameraDevice_createCaptureSession; ACameraDevice_createCaptureSessionWithSessionParameters; # introduced=28 + ACameraDevice_isSessionConfigurationSupported; # introduced=29 ACameraDevice_getId; ACameraManager_create; ACameraManager_delete; diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp index a38a31e79c..d7d774b727 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp +++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp @@ -38,6 +38,7 @@ namespace acam { using HCameraMetadata = frameworks::cameraservice::device::V2_0::CameraMetadata; using OutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration; +using SessionConfiguration = frameworks::cameraservice::device::V2_0::SessionConfiguration; using hardware::Void; // Static member definitions @@ -216,6 +217,47 @@ CameraDevice::createCaptureSession( return ACAMERA_OK; } +camera_status_t CameraDevice::isSessionConfigurationSupported( + const ACaptureSessionOutputContainer* sessionOutputContainer) const { + Mutex::Autolock _l(mDeviceLock); + camera_status_t ret = checkCameraClosedOrErrorLocked(); + if (ret != ACAMERA_OK) { + return ret; + } + + SessionConfiguration sessionConfig; + sessionConfig.inputWidth = 0; + sessionConfig.inputHeight = 0; + sessionConfig.inputFormat = -1; + sessionConfig.operationMode = StreamConfigurationMode::NORMAL_MODE; + sessionConfig.outputStreams.resize(sessionOutputContainer->mOutputs.size()); + size_t index = 0; + for (const auto& output : sessionOutputContainer->mOutputs) { + sessionConfig.outputStreams[index].rotation = utils::convertToHidl(output.mRotation); + sessionConfig.outputStreams[index].windowGroupId = -1; + sessionConfig.outputStreams[index].windowHandles.resize(output.mSharedWindows.size() + 1); + sessionConfig.outputStreams[index].windowHandles[0] = output.mWindow; + sessionConfig.outputStreams[index].physicalCameraId = output.mPhysicalCameraId; + index++; + } + + bool configSupported = false; + Status status = Status::NO_ERROR; + auto remoteRet = mRemote->isSessionConfigurationSupported(sessionConfig, + [&status, &configSupported](auto s, auto supported) { + status = s; + configSupported = supported; + }); + + if (status == Status::INVALID_OPERATION) { + return ACAMERA_ERROR_UNSUPPORTED_OPERATION; + } else if (!remoteRet.isOk()) { + return ACAMERA_ERROR_UNKNOWN; + } else { + return configSupported ? ACAMERA_OK : ACAMERA_ERROR_STREAM_CONFIGURE_FAIL; + } +} + void CameraDevice::addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest, sp &req) { CameraMetadata metadataCopy = aCaptureRequest->settings->getInternalData(); diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h index 28092fd373..47e6f56ef8 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h +++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h @@ -101,6 +101,9 @@ class CameraDevice final : public RefBase { const ACameraCaptureSession_stateCallbacks* callbacks, /*out*/ACameraCaptureSession** session); + camera_status_t isSessionConfigurationSupported( + const ACaptureSessionOutputContainer* sessionOutputContainer) const; + // Callbacks from camera service class ServiceCallback : public ICameraDeviceCallback { public: @@ -397,6 +400,11 @@ struct ACameraDevice { return mDevice->createCaptureSession(outputs, sessionParameters, callbacks, session); } + camera_status_t isSessionConfigurationSupported( + const ACaptureSessionOutputContainer* sessionOutputContainer) const { + return mDevice->isSessionConfigurationSupported(sessionOutputContainer); + } + /*********************** * Device interal APIs * ***********************/ diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp index 2398922048..c51f93b198 100644 --- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp +++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp @@ -121,6 +121,12 @@ class CameraHelper { cameraIdList.numCameras = idPointerList.size(); cameraIdList.cameraIds = idPointerList.data(); + ret = ACameraDevice_isSessionConfigurationSupported(mDevice, mOutputs); + if (ret != ACAMERA_OK && ret != ACAMERA_ERROR_UNSUPPORTED_OPERATION) { + ALOGE("ACameraDevice_isSessionConfigurationSupported failed, ret=%d", ret); + return ret; + } + ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession); if (ret != AMEDIA_OK) { ALOGE("ACameraDevice_createCaptureSession failed, ret=%d", ret); diff --git a/services/camera/libcameraservice/hidl/Convert.cpp b/services/camera/libcameraservice/hidl/Convert.cpp index a87812b6b4..c2ed23a61b 100644 --- a/services/camera/libcameraservice/hidl/Convert.cpp +++ b/services/camera/libcameraservice/hidl/Convert.cpp @@ -97,6 +97,21 @@ hardware::camera2::params::OutputConfiguration convertFromHidl( return outputConfiguration; } +hardware::camera2::params::SessionConfiguration convertFromHidl( + const HSessionConfiguration &hSessionConfiguration) { + hardware::camera2::params::SessionConfiguration sessionConfig( + hSessionConfiguration.inputWidth, hSessionConfiguration.inputHeight, + hSessionConfiguration.inputFormat, + static_cast(hSessionConfiguration.operationMode)); + + for (const auto& hConfig : hSessionConfiguration.outputStreams) { + hardware::camera2::params::OutputConfiguration config = convertFromHidl(hConfig); + sessionConfig.addOutputConfiguration(config); + } + + return sessionConfig; +} + // The camera metadata here is cloned. Since we're reading metadata over // hwbinder we would need to clone it in order to avoid aligment issues. bool convertFromHidl(const HCameraMetadata &src, CameraMetadata *dst) { diff --git a/services/camera/libcameraservice/hidl/Convert.h b/services/camera/libcameraservice/hidl/Convert.h index 82937a30d6..79683f6b00 100644 --- a/services/camera/libcameraservice/hidl/Convert.h +++ b/services/camera/libcameraservice/hidl/Convert.h @@ -53,6 +53,7 @@ using HGraphicBufferProducer = hardware::graphics::bufferqueue::V1_0::IGraphicBu using HOutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration; using HPhysicalCameraSettings = frameworks::cameraservice::device::V2_0::PhysicalCameraSettings; using HPhysicalCaptureResultInfo = frameworks::cameraservice::device::V2_0::PhysicalCaptureResultInfo; +using HSessionConfiguration = frameworks::cameraservice::device::V2_0::SessionConfiguration; using HSubmitInfo = frameworks::cameraservice::device::V2_0::SubmitInfo; using HStatus = frameworks::cameraservice::common::V2_0::Status; using HStreamConfigurationMode = frameworks::cameraservice::device::V2_0::StreamConfigurationMode; @@ -70,6 +71,9 @@ bool convertFromHidl(const HCameraMetadata &src, CameraMetadata *dst); hardware::camera2::params::OutputConfiguration convertFromHidl( const HOutputConfiguration &hOutputConfiguration); +hardware::camera2::params::SessionConfiguration convertFromHidl( + const HSessionConfiguration &hSessionConfiguration); + HCameraDeviceStatus convertToHidlCameraDeviceStatus(int32_t status); void convertToHidl(const std::vector &src, diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp index d22ba5aa61..675ad24bcf 100644 --- a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp +++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp @@ -41,6 +41,7 @@ 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 */; @@ -255,6 +256,18 @@ Return HidlCameraDeviceUser::updateOutputConfiguration( 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 diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h index be8f1d63c5..c3a80fe9e0 100644 --- a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h +++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h @@ -53,6 +53,7 @@ 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 HSessionConfiguration = frameworks::cameraservice::device::V2_0::SessionConfiguration; using HOutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration; using HPhysicalCameraSettings = frameworks::cameraservice::device::V2_0::PhysicalCameraSettings; using HStatus = frameworks::cameraservice::common::V2_0::Status; @@ -97,6 +98,10 @@ struct HidlCameraDeviceUser final : public HCameraDeviceUser { virtual Return updateOutputConfiguration( int32_t streamId, const HOutputConfiguration& outputConfiguration) override; + virtual Return isSessionConfigurationSupported( + const HSessionConfiguration& sessionConfiguration, + isSessionConfigurationSupported_cb _hidl_cb) override; + bool initStatus() { return mInitSuccess; } std::shared_ptr getCaptureResultMetadataQueue() {