/*
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.hardware.camera2.cts.helpers;

import android.graphics.Rect;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraCharacteristics.Key;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.cts.CameraTestUtils;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.util.Range;
import android.util.Size;
import android.util.Log;
import android.util.Rational;

import junit.framework.Assert;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Helpers to get common static info out of the camera.
 *
 * <p>Avoid boiler plate by putting repetitive get/set patterns in this class.</p>
 *
 * <p>Attempt to be durable against the camera device having bad or missing metadata
 * by providing reasonable defaults and logging warnings when that happens.</p>
 */
public class StaticMetadata {

    private static final String TAG = "StaticMetadata";
    private static final int IGNORE_SIZE_CHECK = -1;

    private static final long SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST = 100000L; // 100us
    private static final long SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST = 100000000; // 100ms
    private static final int SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST = 100;
    private static final int SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST = 800;
    private static final int STATISTICS_INFO_MAX_FACE_COUNT_MIN_AT_LEAST = 4;
    private static final int TONEMAP_MAX_CURVE_POINTS_AT_LEAST = 64;
    private static final int CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MIN = -2;
    private static final int CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MAX = 2;
    private static final Rational CONTROL_AE_COMPENSATION_STEP_DEFAULT = new Rational(1, 2);
    private static final byte REQUEST_PIPELINE_MAX_DEPTH_MAX = 8;

    // TODO: Consider making this work across any metadata object, not just camera characteristics
    private final CameraCharacteristics mCharacteristics;
    private final CheckLevel mLevel;
    private final CameraErrorCollector mCollector;

    public enum CheckLevel {
        /** Only log warnings for metadata check failures. Execution continues. */
        WARN,
        /**
         * Use ErrorCollector to collect the metadata check failures, Execution
         * continues.
         */
        COLLECT,
        /** Assert the metadata check failures. Execution aborts. */
        ASSERT
    }

    /**
     * Construct a new StaticMetadata object.
     *
     *<p> Default constructor, only log warnings for the static metadata check failures</p>
     *
     * @param characteristics static info for a camera
     * @throws IllegalArgumentException if characteristics was null
     */
    public StaticMetadata(CameraCharacteristics characteristics) {
        this(characteristics, CheckLevel.WARN, /*collector*/null);
    }

    /**
     * Construct a new StaticMetadata object with {@link CameraErrorCollector}.
     * <p>
     * When level is not {@link CheckLevel.COLLECT}, the {@link CameraErrorCollector} will be
     * ignored, otherwise, it will be used to log the check failures.
     * </p>
     *
     * @param characteristics static info for a camera
     * @param collector The {@link CameraErrorCollector} used by this StaticMetadata
     * @throws IllegalArgumentException if characteristics or collector was null.
     */
    public StaticMetadata(CameraCharacteristics characteristics, CameraErrorCollector collector) {
        this(characteristics, CheckLevel.COLLECT, collector);
    }

    /**
     * Construct a new StaticMetadata object with {@link CheckLevel} and
     * {@link CameraErrorCollector}.
     * <p>
     * When level is not {@link CheckLevel.COLLECT}, the {@link CameraErrorCollector} will be
     * ignored, otherwise, it will be used to log the check failures.
     * </p>
     *
     * @param characteristics static info for a camera
     * @param level The {@link CheckLevel} of this StaticMetadata
     * @param collector The {@link CameraErrorCollector} used by this StaticMetadata
     * @throws IllegalArgumentException if characteristics was null or level was
     *         {@link CheckLevel.COLLECT} but collector was null.
     */
    public StaticMetadata(CameraCharacteristics characteristics, CheckLevel level,
            CameraErrorCollector collector) {
        if (characteristics == null) {
            throw new IllegalArgumentException("characteristics was null");
        }
        if (level == CheckLevel.COLLECT && collector == null) {
            throw new IllegalArgumentException("collector must valid when COLLECT level is set");
        }

        mCharacteristics = characteristics;
        mLevel = level;
        mCollector = collector;
    }

    /**
     * Get the CameraCharacteristics associated with this StaticMetadata.
     *
     * @return A non-null CameraCharacteristics object
     */
    public CameraCharacteristics getCharacteristics() {
        return mCharacteristics;
    }

    /**
     * Whether or not the hardware level reported by android.info.supportedHardwareLevel
     * is {@value CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL}.
     *
     * <p>If the camera device is not reporting the hardwareLevel, this
     * will cause the test to fail.</p>
     *
     * @return {@code true} if the device is {@code FULL}, {@code false} otherwise.
     */
    public boolean isHardwareLevelFull() {
        return getHardwareLevelChecked() == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
    }

