Camera: Add isSessionConfigurationSupported in NDK/VNDK
Test: NativeCameraDeviceTest and AImageReaderVendorTest
Bug: 128933069
Change-Id: I26ca4c0ca12f7bd1b872c2f33e8fa63a056ae068
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
index 09b85d5..691996b 100644
--- a/camera/ndk/NdkCameraDevice.cpp
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -287,3 +287,16 @@
}
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 5e4fcd0..c9db01e 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -227,6 +227,55 @@
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<IGraphicBufferProducer> 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 103efd5..56741ce 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -35,6 +35,7 @@
#include <media/stagefright/foundation/AMessage.h>
#include <camera/CaptureResult.h>
#include <camera/camera2/OutputConfiguration.h>
+#include <camera/camera2/SessionConfiguration.h>
#include <camera/camera2/CaptureRequest.h>
#include <camera/NdkCameraManager.h>
@@ -77,6 +78,9 @@
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 @@
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 cedf83a..bc544e3 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -845,6 +845,43 @@
const ACameraIdList* physicalIdList,
/*out*/ACaptureRequest** request) __INTRODUCED_IN(29);
+/**
+ * Check whether a particular {@ACaptureSessionOutputContainer} is supported by
+ * the camera device.
+ *
+ * <p>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}.</p>
+ *
+ * <p>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.</p>
+ *
+ * <p>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.</p>
+ *
+ * @param device the camera device of interest
+ * @param sessionOutputContainer the {@link ACaptureSessionOutputContainer} of
+ * interest.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the given {@link ACaptureSessionOutputContainer}
+ * is supported by the camera device.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if device, or sessionOutputContainer
+ * is NULL.</li>
+ * <li>{@link ACAMERA_ERROR_STREAM_CONFIGURE_FAIL} if the given
+ * {@link ACaptureSessionOutputContainer}
+ * is not supported by
+ * the camera
+ * device.</li>
+ * <li>{@link ACAMERA_ERROR_UNSUPPORTED_OPERATION} if the query operation is not
+ * supported by the camera device.</li>
+ */
+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 6b58155..fc618ee 100644
--- a/camera/ndk/include/camera/NdkCameraError.h
+++ b/camera/ndk/include/camera/NdkCameraError.h
@@ -106,7 +106,8 @@
/**
* 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 @@
* 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 946a98e..b6f1553 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -14,6 +14,7 @@
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 a38a31e..d7d774b 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -38,6 +38,7 @@
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 @@
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<CaptureRequest> &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 28092fd..47e6f56 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -101,6 +101,9 @@
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 @@
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 2398922..c51f93b 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -121,6 +121,12 @@
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 a87812b..c2ed23a 100644
--- a/services/camera/libcameraservice/hidl/Convert.cpp
+++ b/services/camera/libcameraservice/hidl/Convert.cpp
@@ -97,6 +97,21 @@
return outputConfiguration;
}
+hardware::camera2::params::SessionConfiguration convertFromHidl(
+ const HSessionConfiguration &hSessionConfiguration) {
+ hardware::camera2::params::SessionConfiguration sessionConfig(
+ hSessionConfiguration.inputWidth, hSessionConfiguration.inputHeight,
+ hSessionConfiguration.inputFormat,
+ static_cast<int>(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 82937a3..79683f6 100644
--- a/services/camera/libcameraservice/hidl/Convert.h
+++ b/services/camera/libcameraservice/hidl/Convert.h
@@ -53,6 +53,7 @@
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 @@
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<hardware::CameraStatus> &src,
diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
index d22ba5a..675ad24 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
@@ -41,6 +41,7 @@
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 B2HStatus(ret);
}
+Return<void> 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 be8f1d6..c3a80fe 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h
+++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.h
@@ -53,6 +53,7 @@
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 @@
virtual Return<HStatus> updateOutputConfiguration(
int32_t streamId, const HOutputConfiguration& outputConfiguration) override;
+ virtual Return<void> isSessionConfigurationSupported(
+ const HSessionConfiguration& sessionConfiguration,
+ isSessionConfigurationSupported_cb _hidl_cb) override;
+
bool initStatus() { return mInitSuccess; }
std::shared_ptr<CaptureResultMetadataQueue> getCaptureResultMetadataQueue() {