From 22d63688cdec8826dfbcac681acf96c110d23ec9 Mon Sep 17 00:00:00 2001
From: Avichal Rakesh
Date: Mon, 25 Mar 2024 15:28:30 -0700
Subject: camera2: Ensure SessionCharacteristics and CameraCharactersitics can
be used interchangeably
CameraDeviceSetup#getSessionCharacteristics documentation says that
the returned session characteristics can be used everywhere static
charactersitics from CameraManager#getCameraCharacteristics is.
However #getCameraCharacteristics sets up a few extra fields and
keys in the CameraMetadataNative object returned from cameraservice
that SessionCharacteristics was missing.
To make the return value of #getSessionCharacteristics completely on
par with the return value of #getCameraCharacteristics, this CL
ensures that #getSessionCharacteristics and #getCameraCharateristics
run the same logic on the CameraMetadataNative object returned from
cameraservice before returning it to the caller.
Bug: 303645857
Test: atest android.hardware.camera2.cts.CameraDeviceSetupTest
passes
Change-Id: Ia7ac40c768480a39fe0d1dd9392b5777b0fc2694
---
.../android/hardware/camera2/CameraManager.java | 100 ++++++++++++++++-----
.../camera2/impl/CameraDeviceSetupImpl.java | 5 +-
2 files changed, 81 insertions(+), 24 deletions(-)
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 8feb133e832b..3eb5be04b93d 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -112,6 +112,34 @@ public final class CameraManager {
private static final int CAMERA_TYPE_BACKWARD_COMPATIBLE = 0;
private static final int CAMERA_TYPE_ALL = 1;
+ /**
+ * Caches the mapping between a logical camera ID and 'MultiResolutionStreamConfigurationMap'
+ * that is calculated by {@link #getPhysicalCameraMultiResolutionConfigs} as the calculation
+ * might take many binder calls.
+ *
+ * Note, this is a map of maps. The structure is:
+ *
+ * {
+ * logicalCameraId_1 -> {
+ * physicalCameraId_1 -> [
+ * streamConfiguration_1,
+ * streamConfiguration_2,
+ * ...
+ * ],
+ * physicalCameraId_2 -> [...],
+ * ...
+ * },
+ * logicalCameraId_2 -> {
+ * ...
+ * },
+ * ...
+ * }
+ *
+ *
+ */
+ private final Map>
+ mCameraIdToMultiResolutionStreamConfigurationMap = new HashMap<>();
+
private final Context mContext;
private final Object mLock = new Object();
@@ -566,8 +594,14 @@ public final class CameraManager {
private Map getPhysicalCameraMultiResolutionConfigs(
String cameraId, CameraMetadataNative info, ICameraService cameraService)
throws CameraAccessException {
+ if (mCameraIdToMultiResolutionStreamConfigurationMap.containsKey(cameraId)) {
+ return mCameraIdToMultiResolutionStreamConfigurationMap.get(cameraId);
+ }
+
HashMap multiResolutionStreamConfigurations =
- new HashMap();
+ new HashMap<>();
+ mCameraIdToMultiResolutionStreamConfigurationMap.put(cameraId,
+ multiResolutionStreamConfigurations);
Boolean multiResolutionStreamSupported = info.get(
CameraCharacteristics.SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED);
@@ -676,30 +710,10 @@ public final class CameraManager {
"Camera service is currently unavailable");
}
try {
- Size displaySize = getDisplaySize();
-
CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId,
mContext.getApplicationInfo().targetSdkVersion, overrideToPortrait,
mContext.getDeviceId(), getDevicePolicyFromContext(mContext));
- try {
- info.setCameraId(Integer.parseInt(cameraId));
- } catch (NumberFormatException e) {
- Log.v(TAG, "Failed to parse camera Id " + cameraId + " to integer");
- }
-
- boolean hasConcurrentStreams =
- CameraManagerGlobal.get().cameraIdHasConcurrentStreamsLocked(cameraId,
- mContext.getDeviceId());
- info.setHasMandatoryConcurrentStreams(hasConcurrentStreams);
- info.setDisplaySize(displaySize);
-
- Map multiResolutionSizeMap =
- getPhysicalCameraMultiResolutionConfigs(cameraId, info, cameraService);
- if (multiResolutionSizeMap.size() > 0) {
- info.setMultiResolutionStreamConfigurationMap(multiResolutionSizeMap);
- }
-
- characteristics = new CameraCharacteristics(info);
+ characteristics = prepareCameraCharacteristics(cameraId, info, cameraService);
} catch (ServiceSpecificException e) {
throw ExceptionUtils.throwAsPublicException(e);
} catch (RemoteException e) {
@@ -712,6 +726,48 @@ public final class CameraManager {
return characteristics;
}
+
+ /**
+ * Utility method to take a {@link CameraMetadataNative} object and wrap it into a
+ * {@link CameraCharacteristics} object that has all required fields and keys set and is fit
+ * for apps to consume.
+ *
+ * @param cameraId camera Id that the CameraMetadataNative was fetched for.
+ * @param metadata base CameraMetadataNative to be wrapped
+ * @param cameraService remote cameraservice instance to be used if binder calls need
+ * to be made.
+ * @return A CameraCharacteristics object that can be used by the apps.
+ * @hide
+ */
+ @NonNull
+ public CameraCharacteristics prepareCameraCharacteristics(
+ @NonNull String cameraId, CameraMetadataNative metadata, ICameraService cameraService)
+ throws CameraAccessException {
+ synchronized (mLock) {
+ try {
+ metadata.setCameraId(Integer.parseInt(cameraId));
+ } catch (NumberFormatException e) {
+ Log.v(TAG, "Failed to parse camera Id " + cameraId + " to integer");
+ }
+
+ boolean hasConcurrentStreams =
+ CameraManagerGlobal.get().cameraIdHasConcurrentStreamsLocked(cameraId,
+ mContext.getDeviceId());
+ metadata.setHasMandatoryConcurrentStreams(hasConcurrentStreams);
+
+ Size displaySize = getDisplaySize();
+ metadata.setDisplaySize(displaySize);
+
+ Map multiResolutionSizeMap =
+ getPhysicalCameraMultiResolutionConfigs(cameraId, metadata, cameraService);
+ if (!multiResolutionSizeMap.isEmpty()) {
+ metadata.setMultiResolutionStreamConfigurationMap(multiResolutionSizeMap);
+ }
+
+ return new CameraCharacteristics(metadata);
+ }
+ }
+
/**
* Query the camera extension capabilities of a camera device.
*
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java
index 24ac0b56a095..81d0976c09bb 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java
@@ -132,13 +132,14 @@ public class CameraDeviceSetupImpl extends CameraDevice.CameraDeviceSetup {
}
try {
- CameraMetadataNative metadataNative = cameraService.getSessionCharacteristics(
+ CameraMetadataNative metadata = cameraService.getSessionCharacteristics(
mCameraId, mTargetSdkVersion,
CameraManager.shouldOverrideToPortrait(mContext), sessionConfig,
mContext.getDeviceId(),
mCameraManager.getDevicePolicyFromContext(mContext));
- return new CameraCharacteristics(metadataNative);
+ return mCameraManager.prepareCameraCharacteristics(mCameraId, metadata,
+ cameraService);
} catch (ServiceSpecificException e) {
switch (e.errorCode) {
case ICameraService.ERROR_INVALID_OPERATION ->
--
cgit v1.2.3-59-g8ed1b