    /**
     * Whether or not the hardware level reported by android.info.supportedHardwareLevel
     * Return the supported hardware level of the device, or fail if no value is reported.
     *
     * @return the supported hardware level as a constant defined for
     *      {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}.
     */
    public int getHardwareLevelChecked() {
        Integer hwLevel = getValueFromKeyNonNull(
                CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
        if (hwLevel == null) {
            Assert.fail("No supported hardware level reported.");
        }
        return hwLevel;
    }

    /**
     * Whether or not the hardware level reported by android.info.supportedHardwareLevel
     * is {@value CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY}.
     *
     * <p>If the camera device is not reporting the hardwareLevel, this
     * will cause the test to fail.</p>
     *
     * @return {@code true} if the device is {@code LEGACY}, {@code false} otherwise.
     */
    public boolean isHardwareLevelLegacy() {
        return getHardwareLevelChecked() == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
    }

    /**
     * Whether or not the per frame control is supported by the camera device.
     *
     * @return {@code true} if per frame control is supported, {@code false} otherwise.
     */
    public boolean isPerFrameControlSupported() {
        return getSyncMaxLatency() == CameraMetadata.SYNC_MAX_LATENCY_PER_FRAME_CONTROL;
    }

    /**
     * Get the maximum number of frames to wait for a request settings being applied
     *
     * @return CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN for unknown latency
     *         CameraMetadata.SYNC_MAX_LATENCY_PER_FRAME_CONTROL for per frame control
     *         a positive int otherwise
     */
    public int getSyncMaxLatency() {
        Integer value = getValueFromKeyNonNull(CameraCharacteristics.SYNC_MAX_LATENCY);
        if (value == null) {
            return CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN;
        }
        return value;
    }

    /**
     * Whether or not the hardware level reported by android.info.supportedHardwareLevel
     * is {@value CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED}.
     *
     * <p>If the camera device is incorrectly reporting the hardwareLevel, this
     * will always return {@code true}.</p>
     *
     * @return {@code true} if the device is {@code LIMITED}, {@code false} otherwise.
     */
    public boolean isHardwareLevelLimited() {
        return getHardwareLevelChecked() == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
    }

    /**
     * Whether or not the hardware level reported by {@code android.info.supportedHardwareLevel}
     * is at least {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED}.
     *
     * <p>If the camera device is incorrectly reporting the hardwareLevel, this
     * will always return {@code false}.</p>
     *
     * @return
     *          {@code true} if the device is {@code LIMITED} or {@code FULL},
     *          {@code false} otherwise (i.e. LEGACY).
     */
    public boolean isHardwareLevelLimitedOrBetter() {
        Integer hwLevel = getValueFromKeyNonNull(
                CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);

        if (hwLevel == null) {
            return false;
        }

        // Normal. Device could be limited.
        int hwLevelInt = hwLevel;
        return hwLevelInt == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL ||
                hwLevelInt == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
    }

    /**
     * Get the maximum number of partial result a request can expect
     *
     * @return 1 if partial result is not supported.
     *         a integer value larger than 1 if partial result is supported.
     */
    public int getPartialResultCount() {
        Integer value = mCharacteristics.get(CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT);
        if (value == null) {
            // Optional key. Default value is 1 if key is missing.
            return 1;
        }
        return value;
    }

    /**
     * Get the exposure time value and clamp to the range if needed.
     *
     * @param exposure Input exposure time value to check.
     * @return Exposure value in the legal range.
     */
    public long getExposureClampToRange(long exposure) {
        long minExposure = getExposureMinimumOrDefault(Long.MAX_VALUE);
        long maxExposure = getExposureMaximumOrDefault(Long.MIN_VALUE);
        if (minExposure > SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST) {
            failKeyCheck(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE,
                    String.format(
                    "Min value %d is too large, set to maximal legal value %d",
                    minExposure, SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST));
            minExposure = SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST;
        }
        if (maxExposure < SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST) {
            failKeyCheck(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE,
                    String.format(
                    "Max value %d is too small, set to minimal legal value %d",
                    maxExposure, SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST));
            maxExposure = SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST;
        }

        return Math.max(minExposure, Math.min(maxExposure, exposure));
    }

    /**
     * Check if the camera device support focuser.
     *
     * @return true if camera device support focuser, false otherwise.
     */
    public boolean hasFocuser() {
        if (areKeysAvailable(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE)) {
            // LEGACY devices don't have lens.info.minimumFocusDistance, so guard this query
            return (getMinimumFocusDistanceChecked() > 0);
        } else {
            // Check available AF modes
            int[] availableAfModes = mCharacteristics.get(
                    CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);

            if (availableAfModes == null) {
                return false;
            }

            // Assume that if we have an AF mode which doesn't ignore AF trigger, we have a focuser
            boolean hasFocuser = false;
            loop: for (int mode : availableAfModes) {
                switch (mode) {
                    case CameraMetadata.CONTROL_AF_MODE_AUTO:
                    case CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE:
                    case CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_VIDEO:
                    case CameraMetadata.CONTROL_AF_MODE_MACRO:
                        hasFocuser = true;
                        break loop;
                }
            }

            return hasFocuser;
        }
    }

    /**
     * Check if the camera device has flash unit.
     * @return true if flash unit is available, false otherwise.
     */
    public boolean hasFlash() {
        return getFlashInfoChecked();
    }

    /**
     * Get minimum focus distance.
     *
     * @return minimum focus distance, 0 if minimum focus distance is invalid.
     */
    public float getMinimumFocusDistanceChecked() {
        Key<Float> key = CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE;
        Float minFocusDistance;

        /**
         * android.lens.info.minimumFocusDistance - required for FULL and MANUAL_SENSOR-capable
         *   devices; optional for all other devices.
         */
        if (isHardwareLevelFull() || isCapabilitySupported(
                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
            minFocusDistance = getValueFromKeyNonNull(key);
        } else {
            minFocusDistance = mCharacteristics.get(key);
        }

        if (minFocusDistance == null) {
            return 0.0f;
        }

        checkTrueForKey(key, " minFocusDistance value shouldn't be negative",
                minFocusDistance >= 0);
        if (minFocusDistance < 0) {
            minFocusDistance = 0.0f;
        }

        return minFocusDistance;
    }

    /**
     * Get focusDistanceCalibration.
     *
     * @return focusDistanceCalibration, UNCALIBRATED if value is invalid.
     */
    public int getFocusDistanceCalibrationChecked() {
        Key<Integer> key = CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION;
        Integer calibration = getValueFromKeyNonNull(key);

        if (calibration == null) {
            return CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
        }

        checkTrueForKey(key, " value is out of range" ,
                calibration >= CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED &&
                calibration <= CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED);

        return calibration;
    }

    /**
     * Get max AE regions and do sanity check.
     *
     * @return AE max regions supported by the camera device
     */
    public int getAeMaxRegionsChecked() {
        Integer regionCount = getValueFromKeyNonNull(CameraCharacteristics.CONTROL_MAX_REGIONS_AE);
        if (regionCount == null) {
            return 0;
        }
        return regionCount;
    }

    /**
     * Get max AWB regions and do sanity check.
     *
     * @return AWB max regions supported by the camera device
     */
    public int getAwbMaxRegionsChecked() {
        Integer regionCount = getValueFromKeyNonNull(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB);
        if (regionCount == null) {
            return 0;
        }
        return regionCount;
    }

    /**
     * Get max AF regions and do sanity check.
     *
     * @return AF max regions supported by the camera device
     */
    public int getAfMaxRegionsChecked() {
        Integer regionCount = getValueFromKeyNonNull(CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
        if (regionCount == null) {
            return 0;
        }
        return regionCount;
    }
    /**
     * Get the available anti-banding modes.
     *
     * @return The array contains available anti-banding modes.
     */
    public int[] getAeAvailableAntiBandingModesChecked() {
        Key<int[]> key = CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES;
        int[] modes = getValueFromKeyNonNull(key);

        boolean foundAuto = false;
        boolean found50Hz = false;
        boolean found60Hz = false;
        for (int mode : modes) {
            checkTrueForKey(key, "mode value " + mode + " is out if range",
                    mode >= CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_OFF ||
                    mode <= CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_AUTO);
            if (mode == CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_AUTO) {
                foundAuto = true;
            } else if (mode == CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_50HZ) {
                found50Hz = true;
            } else if (mode == CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_60HZ) {
                found60Hz = true;
            }
        }
        // Must contain AUTO mode or one of 50/60Hz mode.
        checkTrueForKey(key, "Either AUTO mode or both 50HZ/60HZ mode should present",
                foundAuto || (found50Hz && found60Hz));

        return modes;
    }

    /**
     * Check if the antibanding OFF mode is supported.
     *
     * @return true if antibanding OFF mode is supported, false otherwise.
     */
    public boolean isAntiBandingOffModeSupported() {
        List<Integer> antiBandingModes =
                Arrays.asList(CameraTestUtils.toObject(getAeAvailableAntiBandingModesChecked()));

        return antiBandingModes.contains(CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_OFF);
    }

    public Boolean getFlashInfoChecked() {
        Key<Boolean> key = CameraCharacteristics.FLASH_INFO_AVAILABLE;
        Boolean hasFlash = getValueFromKeyNonNull(key);

        // In case the failOnKey only gives warning.
        if (hasFlash == null) {
            return false;
        }

        return hasFlash;
    }

    public int[] getAvailableTestPatternModesChecked() {
        Key<int[]> key =
                CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES;
        int[] modes = getValueFromKeyNonNull(key);

        if (modes == null) {
            return new int[0];
        }

        int expectValue = CameraCharacteristics.SENSOR_TEST_PATTERN_MODE_OFF;
        Integer[] boxedModes = CameraTestUtils.toObject(modes);
        checkTrueForKey(key, " value must contain OFF mode",
                Arrays.asList(boxedModes).contains(expectValue));

        return modes;
    }

    /**
     * Get available thumbnail sizes and do the sanity check.
     *
     * @return The array of available thumbnail sizes
     */
    public Size[] getAvailableThumbnailSizesChecked() {
        Key<Size[]> key = CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES;
        Size[] sizes = getValueFromKeyNonNull(key);
        final List<Size> sizeList = Arrays.asList(sizes);

        // Size must contain (0, 0).
        checkTrueForKey(key, "size should contain (0, 0)", sizeList.contains(new Size(0, 0)));

        // Each size must be distinct.
        checkElementDistinct(key, sizeList);

        // Must be sorted in ascending order by area, by width if areas are same.
        List<Size> orderedSizes =
                CameraTestUtils.getAscendingOrderSizes(sizeList, /*ascending*/true);
        checkTrueForKey(key, "Sizes should be in ascending order: Original " + sizeList.toString()
                + ", Expected " + orderedSizes.toString(), orderedSizes.equals(sizeList));

        // TODO: Aspect ratio match, need wait for android.scaler.availableStreamConfigurations
        // implementation see b/12958122.

        return sizes;
    }

    /**
     * Get available focal lengths and do the sanity check.
     *
     * @return The array of available focal lengths
     */
    public float[] getAvailableFocalLengthsChecked() {
        Key<float[]> key = CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS;
        float[] focalLengths = getValueFromKeyNonNull(key);

        checkTrueForKey(key, "Array should contain at least one element", focalLengths.length >= 1);

        for (int i = 0; i < focalLengths.length; i++) {
            checkTrueForKey(key,
                    String.format("focalLength[%d] %f should be positive.", i, focalLengths[i]),
                    focalLengths[i] > 0);
        }
        checkElementDistinct(key, Arrays.asList(CameraTestUtils.toObject(focalLengths)));

        return focalLengths;
    }

    /**
     * Get available apertures and do the sanity check.
     *
     * @return The non-null array of available apertures
     */
    public float[] getAvailableAperturesChecked() {
        Key<float[]> key = CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES;
        float[] apertures = getValueFromKeyNonNull(key);

        checkTrueForKey(key, "Array should contain at least one element", apertures.length >= 1);

        for (int i = 0; i < apertures.length; i++) {
            checkTrueForKey(key,
                    String.format("apertures[%d] %f should be positive.", i, apertures[i]),
                    apertures[i] > 0);
        }
        checkElementDistinct(key, Arrays.asList(CameraTestUtils.toObject(apertures)));

        return apertures;
    }

    /**
     * Get and check the available hot pixel map modes.
     *
     * @return the available hot pixel map modes
     */
    public int[] getAvailableHotPixelModesChecked() {
        Key<int[]> key = CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES;
        int[] modes = getValueFromKeyNonNull(key);

        if (modes == null) {
            return new int[0];
        }

        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
        if (isHardwareLevelFull()) {
            checkTrueForKey(key, "Full-capability camera devices must support FAST mode",
                    modeList.contains(CameraMetadata.HOT_PIXEL_MODE_FAST));
        }
        checkElementDistinct(key, modeList);
        checkArrayValuesInRange(key, modes, CameraMetadata.HOT_PIXEL_MODE_OFF,
                CameraMetadata.HOT_PIXEL_MODE_HIGH_QUALITY);

        return modes;
    }

    /**
     * Get and check available face detection modes.
     *
     * @return The non-null array of available face detection modes
     */
    public int[] getAvailableFaceDetectModesChecked() {
        Key<int[]> key = CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES;
        int[] modes = getValueFromKeyNonNull(key);

        if (modes == null) {
            return new int[0];
        }

        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
        checkTrueForKey(key, "Array should contain OFF mode",
                modeList.contains(CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF));
        checkElementDistinct(key, modeList);
        checkArrayValuesInRange(key, modes, CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF,
                CameraMetadata.STATISTICS_FACE_DETECT_MODE_FULL);

        return modes;
    }

    /**
     * Get and check max face detected count.
     *
     * @return max number of faces that can be detected
     */
    public int getMaxFaceCountChecked() {
        Key<Integer> key = CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT;
        Integer count = getValueFromKeyNonNull(key);

        if (count == null) {
            return 0;
        }

        List<Integer> faceDetectModes =
                Arrays.asList(CameraTestUtils.toObject(getAvailableFaceDetectModesChecked()));
        if (faceDetectModes.contains(CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF) &&
                faceDetectModes.size() == 1) {
            checkTrueForKey(key, " value must be 0 if only OFF mode is supported in "
                    + "availableFaceDetectionModes", count == 0);
        } else {
            int maxFaceCountAtLeast = STATISTICS_INFO_MAX_FACE_COUNT_MIN_AT_LEAST;

            // Legacy mode may support fewer than STATISTICS_INFO_MAX_FACE_COUNT_MIN_AT_LEAST faces.
            if (isHardwareLevelLegacy()) {
                maxFaceCountAtLeast = 1;
            }
            checkTrueForKey(key, " value must be no less than " + maxFaceCountAtLeast + " if SIMPLE"
                    + "or FULL is also supported in availableFaceDetectionModes",
                    count >= maxFaceCountAtLeast);
        }

        return count;
    }

    /**
     * Get and check the available tone map modes.
     *
     * @return the available tone map modes
     */
    public int[] getAvailableToneMapModesChecked() {
        Key<int[]> key = CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES;
        int[] modes = getValueFromKeyNonNull(key);

        if (modes == null) {
            return new int[0];
        }

        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
        checkTrueForKey(key, " Camera devices must always support FAST mode",
                modeList.contains(CameraMetadata.TONEMAP_MODE_FAST));
        if (isCapabilitySupported(
                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING)) {
            checkTrueForKey(key, "MANUAL_POST_PROCESSING supported camera devices must support"
                    + "CONTRAST_CURVE mode",
                    modeList.contains(CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE) &&
                    modeList.contains(CameraMetadata.TONEMAP_MODE_FAST));
        }
        checkElementDistinct(key, modeList);
        checkArrayValuesInRange(key, modes, CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE,
                CameraMetadata.TONEMAP_MODE_HIGH_QUALITY);

        return modes;
    }

    /**
     * Get and check max tonemap curve point.
     *
     * @return Max tonemap curve points.
     */
    public int getMaxTonemapCurvePointChecked() {
        Key<Integer> key = CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS;
        Integer count = getValueFromKeyNonNull(key);

        if (count == null) {
            return 0;
        }

        List<Integer> modeList =
                Arrays.asList(CameraTestUtils.toObject(getAvailableToneMapModesChecked()));
        if (modeList.contains(CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE)) {
            checkTrueForKey(key, "Full-capability camera device must support maxCurvePoints "
                    + ">= " + TONEMAP_MAX_CURVE_POINTS_AT_LEAST,
                    count >= TONEMAP_MAX_CURVE_POINTS_AT_LEAST);
        }

        return count;
    }

    /**
     * Get and check pixel array size.
     */
    public Size getPixelArraySizeChecked() {
        Key<Size> key = CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE;
        Size pixelArray = getValueFromKeyNonNull(key);
        if (pixelArray == null) {
            return new Size(0, 0);
        }

        return pixelArray;
    }

    /**
     * Get and check active array size.
     */
    public Rect getActiveArraySizeChecked() {
        Key<Rect> key = CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE;
        Rect activeArray = getValueFromKeyNonNull(key);

        if (activeArray == null) {
            return new Rect(0, 0, 0, 0);
        }

        Size pixelArraySize = getPixelArraySizeChecked();
        checkTrueForKey(key, "values left/top are invalid", activeArray.left >= 0 && activeArray.top >= 0);
        checkTrueForKey(key, "values width/height are invalid",
                activeArray.width() <= pixelArraySize.getWidth() &&
                activeArray.height() <= pixelArraySize.getHeight());

        return activeArray;
    }

    /**
     * Get the sensitivity value and clamp to the range if needed.
     *
     * @param sensitivity Input sensitivity value to check.
     * @return Sensitivity value in legal range.
     */
    public int getSensitivityClampToRange(int sensitivity) {
        int minSensitivity = getSensitivityMinimumOrDefault(Integer.MAX_VALUE);
        int maxSensitivity = getSensitivityMaximumOrDefault(Integer.MIN_VALUE);
        if (minSensitivity > SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST) {
            failKeyCheck(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE,
                    String.format(
                    "Min value %d is too large, set to maximal legal value %d",
                    minSensitivity, SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST));
            minSensitivity = SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST;
        }
        if (maxSensitivity < SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST) {
            failKeyCheck(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE,
                    String.format(
                    "Max value %d is too small, set to minimal legal value %d",
                    maxSensitivity, SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST));
            maxSensitivity = SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST;
        }

        return Math.max(minSensitivity, Math.min(maxSensitivity, sensitivity));
    }

    /**
     * Get maxAnalogSensitivity for a camera device.
     * <p>
     * This is only available for FULL capability device, return 0 if it is unavailable.
     * </p>
     *
     * @return maxAnalogSensitivity, 0 if it is not available.
     */
    public int getMaxAnalogSensitivityChecked() {

        Key<Integer> key = CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY;
        Integer maxAnalogsensitivity = mCharacteristics.get(key);
        if (maxAnalogsensitivity == null) {
            if (isHardwareLevelFull()) {
                Assert.fail("Full device should report max analog sensitivity");
            }
            return 0;
        }

        int minSensitivity = getSensitivityMinimumOrDefault();
        int maxSensitivity = getSensitivityMaximumOrDefault();
        checkTrueForKey(key, " Max analog sensitivity " + maxAnalogsensitivity
                + " should be no larger than max sensitivity " + maxSensitivity,
                maxAnalogsensitivity <= maxSensitivity);
        checkTrueForKey(key, " Max analog sensitivity " + maxAnalogsensitivity
                + " should be larger than min sensitivity " + maxSensitivity,
                maxAnalogsensitivity > minSensitivity);

        return maxAnalogsensitivity;
    }

    /**
     * Get hyperfocalDistance and do the sanity check.
     * <p>
     * Note that, this tag is optional, will return -1 if this tag is not
     * available.
     * </p>
     *
     * @return hyperfocalDistance of this device, -1 if this tag is not available.
     */
    public float getHyperfocalDistanceChecked() {
        Key<Float> key = CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE;
        Float hyperfocalDistance = getValueFromKeyNonNull(key);
        if (hyperfocalDistance == null) {
            return -1;
        }

        if (hasFocuser()) {
            float minFocusDistance = getMinimumFocusDistanceChecked();
            checkTrueForKey(key, String.format(" hyperfocal distance %f should be in the range of"
                    + " should be in the range of (%f, %f]", hyperfocalDistance, 0.0f,
                    minFocusDistance),
                    hyperfocalDistance > 0 && hyperfocalDistance <= minFocusDistance);
        }

        return hyperfocalDistance;
    }

    /**
     * Get the minimum value for a sensitivity range from android.sensor.info.sensitivityRange.
     *
     * <p>If the camera is incorrectly reporting values, log a warning and return
     * the default value instead, which is the largest minimum value required to be supported
     * by all camera devices.</p>
     *
     * @return The value reported by the camera device or the defaultValue otherwise.
     */
    public int getSensitivityMinimumOrDefault() {
        return getSensitivityMinimumOrDefault(SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST);
    }

    /**
     * Get the minimum value for a sensitivity range from android.sensor.info.sensitivityRange.
     *
     * <p>If the camera is incorrectly reporting values, log a warning and return
     * the default value instead.</p>
     *
     * @param defaultValue Value to return if no legal value is available
     * @return The value reported by the camera device or the defaultValue otherwise.
     */
    public int getSensitivityMinimumOrDefault(int defaultValue) {
        Range<Integer> range = getValueFromKeyNonNull(
                CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE);
        if (range == null) {
            failKeyCheck(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE,
                    "had no valid minimum value; using default of " + defaultValue);
            return defaultValue;
        }
        return range.getLower();
    }

    /**
     * Get the maximum value for a sensitivity range from android.sensor.info.sensitivityRange.
     *
     * <p>If the camera is incorrectly reporting values, log a warning and return
     * the default value instead, which is the smallest maximum value required to be supported
     * by all camera devices.</p>
     *
     * @return The value reported by the camera device or the defaultValue otherwise.
     */
    public int getSensitivityMaximumOrDefault() {
        return getSensitivityMaximumOrDefault(SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST);
    }

    /**
     * Get the maximum value for a sensitivity range from android.sensor.info.sensitivityRange.
     *
     * <p>If the camera is incorrectly reporting values, log a warning and return
     * the default value instead.</p>
     *
     * @param defaultValue Value to return if no legal value is available
     * @return The value reported by the camera device or the defaultValue otherwise.
     */
    public int getSensitivityMaximumOrDefault(int defaultValue) {
        Range<Integer> range = getValueFromKeyNonNull(
                CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE);
        if (range == null) {
            failKeyCheck(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE,
                    "had no valid maximum value; using default of " + defaultValue);
            return defaultValue;
        }
        return range.getUpper();
    }

    /**
     * Get the minimum value for an exposure range from android.sensor.info.exposureTimeRange.
     *
     * <p>If the camera is incorrectly reporting values, log a warning and return
     * the default value instead.</p>
     *
     * @param defaultValue Value to return if no legal value is available
     * @return The value reported by the camera device or the defaultValue otherwise.
     */
    public long getExposureMinimumOrDefault(long defaultValue) {
        Range<Long> range = getValueFromKeyNonNull(
                CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
        if (range == null) {
            failKeyCheck(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE,
                    "had no valid minimum value; using default of " + defaultValue);
            return defaultValue;
        }
        return range.getLower();
    }

    /**
     * Get the minimum value for an exposure range from android.sensor.info.exposureTimeRange.
     *
     * <p>If the camera is incorrectly reporting values, log a warning and return
     * the default value instead, which is the largest minimum value required to be supported
     * by all camera devices.</p>
     *
     * @return The value reported by the camera device or the defaultValue otherwise.
     */
    public long getExposureMinimumOrDefault() {
        return getExposureMinimumOrDefault(SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST);
    }

    /**
     * Get the maximum value for an exposure range from android.sensor.info.exposureTimeRange.
     *
     * <p>If the camera is incorrectly reporting values, log a warning and return
     * the default value instead.</p>
     *
     * @param defaultValue Value to return if no legal value is available
     * @return The value reported by the camera device or the defaultValue otherwise.
     */
    public long getExposureMaximumOrDefault(long defaultValue) {
        Range<Long> range = getValueFromKeyNonNull(
                CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
        if (range == null) {
            failKeyCheck(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE,
                    "had no valid maximum value; using default of " + defaultValue);
            return defaultValue;
        }
        return range.getUpper();
    }

    /**
     * Get the maximum value for an exposure range from android.sensor.info.exposureTimeRange.
     *
     * <p>If the camera is incorrectly reporting values, log a warning and return
     * the default value instead, which is the smallest maximum value required to be supported
     * by all camera devices.</p>
     *
     * @return The value reported by the camera device or the defaultValue otherwise.
     */
    public long getExposureMaximumOrDefault() {
        return getExposureMaximumOrDefault(SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST);
    }

    /**
     * Get aeAvailableModes and do the sanity check.
     *
     * <p>Depending on the check level this class has, for WAR or COLLECT levels,
     * If the aeMode list is invalid, return an empty mode array. The the caller doesn't
     * have to abort the execution even the aeMode list is invalid.</p>
     * @return AE available modes
     */
    public int[] getAeAvailableModesChecked() {
        Key<int[]> modesKey = CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES;
        int[] modes = getValueFromKeyNonNull(modesKey);
        if (modes == null) {
            modes = new int[0];
        }
        List<Integer> modeList = new ArrayList<Integer>();
        for (int mode : modes) {
            modeList.add(mode);
        }
        checkTrueForKey(modesKey, "value is empty", !modeList.isEmpty());

        // All camera device must support ON
        checkTrueForKey(modesKey, "values " + modeList.toString() + " must contain ON mode",
                modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON));

        // All camera devices with flash units support ON_AUTO_FLASH and ON_ALWAYS_FLASH
        Key<Boolean> flashKey= CameraCharacteristics.FLASH_INFO_AVAILABLE;
        Boolean hasFlash = getValueFromKeyNonNull(flashKey);
        if (hasFlash == null) {
            hasFlash = false;
        }
        if (hasFlash) {
            boolean flashModeConsistentWithFlash =
                    modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH) &&
                    modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
            checkTrueForKey(modesKey,
                    "value must contain ON_AUTO_FLASH and ON_ALWAYS_FLASH and  when flash is" +
                    "available", flashModeConsistentWithFlash);
        } else {
            boolean flashModeConsistentWithoutFlash =
                    !(modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH) ||
                    modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH) ||
                    modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE));
            checkTrueForKey(modesKey,
                    "value must not contain ON_AUTO_FLASH, ON_ALWAYS_FLASH and" +
                    "ON_AUTO_FLASH_REDEYE when flash is unavailable",
                    flashModeConsistentWithoutFlash);
        }

        // FULL mode camera devices always support OFF mode.
        boolean condition =
                !isHardwareLevelFull() || modeList.contains(CameraMetadata.CONTROL_AE_MODE_OFF);
        checkTrueForKey(modesKey, "Full capability device must have OFF mode", condition);

        // Boundary check.
        for (int mode : modes) {
            checkTrueForKey(modesKey, "Value " + mode + " is out of bound",
                    mode >= CameraMetadata.CONTROL_AE_MODE_OFF
                    && mode <= CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE);
        }

        return modes;
    }

