Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc542a4e authored by Igor Murashkin's avatar Igor Murashkin
Browse files

camera2: Fix available keys to filter to only supported keys

The following functions are affected:
* CameraCharacteristics#getKeys
* CameraCharacteristics#getAvailableResultKeys
* CameraCharacteristics#getAvailableRequestKeys

The above keys will now only return keys whose tags are set in
android.request.available{Characteristics,Result,Request}Keys

This change makes it possible to detect if a key is guaranteed to be
available at a granular basis (without querying hardwareLevel or
capabilities).

Change-Id: Iaa34e8c24100339c215604ff49035527fae467cd
parent 7068c395
Loading
Loading
Loading
Loading
+30 −8
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
    }

    private final CameraMetadataNative mProperties;
    private List<CameraCharacteristics.Key<?>> mKeys;
    private List<CaptureRequest.Key<?>> mAvailableRequestKeys;
    private List<CaptureResult.Key<?>> mAvailableResultKeys;

@@ -194,8 +195,20 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
     */
    @Override
    public List<Key<?>> getKeys() {
        // Force the javadoc for this function to show up on the CameraCharacteristics page
        return super.getKeys();
        // List of keys is immutable; cache the results after we calculate them
        if (mKeys != null) {
            return mKeys;
        }

        int[] filterTags = get(REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
        if (filterTags == null) {
            throw new AssertionError("android.request.availableCharacteristicsKeys must be non-null"
                    + " in the characteristics");
        }

        mKeys = Collections.unmodifiableList(
                getKeysStatic(getClass(), getKeyClass(), this, filterTags));
        return mKeys;
    }

    /**
@@ -218,8 +231,13 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
            Object crKey = CaptureRequest.Key.class;
            Class<CaptureRequest.Key<?>> crKeyTyped = (Class<CaptureRequest.Key<?>>)crKey;

            mAvailableRequestKeys = Collections.unmodifiableList(
                    getAvailableKeyList(CaptureRequest.class, crKeyTyped));
            int[] filterTags = get(REQUEST_AVAILABLE_REQUEST_KEYS);
            if (filterTags == null) {
                throw new AssertionError("android.request.availableRequestKeys must be non-null "
                        + "in the characteristics");
            }
            mAvailableRequestKeys =
                    getAvailableKeyList(CaptureRequest.class, crKeyTyped, filterTags);
        }
        return mAvailableRequestKeys;
    }
@@ -244,8 +262,12 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
            Object crKey = CaptureResult.Key.class;
            Class<CaptureResult.Key<?>> crKeyTyped = (Class<CaptureResult.Key<?>>)crKey;

            mAvailableResultKeys = Collections.unmodifiableList(
                    getAvailableKeyList(CaptureResult.class, crKeyTyped));
            int[] filterTags = get(REQUEST_AVAILABLE_RESULT_KEYS);
            if (filterTags == null) {
                throw new AssertionError("android.request.availableResultKeys must be non-null "
                        + "in the characteristics");
            }
            mAvailableResultKeys = getAvailableKeyList(CaptureResult.class, crKeyTyped, filterTags);
        }
        return mAvailableResultKeys;
    }
@@ -266,7 +288,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
     * @throws IllegalArgumentException if metadataClass is not a subclass of CameraMetadata
     */
    private <TKey> List<TKey>
    getAvailableKeyList(Class<?> metadataClass, Class<TKey> keyClass) {
    getAvailableKeyList(Class<?> metadataClass, Class<TKey> keyClass, int[] filterTags) {

        if (metadataClass.equals(CameraMetadata.class)) {
            throw new AssertionError(
@@ -277,7 +299,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
        }

        List<TKey> staticKeyList = CameraCharacteristics.<TKey>getKeysStatic(
                metadataClass, keyClass, /*instance*/null);
                metadataClass, keyClass, /*instance*/null, filterTags);
        return Collections.unmodifiableList(staticKeyList);
    }

+58 −3
Original line number Diff line number Diff line
@@ -16,11 +16,13 @@

package android.hardware.camera2;

import android.hardware.camera2.impl.CameraMetadataNative;
import android.util.Log;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@@ -101,7 +103,8 @@ public abstract class CameraMetadata<TKey> {
    @SuppressWarnings("unchecked")
    public List<TKey> getKeys() {
        Class<CameraMetadata<TKey>> thisClass = (Class<CameraMetadata<TKey>>) getClass();
        return Collections.unmodifiableList(getKeysStatic(thisClass, getKeyClass(), this));
        return Collections.unmodifiableList(
                getKeysStatic(thisClass, getKeyClass(), this, /*filterTags*/null));
    }

    /**
@@ -111,14 +114,25 @@ public abstract class CameraMetadata<TKey> {
     * <p>
     * Optionally, if {@code instance} is not null, then filter out any keys with null values.
     * </p>
     *
     * <p>
     * Optionally, if {@code filterTags} is not {@code null}, then filter out any keys
     * whose native {@code tag} is not in {@code filterTags}. The {@code filterTags} array will be
     * sorted as a side effect.
     * </p>
     */
     /*package*/ @SuppressWarnings("unchecked")
    static <TKey> ArrayList<TKey> getKeysStatic(
             Class<?> type, Class<TKey> keyClass,
             CameraMetadata<TKey> instance) {
             CameraMetadata<TKey> instance,
             int[] filterTags) {

        if (VERBOSE) Log.v(TAG, "getKeysStatic for " + type);

        if (filterTags != null) {
            Arrays.sort(filterTags);
        }

        ArrayList<TKey> keyList = new ArrayList<TKey>();

        Field[] fields = type.getDeclaredFields();
@@ -137,7 +151,15 @@ public abstract class CameraMetadata<TKey> {
                }

                if (instance == null || instance.getProtected(key) != null) {
                    if (shouldKeyBeAdded(key, filterTags)) {
                        keyList.add(key);

                        if (VERBOSE) {
                            Log.v(TAG, "getKeysStatic - key was added - " + key);
                        }
                    } else if (VERBOSE) {
                        Log.v(TAG, "getKeysStatic - key was filtered - " + key);
                    }
                }
            }
        }
@@ -145,6 +167,39 @@ public abstract class CameraMetadata<TKey> {
        return keyList;
    }

    @SuppressWarnings("rawtypes")
    private static <TKey> boolean shouldKeyBeAdded(TKey key, int[] filterTags) {
        if (key == null) {
            throw new NullPointerException("key must not be null");
        }

        CameraMetadataNative.Key nativeKey;

        /*
         * Get the native key from the public api key
         */
        if (key instanceof CameraCharacteristics.Key) {
            nativeKey = ((CameraCharacteristics.Key)key).getNativeKey();
        } else if (key instanceof CaptureResult.Key) {
            nativeKey = ((CaptureResult.Key)key).getNativeKey();
        } else if (key instanceof CaptureRequest.Key) {
            nativeKey = ((CaptureRequest.Key)key).getNativeKey();
        } else {
            // Reject fields that aren't a key
            throw new IllegalArgumentException("key type must be that of a metadata key");
        }

        // No filtering necessary
        if (filterTags == null) {
            return true;
        }

        int keyTag = nativeKey.getTag();

        // non-negative result is returned iff the value is in the array
        return Arrays.binarySearch(filterTags, keyTag) >= 0;
    }

    /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
     * The enum values below this point are generated from metadata
     * definitions in /system/media/camera/docs. Do not modify by hand or