camera2: Add key enumeration functionality to CameraMetadata
* Add a way to enumerate all currently set keys in CameraMetadata
* Add a way to enumerate all available keys for CaptureRequest
* Add a way to enumerate all available keys for CaptureResult
* No way to enumerate all keys for CameraProperties, since it would be
identical to all the currently set keys.
Bug: 10360518
Change-Id: I3a90f8cc385db14a675e4ff876ae93d906ff06bf
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index ec23f08..7f4ba4f 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -18,12 +18,25 @@
import android.hardware.camera2.impl.CameraMetadataNative;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
/**
* The base class for camera controls and information.
*
+ * <p>
* This class defines the basic key/value map used for querying for camera
* characteristics or capture results, and for setting camera request
* parameters.
+ * </p>
+ *
+ * <p>
+ * All instances of CameraMetadata are immutable. The list of keys with {@link #getKeys()}
+ * never changes, nor do the values returned by any key with {@link #get} throughout
+ * the lifetime of the object.
+ * </p>
*
* @see CameraDevice
* @see CameraManager
@@ -38,9 +51,14 @@
}
/**
- * Get a camera metadata field value. The field definitions can be
+ * Get a camera metadata field value.
+ *
+ * <p>The field definitions can be
* found in {@link CameraProperties}, {@link CaptureResult}, and
- * {@link CaptureRequest}.
+ * {@link CaptureRequest}.</p>
+ *
+ * <p>Querying the value for the same key more than once will return a value
+ * which is equal to the previous queried value.</p>
*
* @throws IllegalArgumentException if the key was not valid
*
@@ -49,6 +67,54 @@
*/
public abstract <T> T get(Key<T> key);
+ /**
+ * Returns a list of the keys contained in this map.
+ *
+ * <p>The list returned is not modifiable, so any attempts to modify it will throw
+ * a {@code UnsupportedOperationException}.</p>
+ *
+ * <p>All values retrieved by a key from this list with {@link #get} are guaranteed to be
+ * non-{@code null}. Each key is only listed once in the list. The order of the keys
+ * is undefined.</p>
+ *
+ * @return List of the keys contained in this map.
+ */
+ public List<Key<?>> getKeys() {
+ return Collections.unmodifiableList(getKeysStatic(this.getClass(), this));
+ }
+
+ /**
+ * Return a list of all the Key<?> that are declared as a field inside of the class
+ * {@code type}.
+ *
+ * <p>
+ * Optionally, if {@code instance} is not null, then filter out any keys with null values.
+ * </p>
+ */
+ /*package*/ static ArrayList<Key<?>> getKeysStatic(Class<? extends CameraMetadata> type,
+ CameraMetadata instance) {
+ ArrayList<Key<?>> keyList = new ArrayList<Key<?>>();
+
+ Field[] fields = type.getDeclaredFields();
+ for (Field field : fields) {
+ if (field.getDeclaringClass().isAssignableFrom(Key.class)) {
+ Key<?> key;
+ try {
+ key = (Key<?>) field.get(instance);
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("Can't get IllegalAccessException", e);
+ } catch (IllegalArgumentException e) {
+ throw new AssertionError("Can't get IllegalArgumentException", e);
+ }
+ if (instance == null || instance.get(key) != null) {
+ keyList.add(key);
+ }
+ }
+ }
+
+ return keyList;
+ }
+
public static class Key<T> {
private boolean mHasTag;
diff --git a/core/java/android/hardware/camera2/CameraProperties.java b/core/java/android/hardware/camera2/CameraProperties.java
index 45c009f..58a1ee3 100644
--- a/core/java/android/hardware/camera2/CameraProperties.java
+++ b/core/java/android/hardware/camera2/CameraProperties.java
@@ -18,6 +18,9 @@
import android.hardware.camera2.impl.CameraMetadataNative;
+import java.util.Collections;
+import java.util.List;
+
/**
* <p>The properties describing a
* {@link CameraDevice CameraDevice}.</p>
@@ -32,6 +35,8 @@
public final class CameraProperties extends CameraMetadata {
private final CameraMetadataNative mProperties;
+ private List<Key<?>> mAvailableRequestKeys;
+ private List<Key<?>> mAvailableResultKeys;
/**
* Takes ownership of the passed-in properties object
@@ -46,6 +51,75 @@
return mProperties.get(key);
}
+ /**
+ * Returns the list of keys supported by this {@link CameraDevice} for querying
+ * with a {@link CaptureRequest}.
+ *
+ * <p>The list returned is not modifiable, so any attempts to modify it will throw
+ * a {@code UnsupportedOperationException}.</p>
+ *
+ * <p>Each key is only listed once in the list. The order of the keys is undefined.</p>
+ *
+ * <p>Note that there is no {@code getAvailableCameraPropertiesKeys()} -- use
+ * {@link #getKeys()} instead.</p>
+ *
+ * @return List of keys supported by this CameraDevice for CaptureRequests.
+ */
+ public List<Key<?>> getAvailableCaptureRequestKeys() {
+ if (mAvailableRequestKeys == null) {
+ mAvailableRequestKeys = getAvailableKeyList(CaptureRequest.class);
+ }
+ return mAvailableRequestKeys;
+ }
+
+ /**
+ * Returns the list of keys supported by this {@link CameraDevice} for querying
+ * with a {@link CaptureResult}.
+ *
+ * <p>The list returned is not modifiable, so any attempts to modify it will throw
+ * a {@code UnsupportedOperationException}.</p>
+ *
+ * <p>Each key is only listed once in the list. The order of the keys is undefined.</p>
+ *
+ * <p>Note that there is no {@code getAvailableCameraPropertiesKeys()} -- use
+ * {@link #getKeys()} instead.</p>
+ *
+ * @return List of keys supported by this CameraDevice for CaptureResults.
+ */
+ public List<Key<?>> getAvailableCaptureResultKeys() {
+ if (mAvailableResultKeys == null) {
+ mAvailableResultKeys = getAvailableKeyList(CaptureResult.class);
+ }
+ return mAvailableResultKeys;
+ }
+
+ /**
+ * Returns the list of keys supported by this {@link CameraDevice} by metadataClass.
+ *
+ * <p>The list returned is not modifiable, so any attempts to modify it will throw
+ * a {@code UnsupportedOperationException}.</p>
+ *
+ * <p>Each key is only listed once in the list. The order of the keys is undefined.</p>
+ *
+ * @param metadataClass The subclass of CameraMetadata that you want to get the keys for.
+ *
+ * @return List of keys supported by this CameraDevice for metadataClass.
+ *
+ * @throws IllegalArgumentException if metadataClass is not a subclass of CameraMetadata
+ */
+ private <T extends CameraMetadata> List<Key<?>> getAvailableKeyList(Class<T> metadataClass) {
+
+ if (metadataClass.equals(CameraMetadata.class)) {
+ throw new AssertionError(
+ "metadataClass must be a strict subclass of CameraMetadata");
+ } else if (!CameraMetadata.class.isAssignableFrom(metadataClass)) {
+ throw new AssertionError(
+ "metadataClass must be a subclass of CameraMetadata");
+ }
+
+ return Collections.unmodifiableList(getKeysStatic(metadataClass, /*instance*/null));
+ }
+
/*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
* The key entries below this point are generated from metadata
* definitions in /system/media/camera/docs. Do not modify by hand or
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 4608ab9..3ec5ca0 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -176,7 +176,7 @@
*/
public final static class Builder {
- private CaptureRequest mRequest;
+ private final CaptureRequest mRequest;
/**
* Initialize the builder using the template; the request takes
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 020d7b6..c13438a 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -27,7 +27,6 @@
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Map;
/**
* Implementation of camera metadata marshal/unmarshal across Binder to