    /**
     * Get available AWB modes and do the sanity check.
     *
     * @return array that contains available AWB modes, empty array if awbAvailableModes is
     * unavailable.
     */
    public int[] getAwbAvailableModesChecked() {
        Key<int[]> key =
                CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES;
        int[] awbModes = getValueFromKeyNonNull(key);

        if (awbModes == null) {
            return new int[0];
        }

        List<Integer> modesList = Arrays.asList(CameraTestUtils.toObject(awbModes));
        checkTrueForKey(key, " All camera devices must support AUTO mode",
                modesList.contains(CameraMetadata.CONTROL_AWB_MODE_AUTO));
        if (isHardwareLevelFull()) {
            checkTrueForKey(key, " Full capability camera devices must support OFF mode",
                    modesList.contains(CameraMetadata.CONTROL_AWB_MODE_OFF));
        }

        return awbModes;
    }

    /**
     * Get available AF modes and do the sanity check.
     *
     * @return array that contains available AF modes, empty array if afAvailableModes is
     * unavailable.
     */
    public int[] getAfAvailableModesChecked() {
        Key<int[]> key =
                CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES;
        int[] afModes = getValueFromKeyNonNull(key);

        if (afModes == null) {
            return new int[0];
        }

        List<Integer> modesList = Arrays.asList(CameraTestUtils.toObject(afModes));
        if (isHardwareLevelLimitedOrBetter()) {
            // Some LEGACY mode devices do not support AF OFF
            checkTrueForKey(key, " All camera devices must support OFF mode",
                    modesList.contains(CameraMetadata.CONTROL_AF_MODE_OFF));
        }
        if (hasFocuser()) {
            checkTrueForKey(key, " Camera devices that have focuser units must support AUTO mode",
                    modesList.contains(CameraMetadata.CONTROL_AF_MODE_AUTO));
        }

        return afModes;
    }

