/*
 * 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));
        if (compensationRange == null) {
            return DEFAULT_RANGE;
        }

        // Legacy devices don't have a minimum range requirement
        if (isHardwareLevelLimitedOrBetter()) {
            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);
        }
    }
}