    /**
     * Get supported raw output sizes and do the check.
     *
     * @return Empty size array if raw output is not supported
     */
    public Size[] getRawOutputSizesChecked() {
        return getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR,
                StreamDirection.Output);
    }

    /**
     * Get supported jpeg output sizes and do the check.
     *
     * @return Empty size array if jpeg output is not supported
     */
    public Size[] getJpegOutputSizeChecked() {
        return getAvailableSizesForFormatChecked(ImageFormat.JPEG,
                StreamDirection.Output);
    }

    /**
     * Used to determine the stream direction for various helpers that look up
     * format or size information.
     */
    public enum StreamDirection {
        /** Stream is used with {@link android.hardware.camera2.CameraDevice#configureOutputs} */
        Output,
        /** Stream is used with {@code CameraDevice#configureInputs} -- NOT YET PUBLIC */
        Input
    }

    /**
     * Get available sizes for given user-defined format.
     *
     * <p><strong>Does not</strong> work with implementation-defined format.</p>
     *
     * @param format The format for the requested size array.
     * @param direction The stream direction, input or output.
     * @return The sizes of the given format, empty array if no available size is found.
     */
    public Size[] getAvailableSizesForFormatChecked(int format, StreamDirection direction) {
        Key<StreamConfigurationMap> key =
                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP;
        StreamConfigurationMap config = getValueFromKeyNonNull(key);

        if (config == null) {
            return new Size[0];
        }

        android.util.Size[] utilSizes;

        switch (direction) {
            case Output:
                utilSizes = config.getOutputSizes(format);
                break;
            case Input:
                utilSizes = null;
                break;
            default:
                throw new IllegalArgumentException("direction must be output or input");
        }

        // TODO: Get rid of android.util.Size
        if (utilSizes == null) {
            Log.i(TAG, "This camera doesn't support format " + format + " for " + direction);
            return new Size[0];
        }

        Size[] sizes = new Size[utilSizes.length];
        for (int i = 0; i < utilSizes.length; ++i) {
            sizes[i] = new Size(utilSizes[i].getWidth(), utilSizes[i].getHeight());
        }

        return sizes;
    }

    /**
     * Get available AE target fps ranges.
     *
     * @return Empty int array if aeAvailableTargetFpsRanges is invalid.
     */
    @SuppressWarnings("raw")
    public Range<Integer>[] getAeAvailableTargetFpsRangesChecked() {
        Key<Range<Integer>[]> key =
                CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
        Range<Integer>[] fpsRanges = getValueFromKeyNonNull(key);

        if (fpsRanges == null) {
            return new Range[0];
        }

        // Round down to 2 boundary if it is not integer times of 2, to avoid array out of bound
        // in case the above check fails.
        int fpsRangeLength = fpsRanges.length;
        int minFps, maxFps;
        long maxFrameDuration = getMaxFrameDurationChecked();
        for (int i = 0; i < fpsRangeLength; i += 1) {
            minFps = fpsRanges[i].getLower();
            maxFps = fpsRanges[i].getUpper();
            checkTrueForKey(key, " min fps must be no larger than max fps!",
                    minFps > 0 && maxFps >= minFps);
            long maxDuration = (long) (1e9 / minFps);
            checkTrueForKey(key, String.format(
                    " the frame duration %d for min fps %d must smaller than maxFrameDuration %d",
                    maxDuration, minFps, maxFrameDuration), maxDuration <= maxFrameDuration);
        }

        return fpsRanges;
    }

    /**
     * Get max frame duration.
     *
     * @return 0 if maxFrameDuration is null
     */
    public long getMaxFrameDurationChecked() {
        Key<Long> key =
                CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION;
        Long maxDuration = getValueFromKeyNonNull(key);

        if (maxDuration == null) {
            return 0;
        }

        return maxDuration;
    }

    /**
     * Get available minimal frame durations for a given user-defined format.
     *
     * <p><strong>Does not</strong> work with implementation-defined format.</p>
     *
     * @param format One of the format from {@link ImageFormat}.
     * @return HashMap of minimal frame durations for different sizes, empty HashMap
     *         if availableMinFrameDurations is null.
     */
    public HashMap<Size, Long> getAvailableMinFrameDurationsForFormatChecked(int format) {

        HashMap<Size, Long> minDurationMap = new HashMap<Size, Long>();

        Key<StreamConfigurationMap> key =
                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP;
        StreamConfigurationMap config = getValueFromKeyNonNull(key);

        if (config == null) {
            return minDurationMap;
        }

        for (android.util.Size size : config.getOutputSizes(format)) {
            long minFrameDuration = config.getOutputMinFrameDuration(format, size);

            if (minFrameDuration != 0) {
                minDurationMap.put(new Size(size.getWidth(), size.getHeight()), minFrameDuration);
            }
        }

        return minDurationMap;
    }

    public int[] getAvailableEdgeModesChecked() {
        Key<int[]> key = CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES;
        int[] edgeModes = getValueFromKeyNonNull(key);

        if (edgeModes == null) {
            return new int[0];
        }

        // Full device should always include OFF and FAST
        if (isHardwareLevelFull()) {
            List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(edgeModes));
            checkTrueForKey(key, "Full device must contain OFF and FAST edge modes",
                    modeList.contains(CameraMetadata.EDGE_MODE_OFF) &&
                    modeList.contains(CameraMetadata.EDGE_MODE_FAST));
        }

        return edgeModes;
    }

    public int[] getAvailableNoiseReductionModesChecked() {
        Key<int[]> key =
                CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
        int[] noiseReductionModes = getValueFromKeyNonNull(key);

        if (noiseReductionModes == null) {
            return new int[0];
        }

        // Full device should always include OFF and FAST
        if (isHardwareLevelFull()) {
            List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(noiseReductionModes));
            checkTrueForKey(key, "Full device must contain OFF and FAST noise reduction modes",
                    modeList.contains(CameraMetadata.NOISE_REDUCTION_MODE_OFF) &&
                    modeList.contains(CameraMetadata.NOISE_REDUCTION_MODE_FAST));
        }

        return noiseReductionModes;
    }

    /**
     * Get value of key android.control.aeCompensationStep and do the sanity check.
     *
     * @return default value if the value is null.
     */
    public Rational getAeCompensationStepChecked() {
        Key<Rational> key =
                CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP;
        Rational compensationStep = getValueFromKeyNonNull(key);

        if (compensationStep == null) {
            // Return default step.
            return CONTROL_AE_COMPENSATION_STEP_DEFAULT;
        }

        // Legacy devices don't have a minimum step requirement
        if (isHardwareLevelLimitedOrBetter()) {
            float compensationStepF =
                    (float) compensationStep.getNumerator() / compensationStep.getDenominator();
            checkTrueForKey(key, " value must be no more than 1/2", compensationStepF <= 0.5f);
        }

        return compensationStep;
    }

    /**
     * Get value of key android.control.aeCompensationRange and do the sanity check.
     *
     * @return default value if the value is null or malformed.
     */
    public Range<Integer> getAeCompensationRangeChecked() {
        Key<Range<Integer>> key =
                CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE;
        Range<Integer> compensationRange = getValueFromKeyNonNull(key);
        Rational compensationStep = getAeCompensationStepChecked();
        float compensationStepF = compensationStep.floatValue();
        final Range<Integer> DEFAULT_RANGE = Range.create(
                (int)(CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MIN / compensationStepF),
                (int)(CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MAX / compensationStepF));
        final Range<Integer> ZERO_RANGE = Range.create(0, 0);
        if (compensationRange == null) {
            return ZERO_RANGE;
        }

        // Legacy devices don't have a minimum range requirement
        if (isHardwareLevelLimitedOrBetter() && !compensationRange.equals(ZERO_RANGE)) {
            checkTrueForKey(key, " range value must be at least " + DEFAULT_RANGE
                    + ", actual " + compensationRange + ", compensation step " + compensationStep,
                   compensationRange.getLower() <= DEFAULT_RANGE.getLower() &&
                   compensationRange.getUpper() >= DEFAULT_RANGE.getUpper());
        }

        return compensationRange;
    }

    /**
     * Get availableVideoStabilizationModes and do the sanity check.
     *
     * @return available video stabilization modes, empty array if it is unavailable.
     */
    public int[] getAvailableVideoStabilizationModesChecked() {
        Key<int[]> key =
                CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES;
        int[] modes = getValueFromKeyNonNull(key);

        if (modes == null) {
            return new int[0];
        }

        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
        checkTrueForKey(key, " All device should support OFF mode",
                modeList.contains(CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF));
        checkArrayValuesInRange(key, modes,
                CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF,
                CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_ON);

        return modes;
    }

    /**
     * Get availableOpticalStabilization and do the sanity check.
     *
     * @return available optical stabilization modes, empty array if it is unavailable.
     */
    public int[] getAvailableOpticalStabilizationChecked() {
        Key<int[]> key =
                CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION;
        int[] modes = getValueFromKeyNonNull(key);

        if (modes == null) {
            return new int[0];
        }

        checkArrayValuesInRange(key, modes,
                CameraMetadata.LENS_OPTICAL_STABILIZATION_MODE_OFF,
                CameraMetadata.LENS_OPTICAL_STABILIZATION_MODE_ON);

        return modes;
    }

    /**
     * Get the scaler's max digital zoom ({@code >= 1.0f}) ratio between crop and active array
     * @return the max zoom ratio, or {@code 1.0f} if the value is unavailable
     */
    public float getAvailableMaxDigitalZoomChecked() {
        Key<Float> key =
                CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM;

        Float maxZoom = getValueFromKeyNonNull(key);
        if (maxZoom == null) {
            return 1.0f;
        }

        checkTrueForKey(key, " max digital zoom should be no less than 1",
                maxZoom >= 1.0f && !Float.isNaN(maxZoom) && !Float.isInfinite(maxZoom));

        return maxZoom;
    }

    public int[] getAvailableSceneModesChecked() {
        Key<int[]> key =
                CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES;
        int[] modes = getValueFromKeyNonNull(key);

        if (modes == null) {
            return new int[0];
        }

        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
        // FACE_PRIORITY must be included if face detection is supported.
        if (areKeysAvailable(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT) &&
                getMaxFaceCountChecked() > 0) {
            checkTrueForKey(key, " FACE_PRIORITY must be included if face detection is supported",
                    modeList.contains(CameraMetadata.CONTROL_SCENE_MODE_FACE_PRIORITY));
        }

        return modes;
    }

    public int[] getAvailableEffectModesChecked() {
        Key<int[]> key =
                CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS;
        int[] modes = getValueFromKeyNonNull(key);

        if (modes == null) {
            return new int[0];
        }

        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
        // OFF must be included.
        checkTrueForKey(key, " OFF must be included",
                modeList.contains(CameraMetadata.CONTROL_EFFECT_MODE_OFF));

        return modes;
    }

    /**
     * Get and check the available color aberration modes
     *
     * @return the available color aberration modes
     */
    public int[] getAvailableColorAberrationModesChecked() {
        Key<int[]> key =
                CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES;
        int[] modes = getValueFromKeyNonNull(key);

        if (modes == null) {
            return new int[0];
        }

        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
        checkTrueForKey(key, " Camera devices must always support either OFF or FAST mode",
                modeList.contains(CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_OFF) ||
                modeList.contains(CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_FAST));
        checkElementDistinct(key, modeList);
        checkArrayValuesInRange(key, modes,
                CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_OFF,
                CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY);

        return modes;
    }

    /**
     * Get max pipeline depth and do the sanity check.
     *
     * @return max pipeline depth, default value if it is not available.
     */
    public byte getPipelineMaxDepthChecked() {
        Key<Byte> key =
                CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH;
        Byte maxDepth = getValueFromKeyNonNull(key);

        if (maxDepth == null) {
            return REQUEST_PIPELINE_MAX_DEPTH_MAX;
        }

        checkTrueForKey(key, " max pipeline depth should be no larger than "
                + REQUEST_PIPELINE_MAX_DEPTH_MAX, maxDepth <= REQUEST_PIPELINE_MAX_DEPTH_MAX);

        return maxDepth;
    }

    /**
     * Get available capabilities and do the sanity check.
     *
     * @return reported available capabilities list, empty list if the value is unavailable.
     */
    public List<Integer> getAvailableCapabilitiesChecked() {
        Key<int[]> key =
                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES;
        int[] availableCaps = getValueFromKeyNonNull(key);
        List<Integer> capList;

        if (availableCaps == null) {
            return new ArrayList<Integer>();
        }

        checkArrayValuesInRange(key, availableCaps,
                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);
        capList = Arrays.asList(CameraTestUtils.toObject(availableCaps));
        return capList;
    }

    /**
     * Determine whether the current device supports a capability or not.
     *
     * @param capability (non-negative)
     *
     * @return {@code true} if the capability is supported, {@code false} otherwise.
     *
     * @throws IllegalArgumentException if {@code capability} was negative
     *
     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
     */
    public boolean isCapabilitySupported(int capability) {
        if (capability < 0) {
            throw new IllegalArgumentException("capability must be non-negative");
        }

        List<Integer> availableCapabilities = getAvailableCapabilitiesChecked();

        return availableCapabilities.contains(capability);
    }

    /**
     * Determine whether or not all the {@code keys} are available characteristics keys
     * (as in {@link CameraCharacteristics#getKeys}.
     *
     * <p>If this returns {@code true}, then querying for this key from a characteristics
     * object will always return a non-{@code null} value.</p>
     *
     * @param keys collection of camera characteristics keys
     * @return whether or not all characteristics keys are available
     */
    public final boolean areCharacteristicsKeysAvailable(
            Collection<CameraCharacteristics.Key<?>> keys) {
        return mCharacteristics.getKeys().containsAll(keys);
    }

    /**
     * Determine whether or not all the {@code keys} are available result keys
     * (as in {@link CameraCharacteristics#getAvailableCaptureResultKeys}.
     *
     * <p>If this returns {@code true}, then querying for this key from a result
     * object will almost always return a non-{@code null} value.</p>
     *
     * <p>In some cases (e.g. lens shading map), the request must have additional settings
     * configured in order for the key to correspond to a value.</p>
     *
     * @param keys collection of capture result keys
     * @return whether or not all result keys are available
     */
    public final boolean areResultKeysAvailable(Collection<CaptureResult.Key<?>> keys) {
        return mCharacteristics.getAvailableCaptureResultKeys().containsAll(keys);
    }

    /**
     * Determine whether or not all the {@code keys} are available request keys
     * (as in {@link CameraCharacteristics#getAvailableCaptureRequestKeys}.
     *
     * <p>If this returns {@code true}, then setting this key in the request builder
     * may have some effect (and if it's {@code false}, then the camera device will
     * definitely ignore it).</p>
     *
     * <p>In some cases (e.g. manual control of exposure), other keys must be also be set
     * in order for a key to take effect (e.g. control.mode set to OFF).</p>
     *
     * @param keys collection of capture request keys
     * @return whether or not all result keys are available
     */
    public final boolean areRequestKeysAvailable(Collection<CaptureRequest.Key<?>> keys) {
        return mCharacteristics.getAvailableCaptureRequestKeys().containsAll(keys);
    }

    /**
     * Determine whether or not all the {@code keys} are available characteristics keys
     * (as in {@link CameraCharacteristics#getKeys}.
     *
     * <p>If this returns {@code true}, then querying for this key from a characteristics
     * object will always return a non-{@code null} value.</p>
     *
     * @param keys one or more camera characteristic keys
     * @return whether or not all characteristics keys are available
     */
    @SafeVarargs
    public final boolean areKeysAvailable(CameraCharacteristics.Key<?>... keys) {
        return areCharacteristicsKeysAvailable(Arrays.asList(keys));
    }

    /**
     * Determine whether or not all the {@code keys} are available result keys
     * (as in {@link CameraCharacteristics#getAvailableCaptureResultKeys}.
     *
     * <p>If this returns {@code true}, then querying for this key from a result
     * object will almost always return a non-{@code null} value.</p>
     *
     * <p>In some cases (e.g. lens shading map), the request must have additional settings
     * configured in order for the key to correspond to a value.</p>
     *
     * @param keys one or more capture result keys
     * @return whether or not all result keys are available
     */
    @SafeVarargs
    public final boolean areKeysAvailable(CaptureResult.Key<?>... keys) {
        return areResultKeysAvailable(Arrays.asList(keys));
    }

    /**
     * Determine whether or not all the {@code keys} are available request keys
     * (as in {@link CameraCharacteristics#getAvailableCaptureRequestKeys}.
     *
     * <p>If this returns {@code true}, then setting this key in the request builder
     * may have some effect (and if it's {@code false}, then the camera device will
     * definitely ignore it).</p>
     *
     * <p>In some cases (e.g. manual control of exposure), other keys must be also be set
     * in order for a key to take effect (e.g. control.mode set to OFF).</p>
     *
     * @param keys one or more capture request keys
     * @return whether or not all result keys are available
     */
    @SafeVarargs
    public final boolean areKeysAvailable(CaptureRequest.Key<?>... keys) {
        return areRequestKeysAvailable(Arrays.asList(keys));
    }

    /*
     * Determine if camera device support manual lens shading map control
     *
     * @return {@code true} if manual lens shading map control is supported
     */
    public boolean isManualLensShadingMapSupported() {
        return areKeysAvailable(CaptureRequest.SHADING_MODE);
    }

    /**
     * Determine if camera device support manual color correction control
     *
     * @return {@code true} if manual color correction control is supported
     */
    public boolean isManualColorCorrectionSupported() {
        return areKeysAvailable(CaptureRequest.COLOR_CORRECTION_MODE);
    }

    /**
     * Determine if camera device support manual tone mapping control
     *
     * @return {@code true} if manual tone mapping control is supported
     */
    public boolean isManualToneMapSupported() {
        return areKeysAvailable(CaptureRequest.TONEMAP_MODE);
    }

    /**
     * Determine if camera device support manual color aberration control
     *
     * @return {@code true} if manual color aberration control is supported
     */
    public boolean isManualColorAberrationControlSupported() {
        return areKeysAvailable(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE);
    }

    /**
     * Determine if camera device support edge mode control
     *
     * @return {@code true} if edge mode control is supported
     */
    public boolean isEdgeModeControlSupported() {
        return areKeysAvailable(CaptureRequest.EDGE_MODE);
    }

    /**
     * Determine if camera device support hot pixel mode control
     *
     * @return {@code true} if hot pixel mode control is supported
     */
    public boolean isHotPixelMapModeControlSupported() {
        return areKeysAvailable(CaptureRequest.HOT_PIXEL_MODE);
    }

    /**
     * Determine if camera device support noise reduction mode control
     *
     * @return {@code true} if noise reduction mode control is supported
     */
    public boolean isNoiseReductionModeControlSupported() {
        return areKeysAvailable(CaptureRequest.NOISE_REDUCTION_MODE);
    }

    /**
     * Get max number of output raw streams and do the basic sanity check.
     *
     * @return reported max number of raw output stream
     */
    public int getMaxNumOutputStreamsRawChecked() {
        Integer maxNumStreams =
                getValueFromKeyNonNull(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW);
        if (maxNumStreams == null)
            return 0;
        return maxNumStreams;
    }

    /**
     * Get max number of output processed streams and do the basic sanity check.
     *
     * @return reported max number of processed output stream
     */
    public int getMaxNumOutputStreamsProcessedChecked() {
        Integer maxNumStreams =
                getValueFromKeyNonNull(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC);
        if (maxNumStreams == null)
            return 0;
        return maxNumStreams;
    }

    /**
     * Get max number of output stalling processed streams and do the basic sanity check.
     *
     * @return reported max number of stalling processed output stream
     */
    public int getMaxNumOutputStreamsProcessedStallChecked() {
        Integer maxNumStreams =
                getValueFromKeyNonNull(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING);
        if (maxNumStreams == null)
            return 0;
        return maxNumStreams;
    }

    /**
     * Get lens facing and do the sanity check
     * @return lens facing, return default value (BACK) if value is unavailable.
     */
    public int getLensFacingChecked() {
        Key<Integer> key =
                CameraCharacteristics.LENS_FACING;
        Integer facing = getValueFromKeyNonNull(key);

        if (facing == null) {
            return CameraCharacteristics.LENS_FACING_BACK;
        }

        checkTrueForKey(key, " value is out of range ",
                facing >= CameraCharacteristics.LENS_FACING_FRONT &&
                facing <= CameraCharacteristics.LENS_FACING_BACK);
        return facing;
    }

    /**
     * Get the scaler's cropping type (center only or freeform)
     * @return cropping type, return default value (CENTER_ONLY) if value is unavailable
     */
    public int getScalerCroppingTypeChecked() {
        Key<Integer> key =
                CameraCharacteristics.SCALER_CROPPING_TYPE;
        Integer value = getValueFromKeyNonNull(key);

        if (value == null) {
            return CameraCharacteristics.SCALER_CROPPING_TYPE_CENTER_ONLY;
        }

        checkTrueForKey(key, " value is out of range ",
                value >= CameraCharacteristics.SCALER_CROPPING_TYPE_CENTER_ONLY &&
                value <= CameraCharacteristics.SCALER_CROPPING_TYPE_FREEFORM);

        return value;
    }

    /**
     * Check if high speed video is supported (HIGH_SPEED_VIDEO scene mode is
     * supported, supported high speed fps ranges and sizes are valid).
     *
     * @return true if high speed video is supported.
     */
    public boolean isHighSpeedVideoSupported() {
        List<Integer> sceneModes =
                Arrays.asList(CameraTestUtils.toObject(getAvailableSceneModesChecked()));
        if (sceneModes.contains(CameraCharacteristics.CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO)) {
            StreamConfigurationMap config =
                    getValueFromKeyNonNull(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            if (config == null) {
                return false;
            }
            Size[] availableSizes = config.getHighSpeedVideoSizes();
            if (availableSizes.length == 0) {
                return false;
            }

            for (Size size : availableSizes) {
                Range<Integer>[] availableFpsRanges = config.getHighSpeedVideoFpsRangesFor(size);
                if (availableFpsRanges.length == 0) {
                    return false;
                }
            }

            return true;
        } else {
            return false;
        }
    }

    /**
     * Get the value in index for a fixed-size array from a given key.
     *
     * <p>If the camera device is incorrectly reporting values, log a warning and return
     * the default value instead.</p>
     *
     * @param key Key to fetch
     * @param defaultValue Default value to return if camera device uses invalid values
     * @param name Human-readable name for the array index (logging only)
     * @param index Array index of the subelement
     * @param size Expected fixed size of the array
     *
     * @return The value reported by the camera device, or the defaultValue otherwise.
     */
    private <T> T getArrayElementOrDefault(Key<?> key, T defaultValue, String name, int index,
            int size) {
        T elementValue = getArrayElementCheckRangeNonNull(
                key,
                index,
                size);

        if (elementValue == null) {
            failKeyCheck(key,
                    "had no valid " + name + " value; using default of " + defaultValue);
            elementValue = defaultValue;
        }

        return elementValue;
    }

    /**
     * Fetch an array sub-element from an array value given by a key.
     *
     * <p>
     * Prints a warning if the sub-element was null.
     * </p>
     *
     * <p>Use for variable-size arrays since this does not check the array size.</p>
     *
     * @param key Metadata key to look up
     * @param element A non-negative index value.
     * @return The array sub-element, or null if the checking failed.
     */
    private <T> T getArrayElementNonNull(Key<?> key, int element) {
        return getArrayElementCheckRangeNonNull(key, element, IGNORE_SIZE_CHECK);
    }

    /**
     * Fetch an array sub-element from an array value given by a key.
     *
     * <p>
     * Prints a warning if the array size does not match the size, or if the sub-element was null.
     * </p>
     *
     * @param key Metadata key to look up
     * @param element The index in [0,size)
     * @param size A positive size value or otherwise {@value #IGNORE_SIZE_CHECK}
     * @return The array sub-element, or null if the checking failed.
     */
    private <T> T getArrayElementCheckRangeNonNull(Key<?> key, int element, int size) {
        Object array = getValueFromKeyNonNull(key);

        if (array == null) {
            // Warning already printed
            return null;
        }

        if (size != IGNORE_SIZE_CHECK) {
            int actualLength = Array.getLength(array);
            if (actualLength != size) {
                failKeyCheck(key,
                        String.format("had the wrong number of elements (%d), expected (%d)",
                                actualLength, size));
                return null;
            }
        }

        @SuppressWarnings("unchecked")
        T val = (T) Array.get(array, element);

        if (val == null) {
            failKeyCheck(key, "had a null element at index" + element);
            return null;
        }

        return val;
    }

    /**
     * Gets the key, logging warnings for null values.
     */
    public <T> T getValueFromKeyNonNull(Key<T> key) {
        if (key == null) {
            throw new IllegalArgumentException("key was null");
        }

        T value = mCharacteristics.get(key);

        if (value == null) {
            failKeyCheck(key, "was null");
        }

        return value;
    }

    private void checkArrayValuesInRange(Key<int[]> key, int[] array, int min, int max) {
        for (int value : array) {
            checkTrueForKey(key, String.format(" value is out of range [%d, %d]", min, max),
                    value <= max && value >= min);
        }
    }

    private void checkArrayValuesInRange(Key<byte[]> key, byte[] array, byte min, byte max) {
        for (byte value : array) {
            checkTrueForKey(key, String.format(" value is out of range [%d, %d]", min, max),
                    value <= max && value >= min);
        }
    }

    /**
     * Check the uniqueness of the values in a list.
     *
     * @param key The key to be checked
     * @param list The list contains the value of the key
     */
    private <U, T> void checkElementDistinct(Key<U> key, List<T> list) {
        // Each size must be distinct.
        Set<T> sizeSet = new HashSet<T>(list);
        checkTrueForKey(key, "Each size must be distinct", sizeSet.size() == list.size());
    }

    private <T> void checkTrueForKey(Key<T> key, String message, boolean condition) {
        if (!condition) {
            failKeyCheck(key, message);
        }
    }

    private <T> void failKeyCheck(Key<T> key, String message) {
        // TODO: Consider only warning once per key/message combination if it's too spammy.
        // TODO: Consider offering other options such as throwing an assertion exception
        String failureCause = String.format("The static info key '%s' %s", key.getName(), message);
        switch (mLevel) {
            case WARN:
                Log.w(TAG, failureCause);
                break;
            case COLLECT:
                mCollector.addMessage(failureCause);
                break;
            case ASSERT:
                Assert.fail(failureCause);
            default:
                throw new UnsupportedOperationException("Unhandled level " + mLevel);
        }
    }
}
