/*
 * Copyright 2013 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;

import androidx.annotation.NonNull;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.MultiResolutionImageReader;
import android.hardware.camera2.cts.helpers.CameraErrorCollector;
import android.hardware.camera2.cts.helpers.StaticMetadata;
import android.hardware.camera2.params.InputConfiguration;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.cts.helpers.CameraUtils;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.MandatoryStreamCombination;
import android.hardware.camera2.params.MandatoryStreamCombination.MandatoryStreamInformation;
import android.hardware.camera2.params.MultiResolutionStreamConfigurationMap;
import android.hardware.camera2.params.MultiResolutionStreamInfo;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.SessionConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.location.Location;
import android.location.LocationManager;
import android.media.ExifInterface;
import android.media.Image;
import android.media.ImageReader;
import android.media.ImageWriter;
import android.media.Image.Plane;
import android.os.Build;
import android.os.ConditionVariable;
import android.os.Handler;
import android.util.Log;
import android.util.Pair;
import android.util.Size;
import android.util.Range;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;

import com.android.ex.camera2.blocking.BlockingCameraManager;
import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
import com.android.ex.camera2.blocking.BlockingSessionCallback;
import com.android.ex.camera2.blocking.BlockingStateCallback;
import com.android.ex.camera2.exceptions.TimeoutRuntimeException;

import junit.framework.Assert;

import org.mockito.Mockito;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.text.ParseException;
import java.text.SimpleDateFormat;

/**
 * A package private utility class for wrapping up the camera2 cts test common utility functions
 */
public class CameraTestUtils extends Assert {
    private static final String TAG = "CameraTestUtils";
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    public static final Size SIZE_BOUND_720P = new Size(1280, 720);
    public static final Size SIZE_BOUND_1080P = new Size(1920, 1088);
    public static final Size SIZE_BOUND_2K = new Size(2048, 1088);
    public static final Size SIZE_BOUND_QHD = new Size(2560, 1440);
    public static final Size SIZE_BOUND_2160P = new Size(3840, 2160);
    // Only test the preview size that is no larger than 1080p.
    public static final Size PREVIEW_SIZE_BOUND = SIZE_BOUND_1080P;
    // Default timeouts for reaching various states
    public static final int CAMERA_OPEN_TIMEOUT_MS = 3000;
    public static final int CAMERA_CLOSE_TIMEOUT_MS = 3000;
    public static final int CAMERA_IDLE_TIMEOUT_MS = 3000;
    public static final int CAMERA_ACTIVE_TIMEOUT_MS = 1000;
    public static final int CAMERA_BUSY_TIMEOUT_MS = 1000;
    public static final int CAMERA_UNCONFIGURED_TIMEOUT_MS = 1000;
    public static final int CAMERA_CONFIGURE_TIMEOUT_MS = 3000;
    public static final int CAPTURE_RESULT_TIMEOUT_MS = 3000;
    public static final int CAPTURE_IMAGE_TIMEOUT_MS = 3000;

    public static final int SESSION_CONFIGURE_TIMEOUT_MS = 3000;
    public static final int SESSION_CLOSE_TIMEOUT_MS = 3000;
    public static final int SESSION_READY_TIMEOUT_MS = 5000;
    public static final int SESSION_ACTIVE_TIMEOUT_MS = 1000;

    public static final int MAX_READER_IMAGES = 5;

    public static final int INDEX_ALGORITHM_AE = 0;
    public static final int INDEX_ALGORITHM_AWB = 1;
    public static final int INDEX_ALGORITHM_AF = 2;
    public static final int NUM_ALGORITHMS = 3; // AE, AWB and AF

    // Compensate for the loss of "sensitivity" and "sensitivityBoost"
    public static final int MAX_ISO_MISMATCH = 3;

    public static final String OFFLINE_CAMERA_ID = "offline_camera_id";
    public static final String REPORT_LOG_NAME = "CtsCameraTestCases";

    private static final int EXIF_DATETIME_LENGTH = 19;
    private static final int EXIF_DATETIME_ERROR_MARGIN_SEC = 60;
    private static final float EXIF_FOCAL_LENGTH_ERROR_MARGIN = 0.001f;
    private static final float EXIF_EXPOSURE_TIME_ERROR_MARGIN_RATIO = 0.05f;
    private static final float EXIF_EXPOSURE_TIME_MIN_ERROR_MARGIN_SEC = 0.002f;
    private static final float EXIF_APERTURE_ERROR_MARGIN = 0.001f;

    private static final float ZOOM_RATIO_THRESHOLD = 0.01f;

    private static final Location sTestLocation0 = new Location(LocationManager.GPS_PROVIDER);
    private static final Location sTestLocation1 = new Location(LocationManager.GPS_PROVIDER);
    private static final Location sTestLocation2 = new Location(LocationManager.NETWORK_PROVIDER);

    static {
        sTestLocation0.setTime(1199145600000L);
        sTestLocation0.setLatitude(37.736071);
        sTestLocation0.setLongitude(-122.441983);
        sTestLocation0.setAltitude(21.0);

        sTestLocation1.setTime(1199145601000L);
        sTestLocation1.setLatitude(0.736071);
        sTestLocation1.setLongitude(0.441983);
        sTestLocation1.setAltitude(1.0);

        sTestLocation2.setTime(1199145602000L);
        sTestLocation2.setLatitude(-89.736071);
        sTestLocation2.setLongitude(-179.441983);
        sTestLocation2.setAltitude(100000.0);
    }

    // Exif test data vectors.
    public static final ExifTestData[] EXIF_TEST_DATA = {
            new ExifTestData(
                    /*gpsLocation*/ sTestLocation0,
                    /* orientation */90,
                    /* jpgQuality */(byte) 80,
                    /* thumbQuality */(byte) 75),
            new ExifTestData(
                    /*gpsLocation*/ sTestLocation1,
                    /* orientation */180,
                    /* jpgQuality */(byte) 90,
                    /* thumbQuality */(byte) 85),
            new ExifTestData(
                    /*gpsLocation*/ sTestLocation2,
                    /* orientation */270,
                    /* jpgQuality */(byte) 100,
                    /* thumbQuality */(byte) 80)
    };

    /**
     * Create an {@link android.media.ImageReader} object and get the surface.
     *
     * @param size The size of this ImageReader to be created.
     * @param format The format of this ImageReader to be created
     * @param maxNumImages The max number of images that can be acquired simultaneously.
     * @param listener The listener used by this ImageReader to notify callbacks.
     * @param handler The handler to use for any listener callbacks.
     */
    public static ImageReader makeImageReader(Size size, int format, int maxNumImages,
            ImageReader.OnImageAvailableListener listener, Handler handler) {
        ImageReader reader;
        reader = ImageReader.newInstance(size.getWidth(), size.getHeight(), format,
                maxNumImages);
        reader.setOnImageAvailableListener(listener, handler);
        if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size);
        return reader;
    }

    /**
     * Create an ImageWriter and hook up the ImageListener.
     *
     * @param inputSurface The input surface of the ImageWriter.
     * @param maxImages The max number of Images that can be dequeued simultaneously.
     * @param listener The listener used by this ImageWriter to notify callbacks
     * @param handler The handler to post listener callbacks.
     * @return ImageWriter object created.
     */
    public static ImageWriter makeImageWriter(
            Surface inputSurface, int maxImages,
            ImageWriter.OnImageReleasedListener listener, Handler handler) {
        ImageWriter writer = ImageWriter.newInstance(inputSurface, maxImages);
        writer.setOnImageReleasedListener(listener, handler);
        return writer;
    }

    /**
     * Utility class to store the targets for mandatory stream combination test.
     */
    public static class StreamCombinationTargets {
        public List<SurfaceTexture> mPrivTargets = new ArrayList<>();
        public List<ImageReader> mJpegTargets = new ArrayList<>();
        public List<ImageReader> mYuvTargets = new ArrayList<>();
        public List<ImageReader> mY8Targets = new ArrayList<>();
        public List<ImageReader> mRawTargets = new ArrayList<>();
        public List<ImageReader> mHeicTargets = new ArrayList<>();
        public List<ImageReader> mDepth16Targets = new ArrayList<>();

        public List<MultiResolutionImageReader> mPrivMultiResTargets = new ArrayList<>();
        public List<MultiResolutionImageReader> mJpegMultiResTargets = new ArrayList<>();
        public List<MultiResolutionImageReader> mYuvMultiResTargets = new ArrayList<>();
        public List<MultiResolutionImageReader> mRawMultiResTargets = new ArrayList<>();

        public void close() {
            for (SurfaceTexture target : mPrivTargets) {
                target.release();
            }
            for (ImageReader target : mJpegTargets) {
                target.close();
            }
            for (ImageReader target : mYuvTargets) {
                target.close();
            }
            for (ImageReader target : mY8Targets) {
                target.close();
            }
            for (ImageReader target : mRawTargets) {
                target.close();
            }
            for (ImageReader target : mHeicTargets) {
                target.close();
            }
            for (ImageReader target : mDepth16Targets) {
                target.close();
            }

            for (MultiResolutionImageReader target : mPrivMultiResTargets) {
                target.close();
            }
            for (MultiResolutionImageReader target : mJpegMultiResTargets) {
                target.close();
            }
            for (MultiResolutionImageReader target : mYuvMultiResTargets) {
                target.close();
            }
            for (MultiResolutionImageReader target : mRawMultiResTargets) {
                target.close();
            }
        }
    }

    private static void configureTarget(StreamCombinationTargets targets,
            List<OutputConfiguration> outputConfigs, List<Surface> outputSurfaces,
            int format, Size targetSize, int numBuffers, String overridePhysicalCameraId,
            MultiResolutionStreamConfigurationMap multiResStreamConfig,
            boolean createMultiResiStreamConfig, ImageDropperListener listener, Handler handler) {
        if (createMultiResiStreamConfig) {
            Collection<MultiResolutionStreamInfo> multiResolutionStreams =
                    multiResStreamConfig.getOutputInfo(format);
            MultiResolutionImageReader multiResReader = new MultiResolutionImageReader(
                    multiResolutionStreams, format, numBuffers);
            multiResReader.setOnImageAvailableListener(listener, new HandlerExecutor(handler));
            Collection<OutputConfiguration> configs =
                    OutputConfiguration.createInstancesForMultiResolutionOutput(multiResReader);
            outputConfigs.addAll(configs);
            outputSurfaces.add(multiResReader.getSurface());
            switch (format) {
                case ImageFormat.PRIVATE:
                    targets.mPrivMultiResTargets.add(multiResReader);
                    break;
                case ImageFormat.JPEG:
                    targets.mJpegMultiResTargets.add(multiResReader);
                    break;
                case ImageFormat.YUV_420_888:
                    targets.mYuvMultiResTargets.add(multiResReader);
                    break;
                case ImageFormat.RAW_SENSOR:
                    targets.mRawMultiResTargets.add(multiResReader);
                    break;
                default:
                    fail("Unknown/Unsupported output format " + format);
            }
        } else {
            if (format == ImageFormat.PRIVATE) {
                SurfaceTexture target = new SurfaceTexture(/*random int*/1);
                target.setDefaultBufferSize(targetSize.getWidth(), targetSize.getHeight());
                OutputConfiguration config = new OutputConfiguration(new Surface(target));
                if (overridePhysicalCameraId != null) {
                    config.setPhysicalCameraId(overridePhysicalCameraId);
                }
                outputConfigs.add(config);
                outputSurfaces.add(config.getSurface());
                targets.mPrivTargets.add(target);
            } else {
                ImageReader target = ImageReader.newInstance(targetSize.getWidth(),
                        targetSize.getHeight(), format, numBuffers);
                target.setOnImageAvailableListener(listener, handler);
                OutputConfiguration config = new OutputConfiguration(target.getSurface());
                if (overridePhysicalCameraId != null) {
                    config.setPhysicalCameraId(overridePhysicalCameraId);
                }
                outputConfigs.add(config);
                outputSurfaces.add(config.getSurface());

                switch (format) {
                    case ImageFormat.JPEG:
                      targets.mJpegTargets.add(target);
                      break;
                    case ImageFormat.YUV_420_888:
                      targets.mYuvTargets.add(target);
                      break;
                    case ImageFormat.Y8:
                      targets.mY8Targets.add(target);
                      break;
                    case ImageFormat.RAW_SENSOR:
                      targets.mRawTargets.add(target);
                      break;
                    case ImageFormat.HEIC:
                      targets.mHeicTargets.add(target);
                      break;
                    case ImageFormat.DEPTH16:
                      targets.mDepth16Targets.add(target);
                      break;
                    default:
                      fail("Unknown/Unsupported output format " + format);
                }
            }
        }
    }

    public static void setupConfigurationTargets(List<MandatoryStreamInformation> streamsInfo,
            StreamCombinationTargets targets,
            List<OutputConfiguration> outputConfigs,
            List<Surface> outputSurfaces, int numBuffers,
            boolean substituteY8, boolean substituteHeic, String overridenPhysicalCameraId,
            MultiResolutionStreamConfigurationMap multiResStreamConfig, Handler handler) {
            List<Surface> uhSurfaces = new ArrayList<Surface>();
        setupConfigurationTargets(streamsInfo, targets, outputConfigs, outputSurfaces, uhSurfaces,
            numBuffers, substituteY8, substituteHeic, overridenPhysicalCameraId,
            multiResStreamConfig, handler);
    }

    public static void setupConfigurationTargets(List<MandatoryStreamInformation> streamsInfo,
            StreamCombinationTargets targets,
            List<OutputConfiguration> outputConfigs,
            List<Surface> outputSurfaces, List<Surface> uhSurfaces, int numBuffers,
            boolean substituteY8, boolean substituteHeic, String overridePhysicalCameraId,
            MultiResolutionStreamConfigurationMap multiResStreamConfig, Handler handler) {

        ImageDropperListener imageDropperListener = new ImageDropperListener();
        List<Surface> chosenSurfaces;
        for (MandatoryStreamInformation streamInfo : streamsInfo) {
            if (streamInfo.isInput()) {
                continue;
            }
            chosenSurfaces = outputSurfaces;
            if (streamInfo.isUltraHighResolution()) {
                chosenSurfaces = uhSurfaces;
            }
            int format = streamInfo.getFormat();
            if (substituteY8 && (format == ImageFormat.YUV_420_888)) {
                format = ImageFormat.Y8;
            } else if (substituteHeic && (format == ImageFormat.JPEG)) {
                format = ImageFormat.HEIC;
            }
            Size[] availableSizes = new Size[streamInfo.getAvailableSizes().size()];
            availableSizes = streamInfo.getAvailableSizes().toArray(availableSizes);
            Size targetSize = CameraTestUtils.getMaxSize(availableSizes);
            boolean createMultiResReader =
                    (multiResStreamConfig != null &&
                     !multiResStreamConfig.getOutputInfo(format).isEmpty() &&
                     streamInfo.isMaximumSize());
            switch (format) {
                case ImageFormat.PRIVATE:
                case ImageFormat.JPEG:
                case ImageFormat.YUV_420_888:
                case ImageFormat.Y8:
                case ImageFormat.HEIC:
                case ImageFormat.DEPTH16:
                {
                    configureTarget(targets, outputConfigs, chosenSurfaces, format,
                            targetSize, numBuffers, overridePhysicalCameraId, multiResStreamConfig,
                            createMultiResReader, imageDropperListener, handler);
                    break;
                }
                case ImageFormat.RAW_SENSOR: {
                    // targetSize could be null in the logical camera case where only
                    // physical camera supports RAW stream.
                    if (targetSize != null) {
                        configureTarget(targets, outputConfigs, chosenSurfaces, format,
                                targetSize, numBuffers, overridePhysicalCameraId,
                                multiResStreamConfig, createMultiResReader, imageDropperListener,
                                handler);
                    }
                    break;
                }
                default:
                    fail("Unknown output format " + format);
            }
        }
    }

    /**
     * Close pending images and clean up an {@link android.media.ImageReader} object.
     * @param reader an {@link android.media.ImageReader} to close.
     */
    public static void closeImageReader(ImageReader reader) {
        if (reader != null) {
            reader.close();
        }
    }

    /**
     * Close the pending images then close current active {@link ImageReader} objects.
     */
    public static void closeImageReaders(ImageReader[] readers) {
        if ((readers != null) && (readers.length > 0)) {
            for (ImageReader reader : readers) {
                CameraTestUtils.closeImageReader(reader);
            }
        }
    }

    /**
     * Close pending images and clean up an {@link android.media.ImageWriter} object.
     * @param writer an {@link android.media.ImageWriter} to close.
     */
    public static void closeImageWriter(ImageWriter writer) {
        if (writer != null) {
            writer.close();
        }
    }

    /**
     * Dummy listener that release the image immediately once it is available.
     *
     * <p>
     * It can be used for the case where we don't care the image data at all.
     * </p>
     */
    public static class ImageDropperListener implements ImageReader.OnImageAvailableListener {
        @Override
        public synchronized void onImageAvailable(ImageReader reader) {
            Image image = null;
            try {
                image = reader.acquireNextImage();
            } finally {
                if (image != null) {
                    image.close();
                    mImagesDropped++;
                }
            }
        }

        public synchronized int getImageCount() {
            return mImagesDropped;
        }

        public synchronized void resetImageCount() {
            mImagesDropped = 0;
        }

        private int mImagesDropped = 0;
    }

    /**
     * Image listener that release the image immediately after validating the image
     */
    public static class ImageVerifierListener implements ImageReader.OnImageAvailableListener {
        private Size mSize;
        private int mFormat;
        // Whether the parent ImageReader is valid or not. If the parent ImageReader
        // is destroyed, the acquired Image may become invalid.
        private boolean mReaderIsValid;

        public ImageVerifierListener(Size sz, int format) {
            mSize = sz;
            mFormat = format;
            mReaderIsValid = true;
        }

        public synchronized void onReaderDestroyed() {
            mReaderIsValid = false;
        }

        @Override
        public synchronized void onImageAvailable(ImageReader reader) {
            Image image = null;
            try {
                image = reader.acquireNextImage();
            } finally {
                if (image != null) {
                    // Should only do some quick validity checks in callback, as the ImageReader
                    // could be closed asynchronously, which will close all images acquired from
                    // this ImageReader.
                    checkImage(image, mSize.getWidth(), mSize.getHeight(), mFormat);
                    // checkAndroidImageFormat calls into underlying Image object, which could
                    // become invalid if the ImageReader is destroyed.
                    if (mReaderIsValid) {
                        checkAndroidImageFormat(image);
                    }
                    image.close();
                }
            }
        }
    }

    public static class SimpleImageReaderListener
            implements ImageReader.OnImageAvailableListener {
        private final LinkedBlockingQueue<Image> mQueue =
                new LinkedBlockingQueue<Image>();
        // Indicate whether this listener will drop images or not,
        // when the queued images reaches the reader maxImages
        private final boolean mAsyncMode;
        // maxImages held by the queue in async mode.
        private final int mMaxImages;

        /**
         * Create a synchronous SimpleImageReaderListener that queues the images
         * automatically when they are available, no image will be dropped. If
         * the caller doesn't call getImage(), the producer will eventually run
         * into buffer starvation.
         */
        public SimpleImageReaderListener() {
            mAsyncMode = false;
            mMaxImages = 0;
        }

        /**
         * Create a synchronous/asynchronous SimpleImageReaderListener that
         * queues the images automatically when they are available. For
         * asynchronous listener, image will be dropped if the queued images
         * reach to maxImages queued. If the caller doesn't call getImage(), the
         * producer will not be blocked. For synchronous listener, no image will
         * be dropped. If the caller doesn't call getImage(), the producer will
         * eventually run into buffer starvation.
         *
         * @param asyncMode If the listener is operating at asynchronous mode.
         * @param maxImages The max number of images held by this listener.
         */
        /**
         *
         * @param asyncMode
         */
        public SimpleImageReaderListener(boolean asyncMode, int maxImages) {
            mAsyncMode = asyncMode;
            mMaxImages = maxImages;
        }

        @Override
        public void onImageAvailable(ImageReader reader) {
            try {
                Image imge = reader.acquireNextImage();
                if (imge == null) {
                    return;
                }
                mQueue.put(imge);
                if (mAsyncMode && mQueue.size() >= mMaxImages) {
                    Image img = mQueue.poll();
                    img.close();
                }
            } catch (InterruptedException e) {
                throw new UnsupportedOperationException(
                        "Can't handle InterruptedException in onImageAvailable");
            }
        }

        /**
         * Get an image from the image reader.
         *
         * @param timeout Timeout value for the wait.
         * @return The image from the image reader.
         */
        public Image getImage(long timeout) throws InterruptedException {
            Image image = mQueue.poll(timeout, TimeUnit.MILLISECONDS);
            assertNotNull("Wait for an image timed out in " + timeout + "ms", image);
            return image;
        }

        /**
         * Drain the pending images held by this listener currently.
         *
         */
        public void drain() {
            while (!mQueue.isEmpty()) {
                Image image = mQueue.poll();
                assertNotNull("Unable to get an image", image);
                image.close();
            }
        }
    }

    public static class SimpleImageWriterListener implements ImageWriter.OnImageReleasedListener {
        private final Semaphore mImageReleasedSema = new Semaphore(0);
        private final ImageWriter mWriter;
        @Override
        public void onImageReleased(ImageWriter writer) {
            if (writer != mWriter) {
                return;
            }

            if (VERBOSE) {
                Log.v(TAG, "Input image is released");
            }
            mImageReleasedSema.release();
        }

        public SimpleImageWriterListener(ImageWriter writer) {
            if (writer == null) {
                throw new IllegalArgumentException("writer cannot be null");
            }
            mWriter = writer;
        }

        public void waitForImageReleased(long timeoutMs) throws InterruptedException {
            if (!mImageReleasedSema.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
                fail("wait for image available timed out after " + timeoutMs + "ms");
            }
        }
    }

    public static class ImageAndMultiResStreamInfo {
        public final Image image;
        public final MultiResolutionStreamInfo streamInfo;

        public ImageAndMultiResStreamInfo(Image image, MultiResolutionStreamInfo streamInfo) {
            this.image = image;
            this.streamInfo = streamInfo;
        }
    }

    public static class SimpleMultiResolutionImageReaderListener
            implements ImageReader.OnImageAvailableListener {
        public SimpleMultiResolutionImageReaderListener(MultiResolutionImageReader owner,
                int maxBuffers, boolean acquireLatest) {
            mOwner = owner;
            mMaxBuffers = maxBuffers;
            mAcquireLatest = acquireLatest;
        }

        @Override
        public void onImageAvailable(ImageReader reader) {
            if (VERBOSE) Log.v(TAG, "new image available");

            if (mAcquireLatest) {
                mLastReader = reader;
                mImageAvailable.open();
            } else {
                if (mQueue.size() < mMaxBuffers) {
                    Image image = reader.acquireNextImage();
                    MultiResolutionStreamInfo multiResStreamInfo =
                            mOwner.getStreamInfoForImageReader(reader);
                    mQueue.offer(new ImageAndMultiResStreamInfo(image, multiResStreamInfo));
                }
            }
        }

        public ImageAndMultiResStreamInfo getAnyImageAndInfoAvailable(long timeoutMs)
                throws Exception {
            if (mAcquireLatest) {
                Image image = null;
                if (mImageAvailable.block(timeoutMs)) {
                    if (mLastReader != null) {
                        image = mLastReader.acquireLatestImage();
                        if (VERBOSE) Log.v(TAG, "acquireLatestImage");
                    } else {
                        fail("invalid image reader");
                    }
                    mImageAvailable.close();
                } else {
                    fail("wait for image available time out after " + timeoutMs + "ms");
                }
                return new ImageAndMultiResStreamInfo(image,
                        mOwner.getStreamInfoForImageReader(mLastReader));
            } else {
                ImageAndMultiResStreamInfo imageAndInfo = mQueue.poll(timeoutMs,
                        java.util.concurrent.TimeUnit.MILLISECONDS);
                if (imageAndInfo == null) {
                    fail("wait for image available timed out after " + timeoutMs + "ms");
                }
                return imageAndInfo;
            }
        }

        public void reset() {
            while (!mQueue.isEmpty()) {
                ImageAndMultiResStreamInfo imageAndInfo = mQueue.poll();
                assertNotNull("Acquired image is not valid", imageAndInfo.image);
                imageAndInfo.image.close();
            }
            mImageAvailable.close();
            mLastReader = null;
        }

        private LinkedBlockingQueue<ImageAndMultiResStreamInfo> mQueue =
                new LinkedBlockingQueue<ImageAndMultiResStreamInfo>();
        private final MultiResolutionImageReader mOwner;
        private final int mMaxBuffers;
        private final boolean mAcquireLatest;
        private ConditionVariable mImageAvailable = new ConditionVariable();
        private ImageReader mLastReader = null;
    }

    public static class SimpleCaptureCallback extends CameraCaptureSession.CaptureCallback {
        private final LinkedBlockingQueue<TotalCaptureResult> mQueue =
                new LinkedBlockingQueue<TotalCaptureResult>();
        private final LinkedBlockingQueue<CaptureFailure> mFailureQueue =
                new LinkedBlockingQueue<>();
        // (Surface, framenumber) pair for lost buffers
        private final LinkedBlockingQueue<Pair<Surface, Long>> mBufferLostQueue =
                new LinkedBlockingQueue<>();
        private final LinkedBlockingQueue<Integer> mAbortQueue =
                new LinkedBlockingQueue<>();
        // Pair<CaptureRequest, Long> is a pair of capture request and timestamp.
        private final LinkedBlockingQueue<Pair<CaptureRequest, Long>> mCaptureStartQueue =
                new LinkedBlockingQueue<>();
        // Pair<Int, Long> is a pair of sequence id and frame number
        private final LinkedBlockingQueue<Pair<Integer, Long>> mCaptureSequenceCompletedQueue =
                new LinkedBlockingQueue<>();

        private AtomicLong mNumFramesArrived = new AtomicLong(0);

        @Override
        public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
                long timestamp, long frameNumber) {
            try {
                mCaptureStartQueue.put(new Pair(request, timestamp));
            } catch (InterruptedException e) {
                throw new UnsupportedOperationException(
                        "Can't handle InterruptedException in onCaptureStarted");
            }
        }

        @Override
        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
                TotalCaptureResult result) {
            try {
                mNumFramesArrived.incrementAndGet();
                mQueue.put(result);
            } catch (InterruptedException e) {
                throw new UnsupportedOperationException(
                        "Can't handle InterruptedException in onCaptureCompleted");
            }
        }

        @Override
        public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
                CaptureFailure failure) {
            try {
                mFailureQueue.put(failure);
            } catch (InterruptedException e) {
                throw new UnsupportedOperationException(
                        "Can't handle InterruptedException in onCaptureFailed");
            }
        }

        @Override
        public void onCaptureSequenceAborted(CameraCaptureSession session, int sequenceId) {
            try {
                mAbortQueue.put(sequenceId);
            } catch (InterruptedException e) {
                throw new UnsupportedOperationException(
                        "Can't handle InterruptedException in onCaptureAborted");
            }
        }

        @Override
        public void onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId,
                long frameNumber) {
            try {
                mCaptureSequenceCompletedQueue.put(new Pair(sequenceId, frameNumber));
            } catch (InterruptedException e) {
                throw new UnsupportedOperationException(
                        "Can't handle InterruptedException in onCaptureSequenceCompleted");
            }
        }

        @Override
        public void onCaptureBufferLost(CameraCaptureSession session,
                CaptureRequest request, Surface target, long frameNumber) {
            try {
                mBufferLostQueue.put(new Pair<>(target, frameNumber));
            } catch (InterruptedException e) {
                throw new UnsupportedOperationException(
                        "Can't handle InterruptedException in onCaptureBufferLost");
            }
        }

        public long getTotalNumFrames() {
            return mNumFramesArrived.get();
        }

        public CaptureResult getCaptureResult(long timeout) {
            return getTotalCaptureResult(timeout);
        }

        public TotalCaptureResult getCaptureResult(long timeout, long timestamp) {
            try {
                long currentTs = -1L;
                TotalCaptureResult result;
                while (true) {
                    result = mQueue.poll(timeout, TimeUnit.MILLISECONDS);
                    if (result == null) {
                        throw new RuntimeException(
                                "Wait for a capture result timed out in " + timeout + "ms");
                    }
                    currentTs = result.get(CaptureResult.SENSOR_TIMESTAMP);
                    if (currentTs == timestamp) {
                        return result;
                    }
                }

            } catch (InterruptedException e) {
                throw new UnsupportedOperationException("Unhandled interrupted exception", e);
            }
        }

        public TotalCaptureResult getTotalCaptureResult(long timeout) {
            try {
                TotalCaptureResult result = mQueue.poll(timeout, TimeUnit.MILLISECONDS);
                assertNotNull("Wait for a capture result timed out in " + timeout + "ms", result);
                return result;
            } catch (InterruptedException e) {
                throw new UnsupportedOperationException("Unhandled interrupted exception", e);
            }
        }

        /**
         * Get the {@link #CaptureResult capture result} for a given
         * {@link #CaptureRequest capture request}.
         *
         * @param myRequest The {@link #CaptureRequest capture request} whose
         *            corresponding {@link #CaptureResult capture result} was
         *            being waited for
         * @param numResultsWait Number of frames to wait for the capture result
         *            before timeout.
         * @throws TimeoutRuntimeException If more than numResultsWait results are
         *            seen before the result matching myRequest arrives, or each
         *            individual wait for result times out after
         *            {@value #CAPTURE_RESULT_TIMEOUT_MS}ms.
         */
        public CaptureResult getCaptureResultForRequest(CaptureRequest myRequest,
                int numResultsWait) {
            return getTotalCaptureResultForRequest(myRequest, numResultsWait);
        }

        /**
         * Get the {@link #TotalCaptureResult total capture result} for a given
         * {@link #CaptureRequest capture request}.
         *
         * @param myRequest The {@link #CaptureRequest capture request} whose
         *            corresponding {@link #TotalCaptureResult capture result} was
         *            being waited for
         * @param numResultsWait Number of frames to wait for the capture result
         *            before timeout.
         * @throws TimeoutRuntimeException If more than numResultsWait results are
         *            seen before the result matching myRequest arrives, or each
         *            individual wait for result times out after
         *            {@value #CAPTURE_RESULT_TIMEOUT_MS}ms.
         */
        public TotalCaptureResult getTotalCaptureResultForRequest(CaptureRequest myRequest,
                int numResultsWait) {
            ArrayList<CaptureRequest> captureRequests = new ArrayList<>(1);
            captureRequests.add(myRequest);
            return getTotalCaptureResultsForRequests(captureRequests, numResultsWait)[0];
        }

        /**
         * Get an array of {@link #TotalCaptureResult total capture results} for a given list of
         * {@link #CaptureRequest capture requests}. This can be used when the order of results
         * may not the same as the order of requests.
         *
         * @param captureRequests The list of {@link #CaptureRequest capture requests} whose
         *            corresponding {@link #TotalCaptureResult capture results} are
         *            being waited for.
         * @param numResultsWait Number of frames to wait for the capture results
         *            before timeout.
         * @throws TimeoutRuntimeException If more than numResultsWait results are
         *            seen before all the results matching captureRequests arrives.
         */
        public TotalCaptureResult[] getTotalCaptureResultsForRequests(
                List<CaptureRequest> captureRequests, int numResultsWait) {
            if (numResultsWait < 0) {
                throw new IllegalArgumentException("numResultsWait must be no less than 0");
            }
            if (captureRequests == null || captureRequests.size() == 0) {
                throw new IllegalArgumentException("captureRequests must have at least 1 request.");
            }

            // Create a request -> a list of result indices map that it will wait for.
            HashMap<CaptureRequest, ArrayList<Integer>> remainingResultIndicesMap = new HashMap<>();
            for (int i = 0; i < captureRequests.size(); i++) {
                CaptureRequest request = captureRequests.get(i);
                ArrayList<Integer> indices = remainingResultIndicesMap.get(request);
                if (indices == null) {
                    indices = new ArrayList<>();
                    remainingResultIndicesMap.put(request, indices);
                }
                indices.add(i);
            }

            TotalCaptureResult[] results = new TotalCaptureResult[captureRequests.size()];
            int i = 0;
            do {
                TotalCaptureResult result = getTotalCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);
                CaptureRequest request = result.getRequest();
                ArrayList<Integer> indices = remainingResultIndicesMap.get(request);
                if (indices != null) {
                    results[indices.get(0)] = result;
                    indices.remove(0);

                    // Remove the entry if all results for this request has been fulfilled.
                    if (indices.isEmpty()) {
                        remainingResultIndicesMap.remove(request);
                    }
                }

                if (remainingResultIndicesMap.isEmpty()) {
                    return results;
                }
            } while (i++ < numResultsWait);

            throw new TimeoutRuntimeException("Unable to get the expected capture result after "
                    + "waiting for " + numResultsWait + " results");
        }

        /**
         * Get an array list of {@link #CaptureFailure capture failure} with maxNumFailures entries
         * at most. If it times out before maxNumFailures failures are received, return the failures
         * received so far.
         *
         * @param maxNumFailures The maximal number of failures to return. If it times out before
         *                       the maximal number of failures are received, return the received
         *                       failures so far.
         * @throws UnsupportedOperationException If an error happens while waiting on the failure.
         */
        public ArrayList<CaptureFailure> getCaptureFailures(long maxNumFailures) {
            ArrayList<CaptureFailure> failures = new ArrayList<>();
            try {
                for (int i = 0; i < maxNumFailures; i++) {
                    CaptureFailure failure = mFailureQueue.poll(CAPTURE_RESULT_TIMEOUT_MS,
                            TimeUnit.MILLISECONDS);
                    if (failure == null) {
                        // If waiting on a failure times out, return the failures so far.
                        break;
                    }
                    failures.add(failure);
                }
            }  catch (InterruptedException e) {
                throw new UnsupportedOperationException("Unhandled interrupted exception", e);
            }

            return failures;
        }

        /**
         * Get an array list of lost buffers with maxNumLost entries at most.
         * If it times out before maxNumLost buffer lost callbacks are received, return the
         * lost callbacks received so far.
         *
         * @param maxNumLost The maximal number of buffer lost failures to return. If it times out
         *                   before the maximal number of failures are received, return the received
         *                   buffer lost failures so far.
         * @throws UnsupportedOperationException If an error happens while waiting on the failure.
         */
        public ArrayList<Pair<Surface, Long>> getLostBuffers(long maxNumLost) {
            ArrayList<Pair<Surface, Long>> failures = new ArrayList<>();
            try {
                for (int i = 0; i < maxNumLost; i++) {
                    Pair<Surface, Long> failure = mBufferLostQueue.poll(CAPTURE_RESULT_TIMEOUT_MS,
                            TimeUnit.MILLISECONDS);
                    if (failure == null) {
                        // If waiting on a failure times out, return the failures so far.
                        break;
                    }
                    failures.add(failure);
                }
            }  catch (InterruptedException e) {
                throw new UnsupportedOperationException("Unhandled interrupted exception", e);
            }

            return failures;
        }

        /**
         * Get an array list of aborted capture sequence ids with maxNumAborts entries
         * at most. If it times out before maxNumAborts are received, return the aborted sequences
         * received so far.
         *
         * @param maxNumAborts The maximal number of aborted sequences to return. If it times out
         *                     before the maximal number of aborts are received, return the received
         *                     failed sequences so far.
         * @throws UnsupportedOperationException If an error happens while waiting on the failed
         *                                       sequences.
         */
        public ArrayList<Integer> geAbortedSequences(long maxNumAborts) {
            ArrayList<Integer> abortList = new ArrayList<>();
            try {
                for (int i = 0; i < maxNumAborts; i++) {
                    Integer abortSequence = mAbortQueue.poll(CAPTURE_RESULT_TIMEOUT_MS,
                            TimeUnit.MILLISECONDS);
                    if (abortSequence == null) {
                        break;
                    }
                    abortList.add(abortSequence);
                }
            }  catch (InterruptedException e) {
                throw new UnsupportedOperationException("Unhandled interrupted exception", e);
            }

            return abortList;
        }

        /**
         * Wait until the capture start of a request and expected timestamp arrives or it times
         * out after a number of capture starts.
         *
         * @param request The request for the capture start to wait for.
         * @param timestamp The timestamp for the capture start to wait for.
         * @param numCaptureStartsWait The number of capture start events to wait for before timing
         *                             out.
         */
        public void waitForCaptureStart(CaptureRequest request, Long timestamp,
                int numCaptureStartsWait) throws Exception {
            Pair<CaptureRequest, Long> expectedShutter = new Pair<>(request, timestamp);

            int i = 0;
            do {
                Pair<CaptureRequest, Long> shutter = mCaptureStartQueue.poll(
                        CAPTURE_RESULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);

                if (shutter == null) {
                    throw new TimeoutRuntimeException("Unable to get any more capture start " +
                            "event after waiting for " + CAPTURE_RESULT_TIMEOUT_MS + " ms.");
                } else if (expectedShutter.equals(shutter)) {
                    return;
                }

            } while (i++ < numCaptureStartsWait);

            throw new TimeoutRuntimeException("Unable to get the expected capture start " +
                    "event after waiting for " + numCaptureStartsWait + " capture starts");
        }

        /**
         * Wait until it receives capture sequence completed callback for a given squence ID.
         *
         * @param sequenceId The sequence ID of the capture sequence completed callback to wait for.
         * @param timeoutMs Time to wait for each capture sequence complete callback before
         *                  timing out.
         */
        public long getCaptureSequenceLastFrameNumber(int sequenceId, long timeoutMs) {
            try {
                while (true) {
                    Pair<Integer, Long> completedSequence =
                            mCaptureSequenceCompletedQueue.poll(timeoutMs, TimeUnit.MILLISECONDS);
                    assertNotNull("Wait for a capture sequence completed timed out in " +
                            timeoutMs + "ms", completedSequence);

                    if (completedSequence.first.equals(sequenceId)) {
                        return completedSequence.second.longValue();
                    }
                }
            } catch (InterruptedException e) {
                throw new UnsupportedOperationException("Unhandled interrupted exception", e);
            }
        }

        public boolean hasMoreResults()
        {
            return !mQueue.isEmpty();
        }

        public boolean hasMoreFailures()
        {
            return !mFailureQueue.isEmpty();
        }

        public int getNumLostBuffers()
        {
            return mBufferLostQueue.size();
        }

        public boolean hasMoreAbortedSequences()
        {
            return !mAbortQueue.isEmpty();
        }

        public void drain() {
            mQueue.clear();
            mNumFramesArrived.getAndSet(0);
            mFailureQueue.clear();
            mBufferLostQueue.clear();
            mCaptureStartQueue.clear();
            mAbortQueue.clear();
        }
    }

    public static boolean hasCapability(CameraCharacteristics characteristics, int capability) {
        int [] capabilities =
                characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
        for (int c : capabilities) {
            if (c == capability) {
                return true;
            }
        }
        return false;
    }

    public static boolean isSystemCamera(CameraManager manager, String cameraId)
            throws CameraAccessException {
        CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
        return hasCapability(characteristics,
                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA);
    }

    public static String[] getCameraIdListForTesting(CameraManager manager,
            boolean getSystemCameras)
            throws CameraAccessException {
        String [] ids = manager.getCameraIdListNoLazy();
        List<String> idsForTesting = new ArrayList<String>();
        for (String id : ids) {
            boolean isSystemCamera = isSystemCamera(manager, id);
            if (getSystemCameras == isSystemCamera) {
                idsForTesting.add(id);
            }
        }
        return idsForTesting.toArray(new String[idsForTesting.size()]);
    }

    public static Set<Set<String>> getConcurrentCameraIds(CameraManager manager,
            boolean getSystemCameras)
            throws CameraAccessException {
        Set<String> cameraIds = new HashSet<String>(Arrays.asList(getCameraIdListForTesting(manager, getSystemCameras)));
        Set<Set<String>> combinations =  manager.getConcurrentCameraIds();
        Set<Set<String>> correctComb = new HashSet<Set<String>>();
        for (Set<String> comb : combinations) {
            Set<String> filteredIds = new HashSet<String>();
            for (String id : comb) {
                if (cameraIds.contains(id)) {
                    filteredIds.add(id);
                }
            }
            if (filteredIds.isEmpty()) {
                continue;
            }
            correctComb.add(filteredIds);
        }
        return correctComb;
    }

    /**
     * Block until the camera is opened.
     *
     * <p>Don't use this to test #onDisconnected/#onError since this will throw
     * an AssertionError if it fails to open the camera device.</p>
     *
     * @return CameraDevice opened camera device
     *
     * @throws IllegalArgumentException
     *            If the handler is null, or if the handler's looper is current.
     * @throws CameraAccessException
     *            If open fails immediately.
     * @throws BlockingOpenException
     *            If open fails after blocking for some amount of time.
     * @throws TimeoutRuntimeException
     *            If opening times out. Typically unrecoverable.
     */
    public static CameraDevice openCamera(CameraManager manager, String cameraId,
            CameraDevice.StateCallback listener, Handler handler) throws CameraAccessException,
            BlockingOpenException {

        /**
         * Although camera2 API allows 'null' Handler (it will just use the current
         * thread's Looper), this is not what we want for CTS.
         *
         * In CTS the default looper is used only to process events in between test runs,
         * so anything sent there would not be executed inside a test and the test would fail.
         *
         * In this case, BlockingCameraManager#openCamera performs the check for us.
         */
        return (new BlockingCameraManager(manager)).openCamera(cameraId, listener, handler);
    }


    /**
     * Block until the camera is opened.
     *
     * <p>Don't use this to test #onDisconnected/#onError since this will throw
     * an AssertionError if it fails to open the camera device.</p>
     *
     * @throws IllegalArgumentException
     *            If the handler is null, or if the handler's looper is current.
     * @throws CameraAccessException
     *            If open fails immediately.
     * @throws BlockingOpenException
     *            If open fails after blocking for some amount of time.
     * @throws TimeoutRuntimeException
     *            If opening times out. Typically unrecoverable.
     */
    public static CameraDevice openCamera(CameraManager manager, String cameraId, Handler handler)
            throws CameraAccessException,
            BlockingOpenException {
        return openCamera(manager, cameraId, /*listener*/null, handler);
    }

    /**
     * Configure a new camera session with output surfaces and type.
     *
     * @param camera The CameraDevice to be configured.
     * @param outputSurfaces The surface list that used for camera output.
     * @param listener The callback CameraDevice will notify when capture results are available.
     */
    public static CameraCaptureSession configureCameraSession(CameraDevice camera,
            List<Surface> outputSurfaces, boolean isHighSpeed,
            CameraCaptureSession.StateCallback listener, Handler handler)
            throws CameraAccessException {
        BlockingSessionCallback sessionListener = new BlockingSessionCallback(listener);
        if (isHighSpeed) {
            camera.createConstrainedHighSpeedCaptureSession(outputSurfaces,
                    sessionListener, handler);
        } else {
            camera.createCaptureSession(outputSurfaces, sessionListener, handler);
        }
        CameraCaptureSession session =
                sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
        assertFalse("Camera session should not be a reprocessable session",
                session.isReprocessable());
        String sessionType = isHighSpeed ? "High Speed" : "Normal";
        assertTrue("Capture session type must be " + sessionType,
                isHighSpeed ==
                CameraConstrainedHighSpeedCaptureSession.class.isAssignableFrom(session.getClass()));

        return session;
    }

    /**
     * Build a new constrained camera session with output surfaces, type and recording session
     * parameters.
     *
     * @param camera The CameraDevice to be configured.
     * @param outputSurfaces The surface list that used for camera output.
     * @param listener The callback CameraDevice will notify when capture results are available.
     * @param initialRequest Initial request settings to use as session parameters.
     */
    public static CameraCaptureSession buildConstrainedCameraSession(CameraDevice camera,
            List<Surface> outputSurfaces, CameraCaptureSession.StateCallback listener,
            Handler handler, CaptureRequest initialRequest) throws CameraAccessException {
        BlockingSessionCallback sessionListener = new BlockingSessionCallback(listener);

        List<OutputConfiguration> outConfigurations = new ArrayList<>(outputSurfaces.size());
        for (Surface surface : outputSurfaces) {
            outConfigurations.add(new OutputConfiguration(surface));
        }
        SessionConfiguration sessionConfig = new SessionConfiguration(
                SessionConfiguration.SESSION_HIGH_SPEED, outConfigurations,
                new HandlerExecutor(handler), sessionListener);
        sessionConfig.setSessionParameters(initialRequest);
        camera.createCaptureSession(sessionConfig);

        CameraCaptureSession session =
                sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
        assertFalse("Camera session should not be a reprocessable session",
                session.isReprocessable());
        assertTrue("Capture session type must be High Speed",
                CameraConstrainedHighSpeedCaptureSession.class.isAssignableFrom(
                        session.getClass()));

        return session;
    }

    /**
     * Configure a new camera session with output configurations.
     *
     * @param camera The CameraDevice to be configured.
     * @param outputs The OutputConfiguration list that is used for camera output.
     * @param listener The callback CameraDevice will notify when capture results are available.
     */
    public static CameraCaptureSession configureCameraSessionWithConfig(CameraDevice camera,
            List<OutputConfiguration> outputs,
            CameraCaptureSession.StateCallback listener, Handler handler)
            throws CameraAccessException {
        BlockingSessionCallback sessionListener = new BlockingSessionCallback(listener);
        camera.createCaptureSessionByOutputConfigurations(outputs, sessionListener, handler);
        CameraCaptureSession session =
                sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
        assertFalse("Camera session should not be a reprocessable session",
                session.isReprocessable());
        return session;
    }

    /**
     * Try configure a new camera session with output configurations.
     *
     * @param camera The CameraDevice to be configured.
     * @param outputs The OutputConfiguration list that is used for camera output.
     * @param initialRequest The session parameters passed in during stream configuration
     * @param listener The callback CameraDevice will notify when capture results are available.
     */
    public static CameraCaptureSession tryConfigureCameraSessionWithConfig(CameraDevice camera,
            List<OutputConfiguration> outputs, CaptureRequest initialRequest,
            CameraCaptureSession.StateCallback listener, Handler handler)
            throws CameraAccessException {
        BlockingSessionCallback sessionListener = new BlockingSessionCallback(listener);
        SessionConfiguration sessionConfig = new SessionConfiguration(
                SessionConfiguration.SESSION_REGULAR, outputs, new HandlerExecutor(handler),
                sessionListener);
        sessionConfig.setSessionParameters(initialRequest);
        camera.createCaptureSession(sessionConfig);

        Integer[] sessionStates = {BlockingSessionCallback.SESSION_READY,
                                   BlockingSessionCallback.SESSION_CONFIGURE_FAILED};
        int state = sessionListener.getStateWaiter().waitForAnyOfStates(
                Arrays.asList(sessionStates), SESSION_CONFIGURE_TIMEOUT_MS);

        CameraCaptureSession session = null;
        if (state == BlockingSessionCallback.SESSION_READY) {
            session = sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
            assertFalse("Camera session should not be a reprocessable session",
                    session.isReprocessable());
        }
        return session;
    }

    /**
     * Configure a new camera session with output surfaces and initial session parameters.
     *
     * @param camera The CameraDevice to be configured.
     * @param outputSurfaces The surface list that used for camera output.
     * @param listener The callback CameraDevice will notify when session is available.
     * @param handler The handler used to notify callbacks.
     * @param initialRequest Initial request settings to use as session parameters.
     */
    public static CameraCaptureSession configureCameraSessionWithParameters(CameraDevice camera,
            List<Surface> outputSurfaces, BlockingSessionCallback listener,
            Handler handler, CaptureRequest initialRequest) throws CameraAccessException {
        List<OutputConfiguration> outConfigurations = new ArrayList<>(outputSurfaces.size());
        for (Surface surface : outputSurfaces) {
            outConfigurations.add(new OutputConfiguration(surface));
        }
        SessionConfiguration sessionConfig = new SessionConfiguration(
                SessionConfiguration.SESSION_REGULAR, outConfigurations,
                new HandlerExecutor(handler), listener);
        sessionConfig.setSessionParameters(initialRequest);
        camera.createCaptureSession(sessionConfig);

        CameraCaptureSession session = listener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
        assertFalse("Camera session should not be a reprocessable session",
                session.isReprocessable());
        assertFalse("Capture session type must be regular",
                CameraConstrainedHighSpeedCaptureSession.class.isAssignableFrom(
                        session.getClass()));

        return session;
    }

    /**
     * Configure a new camera session with output surfaces.
     *
     * @param camera The CameraDevice to be configured.
     * @param outputSurfaces The surface list that used for camera output.
     * @param listener The callback CameraDevice will notify when capture results are available.
     */
    public static CameraCaptureSession configureCameraSession(CameraDevice camera,
            List<Surface> outputSurfaces,
            CameraCaptureSession.StateCallback listener, Handler handler)
            throws CameraAccessException {

        return configureCameraSession(camera, outputSurfaces, /*isHighSpeed*/false,
                listener, handler);
    }

    public static CameraCaptureSession configureReprocessableCameraSession(CameraDevice camera,
            InputConfiguration inputConfiguration, List<Surface> outputSurfaces,
            CameraCaptureSession.StateCallback listener, Handler handler)
            throws CameraAccessException {
        List<OutputConfiguration> outputConfigs = new ArrayList<OutputConfiguration>();
        for (Surface surface : outputSurfaces) {
            outputConfigs.add(new OutputConfiguration(surface));
        }
        CameraCaptureSession session = configureReprocessableCameraSessionWithConfigurations(
                camera, inputConfiguration, outputConfigs, listener, handler);

        return session;
    }

    public static CameraCaptureSession configureReprocessableCameraSessionWithConfigurations(
            CameraDevice camera, InputConfiguration inputConfiguration,
            List<OutputConfiguration> outputConfigs, CameraCaptureSession.StateCallback listener,
            Handler handler) throws CameraAccessException {
        BlockingSessionCallback sessionListener = new BlockingSessionCallback(listener);
        SessionConfiguration sessionConfig = new SessionConfiguration(
                SessionConfiguration.SESSION_REGULAR, outputConfigs, new HandlerExecutor(handler),
                sessionListener);
        sessionConfig.setInputConfiguration(inputConfiguration);
        camera.createCaptureSession(sessionConfig);

        Integer[] sessionStates = {BlockingSessionCallback.SESSION_READY,
                                   BlockingSessionCallback.SESSION_CONFIGURE_FAILED};
        int state = sessionListener.getStateWaiter().waitForAnyOfStates(
                Arrays.asList(sessionStates), SESSION_CONFIGURE_TIMEOUT_MS);

        assertTrue("Creating a reprocessable session failed.",
                state == BlockingSessionCallback.SESSION_READY);
        CameraCaptureSession session =
                sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
        assertTrue("Camera session should be a reprocessable session", session.isReprocessable());

        return session;
    }

    /**
     * Create a reprocessable camera session with input and output configurations.
     *
     * @param camera The CameraDevice to be configured.
     * @param inputConfiguration The input configuration used to create this session.
     * @param outputs The output configurations used to create this session.
     * @param listener The callback CameraDevice will notify when capture results are available.
     * @param handler The handler used to notify callbacks.
     * @return The session ready to use.
     * @throws CameraAccessException
     */
    public static CameraCaptureSession configureReprocCameraSessionWithConfig(CameraDevice camera,
            InputConfiguration inputConfiguration, List<OutputConfiguration> outputs,
            CameraCaptureSession.StateCallback listener, Handler handler)
            throws CameraAccessException {
        BlockingSessionCallback sessionListener = new BlockingSessionCallback(listener);
        camera.createReprocessableCaptureSessionByConfigurations(inputConfiguration, outputs,
                sessionListener, handler);

        Integer[] sessionStates = {BlockingSessionCallback.SESSION_READY,
                                   BlockingSessionCallback.SESSION_CONFIGURE_FAILED};
        int state = sessionListener.getStateWaiter().waitForAnyOfStates(
                Arrays.asList(sessionStates), SESSION_CONFIGURE_TIMEOUT_MS);

        assertTrue("Creating a reprocessable session failed.",
                state == BlockingSessionCallback.SESSION_READY);

        CameraCaptureSession session =
                sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
        assertTrue("Camera session should be a reprocessable session", session.isReprocessable());

        return session;
    }

    public static <T> void assertArrayNotEmpty(T arr, String message) {
        assertTrue(message, arr != null && Array.getLength(arr) > 0);
    }

    /**
     * Check if the format is a legal YUV format camera supported.
     */
    public static void checkYuvFormat(int format) {
        if ((format != ImageFormat.YUV_420_888) &&
                (format != ImageFormat.NV21) &&
                (format != ImageFormat.YV12)) {
            fail("Wrong formats: " + format);
        }
    }

    /**
     * Check if image size and format match given size and format.
     */
    public static void checkImage(Image image, int width, int height, int format) {
        // Image reader will wrap YV12/NV21 image by YUV_420_888
        if (format == ImageFormat.NV21 || format == ImageFormat.YV12) {
            format = ImageFormat.YUV_420_888;
        }
        assertNotNull("Input image is invalid", image);
        assertEquals("Format doesn't match", format, image.getFormat());
        assertEquals("Width doesn't match", width, image.getWidth());
        assertEquals("Height doesn't match", height, image.getHeight());
    }

    /**
     * <p>Read data from all planes of an Image into a contiguous unpadded, unpacked
     * 1-D linear byte array, such that it can be write into disk, or accessed by
     * software conveniently. It supports YUV_420_888/NV21/YV12 and JPEG input
     * Image format.</p>
     *
     * <p>For YUV_420_888/NV21/YV12/Y8/Y16, it returns a byte array that contains
     * the Y plane data first, followed by U(Cb), V(Cr) planes if there is any
     * (xstride = width, ystride = height for chroma and luma components).</p>
     *
     * <p>For JPEG, it returns a 1-D byte array contains a complete JPEG image.</p>
     *
     * <p>For YUV P010, it returns a byte array that contains Y plane first, followed
     * by the interleaved U(Cb)/V(Cr) plane.</p>
     */
    public static byte[] getDataFromImage(Image image) {
        assertNotNull("Invalid image:", image);
        int format = image.getFormat();
        int width = image.getWidth();
        int height = image.getHeight();
        int rowStride, pixelStride;
        byte[] data = null;

        // Read image data
        Plane[] planes = image.getPlanes();
        assertTrue("Fail to get image planes", planes != null && planes.length > 0);

        // Check image validity
        checkAndroidImageFormat(image);

        ByteBuffer buffer = null;
        // JPEG doesn't have pixelstride and rowstride, treat it as 1D buffer.
        // Same goes for DEPTH_POINT_CLOUD, RAW_PRIVATE, DEPTH_JPEG, and HEIC
        if (format == ImageFormat.JPEG || format == ImageFormat.DEPTH_POINT_CLOUD ||
                format == ImageFormat.RAW_PRIVATE || format == ImageFormat.DEPTH_JPEG ||
                format == ImageFormat.HEIC) {
            buffer = planes[0].getBuffer();
            assertNotNull("Fail to get jpeg/depth/heic ByteBuffer", buffer);
            data = new byte[buffer.remaining()];
            buffer.get(data);
            buffer.rewind();
            return data;
        } else if (format == ImageFormat.YCBCR_P010) {
            // P010 samples are stored within 16 bit values
            int offset = 0;
            int bytesPerPixelRounded = (ImageFormat.getBitsPerPixel(format) + 7) / 8;
            data = new byte[width * height * bytesPerPixelRounded];
            assertTrue("Unexpected number of planes, expected " + 3 + " actual " + planes.length,
                    planes.length == 3);
            for (int i = 0; i < 2; i++) {
                buffer = planes[i].getBuffer();
                assertNotNull("Fail to get bytebuffer from plane", buffer);
                buffer.rewind();
                rowStride = planes[i].getRowStride();
                if (VERBOSE) {
                    Log.v(TAG, "rowStride " + rowStride);
                    Log.v(TAG, "width " + width);
                    Log.v(TAG, "height " + height);
                }
                int h = (i == 0) ? height : height / 2;
                for (int row = 0; row < h; row++) {
                    // Each 10-bit pixel occupies 2 bytes
                    int length = 2 * width;
                    buffer.get(data, offset, length);
                    offset += length;
                    if (row < h - 1) {
                        buffer.position(buffer.position() + rowStride - length);
                    }
                }
                if (VERBOSE) Log.v(TAG, "Finished reading data from plane " + i);
                buffer.rewind();
            }
            return data;
        }

        int offset = 0;
        data = new byte[width * height * ImageFormat.getBitsPerPixel(format) / 8];
        int maxRowSize = planes[0].getRowStride();
        for (int i = 0; i < planes.length; i++) {
            if (maxRowSize < planes[i].getRowStride()) {
                maxRowSize = planes[i].getRowStride();
            }
        }
        byte[] rowData = new byte[maxRowSize];
        if(VERBOSE) Log.v(TAG, "get data from " + planes.length + " planes");
        for (int i = 0; i < planes.length; i++) {
            buffer = planes[i].getBuffer();
            assertNotNull("Fail to get bytebuffer from plane", buffer);
            buffer.rewind();
            rowStride = planes[i].getRowStride();
            pixelStride = planes[i].getPixelStride();
            assertTrue("pixel stride " + pixelStride + " is invalid", pixelStride > 0);
            if (VERBOSE) {
                Log.v(TAG, "pixelStride " + pixelStride);
                Log.v(TAG, "rowStride " + rowStride);
                Log.v(TAG, "width " + width);
                Log.v(TAG, "height " + height);
            }
            // For multi-planar yuv images, assuming yuv420 with 2x2 chroma subsampling.
            int w = (i == 0) ? width : width / 2;
            int h = (i == 0) ? height : height / 2;
            assertTrue("rowStride " + rowStride + " should be >= width " + w , rowStride >= w);
            for (int row = 0; row < h; row++) {
                int bytesPerPixel = ImageFormat.getBitsPerPixel(format) / 8;
                int length;
                if (pixelStride == bytesPerPixel) {
                    // Special case: optimized read of the entire row
                    length = w * bytesPerPixel;
                    buffer.get(data, offset, length);
                    offset += length;
                } else {
                    // Generic case: should work for any pixelStride but slower.
                    // Use intermediate buffer to avoid read byte-by-byte from
                    // DirectByteBuffer, which is very bad for performance
                    length = (w - 1) * pixelStride + bytesPerPixel;
                    buffer.get(rowData, 0, length);
                    for (int col = 0; col < w; col++) {
                        data[offset++] = rowData[col * pixelStride];
                    }
                }
                // Advance buffer the remainder of the row stride
                if (row < h - 1) {
                    buffer.position(buffer.position() + rowStride - length);
                }
            }
            if (VERBOSE) Log.v(TAG, "Finished reading data from plane " + i);
            buffer.rewind();
        }
        return data;
    }

    /**
     * <p>Check android image format validity for an image, only support below formats:</p>
     *
     * <p>YUV_420_888/NV21/YV12, can add more for future</p>
     */
    public static void checkAndroidImageFormat(Image image) {
        int format = image.getFormat();
        Plane[] planes = image.getPlanes();
        switch (format) {
            case ImageFormat.YUV_420_888:
            case ImageFormat.NV21:
            case ImageFormat.YV12:
            case ImageFormat.YCBCR_P010:
                assertEquals("YUV420 format Images should have 3 planes", 3, planes.length);
                break;
            case ImageFormat.JPEG:
            case ImageFormat.RAW_SENSOR:
            case ImageFormat.RAW_PRIVATE:
            case ImageFormat.DEPTH16:
            case ImageFormat.DEPTH_POINT_CLOUD:
            case ImageFormat.DEPTH_JPEG:
            case ImageFormat.Y8:
            case ImageFormat.HEIC:
                assertEquals("JPEG/RAW/depth/Y8 Images should have one plane", 1, planes.length);
                break;
            default:
                fail("Unsupported Image Format: " + format);
        }
    }

    public static void dumpFile(String fileName, Bitmap data) {
        FileOutputStream outStream;
        try {
            Log.v(TAG, "output will be saved as " + fileName);
            outStream = new FileOutputStream(fileName);
        } catch (IOException ioe) {
            throw new RuntimeException("Unable to create debug output file " + fileName, ioe);
        }

        try {
            data.compress(Bitmap.CompressFormat.JPEG, /*quality*/90, outStream);
            outStream.close();
        } catch (IOException ioe) {
            throw new RuntimeException("failed writing data to file " + fileName, ioe);
        }
    }

    public static void dumpFile(String fileName, byte[] data) {
        FileOutputStream outStream;
        try {
            Log.v(TAG, "output will be saved as " + fileName);
            outStream = new FileOutputStream(fileName);
        } catch (IOException ioe) {
            throw new RuntimeException("Unable to create debug output file " + fileName, ioe);
        }

        try {
            outStream.write(data);
            outStream.close();
        } catch (IOException ioe) {
            throw new RuntimeException("failed writing data to file " + fileName, ioe);
        }
    }

    /**
     * Get the available output sizes for the user-defined {@code format}.
     *
     * <p>Note that implementation-defined/hidden formats are not supported.</p>
     */
    public static Size[] getSupportedSizeForFormat(int format, String cameraId,
            CameraManager cameraManager) throws CameraAccessException {
        return getSupportedSizeForFormat(format, cameraId, cameraManager,
                /*maxResolution*/false);
    }

    public static Size[] getSupportedSizeForFormat(int format, String cameraId,
            CameraManager cameraManager, boolean maxResolution) throws CameraAccessException {
        CameraCharacteristics properties = cameraManager.getCameraCharacteristics(cameraId);
        assertNotNull("Can't get camera characteristics!", properties);
        if (VERBOSE) {
            Log.v(TAG, "get camera characteristics for camera: " + cameraId);
        }
        CameraCharacteristics.Key<StreamConfigurationMap> configMapTag = maxResolution ?
                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION :
                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP;
        StreamConfigurationMap configMap = properties.get(configMapTag);
        if (configMap == null) {
            assertTrue("SCALER_STREAM_CONFIGURATION_MAP is null!", maxResolution);
            return null;
        }

        Size[] availableSizes = configMap.getOutputSizes(format);
        if (!maxResolution) {
            assertArrayNotEmpty(availableSizes, "availableSizes should not be empty for format: "
                    + format);
        }
        Size[] highResAvailableSizes = configMap.getHighResolutionOutputSizes(format);
        if (highResAvailableSizes != null && highResAvailableSizes.length > 0) {
            Size[] allSizes = new Size[availableSizes.length + highResAvailableSizes.length];
            System.arraycopy(availableSizes, 0, allSizes, 0,
                    availableSizes.length);
            System.arraycopy(highResAvailableSizes, 0, allSizes, availableSizes.length,
                    highResAvailableSizes.length);
            availableSizes = allSizes;
        }
        if (VERBOSE) Log.v(TAG, "Supported sizes are: " + Arrays.deepToString(availableSizes));
        return availableSizes;
    }

    /**
     * Get the available output sizes for the given class.
     *
     */
    public static Size[] getSupportedSizeForClass(Class klass, String cameraId,
            CameraManager cameraManager) throws CameraAccessException {
        CameraCharacteristics properties = cameraManager.getCameraCharacteristics(cameraId);
        assertNotNull("Can't get camera characteristics!", properties);
        if (VERBOSE) {
            Log.v(TAG, "get camera characteristics for camera: " + cameraId);
        }
        StreamConfigurationMap configMap =
                properties.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        Size[] availableSizes = configMap.getOutputSizes(klass);
        assertArrayNotEmpty(availableSizes, "availableSizes should not be empty for class: "
                + klass);
        Size[] highResAvailableSizes = configMap.getHighResolutionOutputSizes(ImageFormat.PRIVATE);
        if (highResAvailableSizes != null && highResAvailableSizes.length > 0) {
            Size[] allSizes = new Size[availableSizes.length + highResAvailableSizes.length];
            System.arraycopy(availableSizes, 0, allSizes, 0,
                    availableSizes.length);
            System.arraycopy(highResAvailableSizes, 0, allSizes, availableSizes.length,
                    highResAvailableSizes.length);
            availableSizes = allSizes;
        }
        if (VERBOSE) Log.v(TAG, "Supported sizes are: " + Arrays.deepToString(availableSizes));
        return availableSizes;
    }

    /**
     * Size comparator that compares the number of pixels it covers.
     *
     * <p>If two the areas of two sizes are same, compare the widths.</p>
     */
    public static class SizeComparator implements Comparator<Size> {
        @Override
        public int compare(Size lhs, Size rhs) {
            return CameraUtils
                    .compareSizes(lhs.getWidth(), lhs.getHeight(), rhs.getWidth(), rhs.getHeight());
        }
    }

    /**
     * Get sorted size list in descending order. Remove the sizes larger than
     * the bound. If the bound is null, don't do the size bound filtering.
     */
    static public List<Size> getSupportedPreviewSizes(String cameraId,
            CameraManager cameraManager, Size bound) throws CameraAccessException {

        Size[] rawSizes = getSupportedSizeForClass(android.view.SurfaceHolder.class, cameraId,
                cameraManager);
        assertArrayNotEmpty(rawSizes,
                "Available sizes for SurfaceHolder class should not be empty");
        if (VERBOSE) {
            Log.v(TAG, "Supported sizes are: " + Arrays.deepToString(rawSizes));
        }

        if (bound == null) {
            return getAscendingOrderSizes(Arrays.asList(rawSizes), /*ascending*/false);
        }

        List<Size> sizes = new ArrayList<Size>();
        for (Size sz: rawSizes) {
            if (sz.getWidth() <= bound.getWidth() && sz.getHeight() <= bound.getHeight()) {
                sizes.add(sz);
            }
        }
        return getAscendingOrderSizes(sizes, /*ascending*/false);
    }

    /**
     * Get a sorted list of sizes from a given size list.
     *
     * <p>
     * The size is compare by area it covers, if the areas are same, then
     * compare the widths.
     * </p>
     *
     * @param sizeList The input size list to be sorted
     * @param ascending True if the order is ascending, otherwise descending order
     * @return The ordered list of sizes
     */
    static public List<Size> getAscendingOrderSizes(final List<Size> sizeList, boolean ascending) {
        if (sizeList == null) {
            throw new IllegalArgumentException("sizeList shouldn't be null");
        }

        Comparator<Size> comparator = new SizeComparator();
        List<Size> sortedSizes = new ArrayList<Size>();
        sortedSizes.addAll(sizeList);
        Collections.sort(sortedSizes, comparator);
        if (!ascending) {
            Collections.reverse(sortedSizes);
        }

        return sortedSizes;
    }
    /**
     * Get sorted (descending order) size list for given format. Remove the sizes larger than
     * the bound. If the bound is null, don't do the size bound filtering.
     */
    static public List<Size> getSortedSizesForFormat(String cameraId,
            CameraManager cameraManager, int format, Size bound) throws CameraAccessException {
        return getSortedSizesForFormat(cameraId, cameraManager, format, /*maxResolution*/false,
                bound);
    }

    /**
     * Get sorted (descending order) size list for given format (with an option to get sizes from
     * the maximum resolution stream configuration map). Remove the sizes larger than
     * the bound. If the bound is null, don't do the size bound filtering.
     */
    static public List<Size> getSortedSizesForFormat(String cameraId,
            CameraManager cameraManager, int format, boolean maxResolution, Size bound)
            throws CameraAccessException {
        Comparator<Size> comparator = new SizeComparator();
        Size[] sizes = getSupportedSizeForFormat(format, cameraId, cameraManager, maxResolution);
        List<Size> sortedSizes = null;
        if (bound != null) {
            sortedSizes = new ArrayList<Size>(/*capacity*/1);
            for (Size sz : sizes) {
                if (comparator.compare(sz, bound) <= 0) {
                    sortedSizes.add(sz);
                }
            }
        } else {
            sortedSizes = Arrays.asList(sizes);
        }
        assertTrue("Supported size list should have at least one element",
                sortedSizes.size() > 0);

        Collections.sort(sortedSizes, comparator);
        // Make it in descending order.
        Collections.reverse(sortedSizes);
        return sortedSizes;
    }

    /**
     * Get supported video size list for a given camera device.
     *
     * <p>
     * Filter out the sizes that are larger than the bound. If the bound is
     * null, don't do the size bound filtering.
     * </p>
     */
    static public List<Size> getSupportedVideoSizes(String cameraId,
            CameraManager cameraManager, Size bound) throws CameraAccessException {

        Size[] rawSizes = getSupportedSizeForClass(android.media.MediaRecorder.class,
                cameraId, cameraManager);
        assertArrayNotEmpty(rawSizes,
                "Available sizes for MediaRecorder class should not be empty");
        if (VERBOSE) {
            Log.v(TAG, "Supported sizes are: " + Arrays.deepToString(rawSizes));
        }

        if (bound == null) {
            return getAscendingOrderSizes(Arrays.asList(rawSizes), /*ascending*/false);
        }

        List<Size> sizes = new ArrayList<Size>();
        for (Size sz: rawSizes) {
            if (sz.getWidth() <= bound.getWidth() && sz.getHeight() <= bound.getHeight()) {
                sizes.add(sz);
            }
        }
        return getAscendingOrderSizes(sizes, /*ascending*/false);
    }

    /**
     * Get supported video size list (descending order) for a given camera device.
     *
     * <p>
     * Filter out the sizes that are larger than the bound. If the bound is
     * null, don't do the size bound filtering.
     * </p>
     */
    static public List<Size> getSupportedStillSizes(String cameraId,
            CameraManager cameraManager, Size bound) throws CameraAccessException {
        return getSortedSizesForFormat(cameraId, cameraManager, ImageFormat.JPEG, bound);
    }

    static public List<Size> getSupportedHeicSizes(String cameraId,
            CameraManager cameraManager, Size bound) throws CameraAccessException {
        return getSortedSizesForFormat(cameraId, cameraManager, ImageFormat.HEIC, bound);
    }

    static public Size getMinPreviewSize(String cameraId, CameraManager cameraManager)
            throws CameraAccessException {
        List<Size> sizes = getSupportedPreviewSizes(cameraId, cameraManager, null);
        return sizes.get(sizes.size() - 1);
    }

    /**
     * Get max supported preview size for a camera device.
     */
    static public Size getMaxPreviewSize(String cameraId, CameraManager cameraManager)
            throws CameraAccessException {
        return getMaxPreviewSize(cameraId, cameraManager, /*bound*/null);
    }

    /**
     * Get max preview size for a camera device in the supported sizes that are no larger
     * than the bound.
     */
    static public Size getMaxPreviewSize(String cameraId, CameraManager cameraManager, Size bound)
            throws CameraAccessException {
        List<Size> sizes = getSupportedPreviewSizes(cameraId, cameraManager, bound);
        return sizes.get(0);
    }

    /**
     * Get max depth size for a camera device.
     */
    static public Size getMaxDepthSize(String cameraId, CameraManager cameraManager)
            throws CameraAccessException {
        List<Size> sizes = getSortedSizesForFormat(cameraId, cameraManager, ImageFormat.DEPTH16,
                /*bound*/ null);
        return sizes.get(0);
    }

    /**
     * Return the lower size
     * @param a first size
     *
     * @param b second size
     *
     * @return Size the smaller size
     *
     * @throws IllegalArgumentException if either param was null.
     *
     */
    @NonNull public static Size getMinSize(Size a, Size b) {
        if (a == null || b == null) {
            throw new IllegalArgumentException("sizes was empty");
        }
        if (a.getWidth() * a.getHeight() < b.getHeight() * b.getWidth()) {
            return a;
        }
        return b;
    }

    /**
     * Get the largest size by area.
     *
     * @param sizes an array of sizes, must have at least 1 element
     *
     * @return Largest Size
     *
     * @throws IllegalArgumentException if sizes was null or had 0 elements
     */
    public static Size getMaxSize(Size... sizes) {
        if (sizes == null || sizes.length == 0) {
            throw new IllegalArgumentException("sizes was empty");
        }

        Size sz = sizes[0];
        for (Size size : sizes) {
            if (size.getWidth() * size.getHeight() > sz.getWidth() * sz.getHeight()) {
                sz = size;
            }
        }

        return sz;
    }

    /**
     * Get the largest size by area within (less than) bound
     *
     * @param sizes an array of sizes, must have at least 1 element
     *
     * @return Largest Size. Null if no such size exists within bound.
     *
     * @throws IllegalArgumentException if sizes was null or had 0 elements, or bound is invalid.
     */
    public static Size getMaxSizeWithBound(Size[] sizes, int bound) {
        if (sizes == null || sizes.length == 0) {
            throw new IllegalArgumentException("sizes was empty");
        }
        if (bound <= 0) {
            throw new IllegalArgumentException("bound is invalid");
        }

        Size sz = null;
        for (Size size : sizes) {
            if (size.getWidth() * size.getHeight() >= bound) {
                continue;
            }

            if (sz == null ||
                    size.getWidth() * size.getHeight() > sz.getWidth() * sz.getHeight()) {
                sz = size;
            }
        }

        return sz;
    }

    /**
     * Returns true if the given {@code array} contains the given element.
     *
     * @param array {@code array} to check for {@code elem}
     * @param elem {@code elem} to test for
     * @return {@code true} if the given element is contained
     */
    public static boolean contains(int[] array, int elem) {
        if (array == null) return false;
        for (int i = 0; i < array.length; i++) {
            if (elem == array[i]) return true;
        }
        return false;
    }

    /**
     * Get object array from byte array.
     *
     * @param array Input byte array to be converted
     * @return Byte object array converted from input byte array
     */
    public static Byte[] toObject(byte[] array) {
        return convertPrimitiveArrayToObjectArray(array, Byte.class);
    }

    /**
     * Get object array from int array.
     *
     * @param array Input int array to be converted
     * @return Integer object array converted from input int array
     */
    public static Integer[] toObject(int[] array) {
        return convertPrimitiveArrayToObjectArray(array, Integer.class);
    }

    /**
     * Get object array from float array.
     *
     * @param array Input float array to be converted
     * @return Float object array converted from input float array
     */
    public static Float[] toObject(float[] array) {
        return convertPrimitiveArrayToObjectArray(array, Float.class);
    }

    /**
     * Get object array from double array.
     *
     * @param array Input double array to be converted
     * @return Double object array converted from input double array
     */
    public static Double[] toObject(double[] array) {
        return convertPrimitiveArrayToObjectArray(array, Double.class);
    }

    /**
     * Convert a primitive input array into its object array version (e.g. from int[] to Integer[]).
     *
     * @param array Input array object
     * @param wrapperClass The boxed class it converts to
     * @return Boxed version of primitive array
     */
    private static <T> T[] convertPrimitiveArrayToObjectArray(final Object array,
            final Class<T> wrapperClass) {
        // getLength does the null check and isArray check already.
        int arrayLength = Array.getLength(array);
        if (arrayLength == 0) {
            throw new IllegalArgumentException("Input array shouldn't be empty");
        }

        @SuppressWarnings("unchecked")
        final T[] result = (T[]) Array.newInstance(wrapperClass, arrayLength);
        for (int i = 0; i < arrayLength; i++) {
            Array.set(result, i, Array.get(array, i));
        }
        return result;
    }

    /**
     * Update one 3A region in capture request builder if that region is supported. Do nothing
     * if the specified 3A region is not supported by camera device.
     * @param requestBuilder The request to be updated
     * @param algoIdx The index to the algorithm. (AE: 0, AWB: 1, AF: 2)
     * @param regions The 3A regions to be set
     * @param staticInfo static metadata characteristics
     */
    public static void update3aRegion(
            CaptureRequest.Builder requestBuilder, int algoIdx, MeteringRectangle[] regions,
            StaticMetadata staticInfo)
    {
        int maxRegions;
        CaptureRequest.Key<MeteringRectangle[]> key;

        if (regions == null || regions.length == 0 || staticInfo == null) {
            throw new IllegalArgumentException("Invalid input 3A region!");
        }

        switch (algoIdx) {
            case INDEX_ALGORITHM_AE:
                maxRegions = staticInfo.getAeMaxRegionsChecked();
                key = CaptureRequest.CONTROL_AE_REGIONS;
                break;
            case INDEX_ALGORITHM_AWB:
                maxRegions = staticInfo.getAwbMaxRegionsChecked();
                key = CaptureRequest.CONTROL_AWB_REGIONS;
                break;
            case INDEX_ALGORITHM_AF:
                maxRegions = staticInfo.getAfMaxRegionsChecked();
                key = CaptureRequest.CONTROL_AF_REGIONS;
                break;
            default:
                throw new IllegalArgumentException("Unknown 3A Algorithm!");
        }

        if (maxRegions >= regions.length) {
            requestBuilder.set(key, regions);
        }
    }

    /**
     * Validate one 3A region in capture result equals to expected region if that region is
     * supported. Do nothing if the specified 3A region is not supported by camera device.
     * @param result The capture result to be validated
     * @param partialResults The partial results to be validated
     * @param algoIdx The index to the algorithm. (AE: 0, AWB: 1, AF: 2)
     * @param expectRegions The 3A regions expected in capture result
     * @param scaleByZoomRatio whether to scale the error threshold by zoom ratio
     * @param staticInfo static metadata characteristics
     */
    public static void validate3aRegion(
            CaptureResult result, List<CaptureResult> partialResults, int algoIdx,
            MeteringRectangle[] expectRegions, boolean scaleByZoomRatio, StaticMetadata staticInfo)
    {
        // There are multiple cases where result 3A region could be slightly different than the
        // request:
        // 1. Distortion correction,
        // 2. Adding smaller 3a region in the test exposes existing devices' offset is larger
        //    than 1.
        // 3. Precision loss due to converting to HAL zoom ratio and back
        // 4. Error magnification due to active array scale-up when zoom ratio API is used.
        //
        // To handle all these scenarios, make the threshold larger, and scale the threshold based
        // on zoom ratio. The scaling factor should be relatively tight, and shouldn't be smaller
        // than 1x.
        final int maxCoordOffset = 5;
        int maxRegions;
        CaptureResult.Key<MeteringRectangle[]> key;
        MeteringRectangle[] actualRegion;

        switch (algoIdx) {
            case INDEX_ALGORITHM_AE:
                maxRegions = staticInfo.getAeMaxRegionsChecked();
                key = CaptureResult.CONTROL_AE_REGIONS;
                break;
            case INDEX_ALGORITHM_AWB:
                maxRegions = staticInfo.getAwbMaxRegionsChecked();
                key = CaptureResult.CONTROL_AWB_REGIONS;
                break;
            case INDEX_ALGORITHM_AF:
                maxRegions = staticInfo.getAfMaxRegionsChecked();
                key = CaptureResult.CONTROL_AF_REGIONS;
                break;
            default:
                throw new IllegalArgumentException("Unknown 3A Algorithm!");
        }

        int maxDist = maxCoordOffset;
        if (scaleByZoomRatio) {
            Float zoomRatio = result.get(CaptureResult.CONTROL_ZOOM_RATIO);
            for (CaptureResult partialResult : partialResults) {
                Float zoomRatioInPartial = partialResult.get(CaptureResult.CONTROL_ZOOM_RATIO);
                if (zoomRatioInPartial != null) {
                    assertEquals("CONTROL_ZOOM_RATIO in partial result must match"
                            + " that in final result", zoomRatio, zoomRatioInPartial);
                }
            }
            maxDist = (int)Math.ceil(maxDist * Math.max(zoomRatio / 2, 1.0f));
        }

        if (maxRegions > 0)
        {
            actualRegion = getValueNotNull(result, key);
            for (CaptureResult partialResult : partialResults) {
                MeteringRectangle[] actualRegionInPartial = partialResult.get(key);
                if (actualRegionInPartial != null) {
                    assertEquals("Key " + key.getName() + " in partial result must match"
                            + " that in final result", actualRegionInPartial, actualRegion);
                }
            }

            for (int i = 0; i < actualRegion.length; i++) {
                // If the expected region's metering weight is 0, allow the camera device
                // to override it.
                if (expectRegions[i].getMeteringWeight() == 0) {
                    continue;
                }

                Rect a = actualRegion[i].getRect();
                Rect e = expectRegions[i].getRect();

                if (VERBOSE) {
                    Log.v(TAG, "Actual region " + actualRegion[i].toString() +
                            ", expected region " + expectRegions[i].toString() +
                            ", maxDist " + maxDist);
                }
                assertTrue(
                    "Expected 3A regions: " + Arrays.toString(expectRegions) +
                    " are not close enough to the actual one: " + Arrays.toString(actualRegion),
                    maxDist >= Math.abs(a.left - e.left));

                assertTrue(
                    "Expected 3A regions: " + Arrays.toString(expectRegions) +
                    " are not close enough to the actual one: " + Arrays.toString(actualRegion),
                    maxDist >= Math.abs(a.right - e.right));

                assertTrue(
                    "Expected 3A regions: " + Arrays.toString(expectRegions) +
                    " are not close enough to the actual one: " + Arrays.toString(actualRegion),
                    maxDist >= Math.abs(a.top - e.top));
                assertTrue(
                    "Expected 3A regions: " + Arrays.toString(expectRegions) +
                    " are not close enough to the actual one: " + Arrays.toString(actualRegion),
                    maxDist >= Math.abs(a.bottom - e.bottom));
            }
        }
    }


    /**
     * Validate image based on format and size.
     *
     * @param image The image to be validated.
     * @param width The image width.
     * @param height The image height.
     * @param format The image format.
     * @param filePath The debug dump file path, null if don't want to dump to
     *            file.
     * @throws UnsupportedOperationException if calling with an unknown format
     */
    public static void validateImage(Image image, int width, int height, int format,
            String filePath) {
        checkImage(image, width, height, format);

        /**
         * TODO: validate timestamp:
         * 1. capture result timestamp against the image timestamp (need
         * consider frame drops)
         * 2. timestamps should be monotonically increasing for different requests
         */
        if(VERBOSE) Log.v(TAG, "validating Image");
        byte[] data = getDataFromImage(image);
        assertTrue("Invalid image data", data != null && data.length > 0);

        switch (format) {
            // Clients must be able to process and handle depth jpeg images like any other
            // regular jpeg.
            case ImageFormat.DEPTH_JPEG:
            case ImageFormat.JPEG:
                validateJpegData(data, width, height, filePath);
                break;
            case ImageFormat.YCBCR_P010:
                validateP010Data(data, width, height, format, image.getTimestamp(), filePath);
                break;
            case ImageFormat.YUV_420_888:
            case ImageFormat.YV12:
                validateYuvData(data, width, height, format, image.getTimestamp(), filePath);
                break;
            case ImageFormat.RAW_SENSOR:
                validateRaw16Data(data, width, height, format, image.getTimestamp(), filePath);
                break;
            case ImageFormat.DEPTH16:
                validateDepth16Data(data, width, height, format, image.getTimestamp(), filePath);
                break;
            case ImageFormat.DEPTH_POINT_CLOUD:
                validateDepthPointCloudData(data, width, height, format, image.getTimestamp(), filePath);
                break;
            case ImageFormat.RAW_PRIVATE:
                validateRawPrivateData(data, width, height, image.getTimestamp(), filePath);
                break;
            case ImageFormat.Y8:
                validateY8Data(data, width, height, format, image.getTimestamp(), filePath);
                break;
            case ImageFormat.HEIC:
                validateHeicData(data, width, height, filePath);
                break;
            default:
                throw new UnsupportedOperationException("Unsupported format for validation: "
                        + format);
        }
    }

    public static class HandlerExecutor implements Executor {
        private final Handler mHandler;

        public HandlerExecutor(Handler handler) {
            assertNotNull("handler must be valid", handler);
            mHandler = handler;
        }

        @Override
        public void execute(Runnable runCmd) {
            mHandler.post(runCmd);
        }
    }

    /**
     * Provide a mock for {@link CameraDevice.StateCallback}.
     *
     * <p>Only useful because mockito can't mock {@link CameraDevice.StateCallback} which is an
     * abstract class.</p>
     *
     * <p>
     * Use this instead of other classes when needing to verify interactions, since
     * trying to spy on {@link BlockingStateCallback} (or others) will cause unnecessary extra
     * interactions which will cause false test failures.
     * </p>
     *
     */
    public static class MockStateCallback extends CameraDevice.StateCallback {

        @Override
        public void onOpened(CameraDevice camera) {
        }

        @Override
        public void onDisconnected(CameraDevice camera) {
        }

        @Override
        public void onError(CameraDevice camera, int error) {
        }

        private MockStateCallback() {}

        /**
         * Create a Mockito-ready mocked StateCallback.
         */
        public static MockStateCallback mock() {
            return Mockito.spy(new MockStateCallback());
        }
    }

    public static void validateJpegData(byte[] jpegData, int width, int height, String filePath) {
        BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
        // DecodeBound mode: only parse the frame header to get width/height.
        // it doesn't decode the pixel.
        bmpOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, bmpOptions);
        assertEquals(width, bmpOptions.outWidth);
        assertEquals(height, bmpOptions.outHeight);

        // Pixel decoding mode: decode whole image. check if the image data
        // is decodable here.
        assertNotNull("Decoding jpeg failed",
                BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length));
        if (DEBUG && filePath != null) {
            String fileName =
                    filePath + "/" + width + "x" + height + ".jpeg";
            dumpFile(fileName, jpegData);
        }
    }

    private static void validateYuvData(byte[] yuvData, int width, int height, int format,
            long ts, String filePath) {
        checkYuvFormat(format);
        if (VERBOSE) Log.v(TAG, "Validating YUV data");
        int expectedSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
        assertEquals("Yuv data doesn't match", expectedSize, yuvData.length);

        // TODO: Can add data validation for test pattern.

        if (DEBUG && filePath != null) {
            String fileName =
                    filePath + "/" + width + "x" + height + "_" + ts / 1e6 + ".yuv";
            dumpFile(fileName, yuvData);
        }
    }

    private static void validateP010Data(byte[] p010Data, int width, int height, int format,
            long ts, String filePath) {
        if (VERBOSE) Log.v(TAG, "Validating P010 data");
        // The P010 10 bit samples are stored in two bytes so the size needs to be adjusted
        // accordingly.
        int bytesPerPixelRounded = (ImageFormat.getBitsPerPixel(format) + 7) / 8;
        int expectedSize = width * height * bytesPerPixelRounded;
        assertEquals("P010 data doesn't match", expectedSize, p010Data.length);

        if (DEBUG && filePath != null) {
            String fileName =
                    filePath + "/" + width + "x" + height + "_" + ts / 1e6 + ".p010";
            dumpFile(fileName, p010Data);
        }
    }
    private static void validateRaw16Data(byte[] rawData, int width, int height, int format,
            long ts, String filePath) {
        if (VERBOSE) Log.v(TAG, "Validating raw data");
        int expectedSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
        assertEquals("Raw data doesn't match", expectedSize, rawData.length);

        // TODO: Can add data validation for test pattern.

        if (DEBUG && filePath != null) {
            String fileName =
                    filePath + "/" + width + "x" + height + "_" + ts / 1e6 + ".raw16";
            dumpFile(fileName, rawData);
        }

        return;
    }

    private static void validateY8Data(byte[] rawData, int width, int height, int format,
            long ts, String filePath) {
        if (VERBOSE) Log.v(TAG, "Validating Y8 data");
        int expectedSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
        assertEquals("Y8 data doesn't match", expectedSize, rawData.length);

        // TODO: Can add data validation for test pattern.

        if (DEBUG && filePath != null) {
            String fileName =
                    filePath + "/" + width + "x" + height + "_" + ts / 1e6 + ".y8";
            dumpFile(fileName, rawData);
        }

        return;
    }

    private static void validateRawPrivateData(byte[] rawData, int width, int height,
            long ts, String filePath) {
        if (VERBOSE) Log.v(TAG, "Validating private raw data");
        // Expect each RAW pixel should occupy at least one byte and no more than 30 bytes
        int expectedSizeMin = width * height;
        int expectedSizeMax = width * height * 30;

        assertTrue("Opaque RAW size " + rawData.length + "out of normal bound [" +
                expectedSizeMin + "," + expectedSizeMax + "]",
                expectedSizeMin <= rawData.length && rawData.length <= expectedSizeMax);

        if (DEBUG && filePath != null) {
            String fileName =
                    filePath + "/" + width + "x" + height + "_" + ts / 1e6 + ".rawPriv";
            dumpFile(fileName, rawData);
        }

        return;
    }

    private static void validateDepth16Data(byte[] depthData, int width, int height, int format,
            long ts, String filePath) {

        if (VERBOSE) Log.v(TAG, "Validating depth16 data");
        int expectedSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
        assertEquals("Depth data doesn't match", expectedSize, depthData.length);


        if (DEBUG && filePath != null) {
            String fileName =
                    filePath + "/" + width + "x" + height + "_" + ts / 1e6 + ".depth16";
            dumpFile(fileName, depthData);
        }

        return;

    }

    private static void validateDepthPointCloudData(byte[] depthData, int width, int height, int format,
            long ts, String filePath) {

        if (VERBOSE) Log.v(TAG, "Validating depth point cloud data");

        // Can't validate size since it is variable

        if (DEBUG && filePath != null) {
            String fileName =
                    filePath + "/" + width + "x" + height + "_" + ts / 1e6 + ".depth_point_cloud";
            dumpFile(fileName, depthData);
        }

        return;

    }

    private static void validateHeicData(byte[] heicData, int width, int height, String filePath) {
        BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
        // DecodeBound mode: only parse the frame header to get width/height.
        // it doesn't decode the pixel.
        bmpOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(heicData, 0, heicData.length, bmpOptions);
        assertEquals(width, bmpOptions.outWidth);
        assertEquals(height, bmpOptions.outHeight);

        // Pixel decoding mode: decode whole image. check if the image data
        // is decodable here.
        assertNotNull("Decoding heic failed",
                BitmapFactory.decodeByteArray(heicData, 0, heicData.length));
        if (DEBUG && filePath != null) {
            String fileName =
                    filePath + "/" + width + "x" + height + ".heic";
            dumpFile(fileName, heicData);
        }
    }

    public static <T> T getValueNotNull(CaptureResult result, CaptureResult.Key<T> key) {
        if (result == null) {
            throw new IllegalArgumentException("Result must not be null");
        }

        T value = result.get(key);
        assertNotNull("Value of Key " + key.getName() + "shouldn't be null", value);
        return value;
    }

    public static <T> T getValueNotNull(CameraCharacteristics characteristics,
            CameraCharacteristics.Key<T> key) {
        if (characteristics == null) {
            throw new IllegalArgumentException("Camera characteristics must not be null");
        }

        T value = characteristics.get(key);
        assertNotNull("Value of Key " + key.getName() + "shouldn't be null", value);
        return value;
    }

    /**
     * Get a crop region for a given zoom factor and center position.
     * <p>
     * The center position is normalized position in range of [0, 1.0], where
     * (0, 0) represents top left corner, (1.0. 1.0) represents bottom right
     * corner. The center position could limit the effective minimal zoom
     * factor, for example, if the center position is (0.75, 0.75), the
     * effective minimal zoom position becomes 2.0. If the requested zoom factor
     * is smaller than 2.0, a crop region with 2.0 zoom factor will be returned.
     * </p>
     * <p>
     * The aspect ratio of the crop region is maintained the same as the aspect
     * ratio of active array.
     * </p>
     *
     * @param zoomFactor The zoom factor to generate the crop region, it must be
     *            >= 1.0
     * @param center The normalized zoom center point that is in the range of [0, 1].
     * @param maxZoom The max zoom factor supported by this device.
     * @param activeArray The active array size of this device.
     * @return crop region for the given normalized center and zoom factor.
     */
    public static Rect getCropRegionForZoom(float zoomFactor, final PointF center,
            final float maxZoom, final Rect activeArray) {
        if (zoomFactor < 1.0) {
            throw new IllegalArgumentException("zoom factor " + zoomFactor + " should be >= 1.0");
        }
        if (center.x > 1.0 || center.x < 0) {
            throw new IllegalArgumentException("center.x " + center.x
                    + " should be in range of [0, 1.0]");
        }
        if (center.y > 1.0 || center.y < 0) {
            throw new IllegalArgumentException("center.y " + center.y
                    + " should be in range of [0, 1.0]");
        }
        if (maxZoom < 1.0) {
            throw new IllegalArgumentException("max zoom factor " + maxZoom + " should be >= 1.0");
        }
        if (activeArray == null) {
            throw new IllegalArgumentException("activeArray must not be null");
        }

        float minCenterLength = Math.min(Math.min(center.x, 1.0f - center.x),
                Math.min(center.y, 1.0f - center.y));
        float minEffectiveZoom =  0.5f / minCenterLength;
        if (minEffectiveZoom > maxZoom) {
            throw new IllegalArgumentException("Requested center " + center.toString() +
                    " has minimal zoomable factor " + minEffectiveZoom + ", which exceeds max"
                            + " zoom factor " + maxZoom);
        }

        if (zoomFactor < minEffectiveZoom) {
            Log.w(TAG, "Requested zoomFactor " + zoomFactor + " < minimal zoomable factor "
                    + minEffectiveZoom + ". It will be overwritten by " + minEffectiveZoom);
            zoomFactor = minEffectiveZoom;
        }

        int cropCenterX = (int)(activeArray.width() * center.x);
        int cropCenterY = (int)(activeArray.height() * center.y);
        int cropWidth = (int) (activeArray.width() / zoomFactor);
        int cropHeight = (int) (activeArray.height() / zoomFactor);

        return new Rect(
                /*left*/cropCenterX - cropWidth / 2,
                /*top*/cropCenterY - cropHeight / 2,
                /*right*/ cropCenterX + cropWidth / 2,
                /*bottom*/cropCenterY + cropHeight / 2);
    }

    /**
     * Get AeAvailableTargetFpsRanges and sort them in descending order by max fps
     *
     * @param staticInfo camera static metadata
     * @return AeAvailableTargetFpsRanges in descending order by max fps
     */
    public static Range<Integer>[] getDescendingTargetFpsRanges(StaticMetadata staticInfo) {
        Range<Integer>[] fpsRanges = staticInfo.getAeAvailableTargetFpsRangesChecked();
        Arrays.sort(fpsRanges, new Comparator<Range<Integer>>() {
            public int compare(Range<Integer> r1, Range<Integer> r2) {
                return r2.getUpper() - r1.getUpper();
            }
        });
        return fpsRanges;
    }

    /**
     * Get AeAvailableTargetFpsRanges with max fps not exceeding 30
     *
     * @param staticInfo camera static metadata
     * @return AeAvailableTargetFpsRanges with max fps not exceeding 30
     */
    public static List<Range<Integer>> getTargetFpsRangesUpTo30(StaticMetadata staticInfo) {
        Range<Integer>[] fpsRanges = staticInfo.getAeAvailableTargetFpsRangesChecked();
        ArrayList<Range<Integer>> fpsRangesUpTo30 = new ArrayList<Range<Integer>>();
        for (Range<Integer> fpsRange : fpsRanges) {
            if (fpsRange.getUpper() <= 30) {
                fpsRangesUpTo30.add(fpsRange);
            }
        }
        return fpsRangesUpTo30;
    }

    /**
     * Get AeAvailableTargetFpsRanges with max fps greater than 30
     *
     * @param staticInfo camera static metadata
     * @return AeAvailableTargetFpsRanges with max fps greater than 30
     */
    public static List<Range<Integer>> getTargetFpsRangesGreaterThan30(StaticMetadata staticInfo) {
        Range<Integer>[] fpsRanges = staticInfo.getAeAvailableTargetFpsRangesChecked();
        ArrayList<Range<Integer>> fpsRangesGreaterThan30 = new ArrayList<Range<Integer>>();
        for (Range<Integer> fpsRange : fpsRanges) {
            if (fpsRange.getUpper() > 30) {
                fpsRangesGreaterThan30.add(fpsRange);
            }
        }
        return fpsRangesGreaterThan30;
    }

    /**
     * Calculate output 3A region from the intersection of input 3A region and cropped region.
     *
     * @param requestRegions The input 3A regions
     * @param cropRect The cropped region
     * @return expected 3A regions output in capture result
     */
    public static MeteringRectangle[] getExpectedOutputRegion(
            MeteringRectangle[] requestRegions, Rect cropRect){
        MeteringRectangle[] resultRegions = new MeteringRectangle[requestRegions.length];
        for (int i = 0; i < requestRegions.length; i++) {
            Rect requestRect = requestRegions[i].getRect();
            Rect resultRect = new Rect();
            boolean intersect = resultRect.setIntersect(requestRect, cropRect);
            resultRegions[i] = new MeteringRectangle(
                    resultRect,
                    intersect ? requestRegions[i].getMeteringWeight() : 0);
        }
        return resultRegions;
    }

    /**
     * Copy source image data to destination image.
     *
     * @param src The source image to be copied from.
     * @param dst The destination image to be copied to.
     * @throws IllegalArgumentException If the source and destination images have
     *             different format, size, or one of the images is not copyable.
     */
    public static void imageCopy(Image src, Image dst) {
        if (src == null || dst == null) {
            throw new IllegalArgumentException("Images should be non-null");
        }
        if (src.getFormat() != dst.getFormat()) {
            throw new IllegalArgumentException("Src and dst images should have the same format");
        }
        if (src.getFormat() == ImageFormat.PRIVATE ||
                dst.getFormat() == ImageFormat.PRIVATE) {
            throw new IllegalArgumentException("PRIVATE format images are not copyable");
        }

        Size srcSize = new Size(src.getWidth(), src.getHeight());
        Size dstSize = new Size(dst.getWidth(), dst.getHeight());
        if (!srcSize.equals(dstSize)) {
            throw new IllegalArgumentException("source image size " + srcSize + " is different"
                    + " with " + "destination image size " + dstSize);
        }

        // TODO: check the owner of the dst image, it must be from ImageWriter, other source may
        // not be writable. Maybe we should add an isWritable() method in image class.

        Plane[] srcPlanes = src.getPlanes();
        Plane[] dstPlanes = dst.getPlanes();
        ByteBuffer srcBuffer = null;
        ByteBuffer dstBuffer = null;
        for (int i = 0; i < srcPlanes.length; i++) {
            srcBuffer = srcPlanes[i].getBuffer();
            dstBuffer = dstPlanes[i].getBuffer();
            int srcPos = srcBuffer.position();
            srcBuffer.rewind();
            dstBuffer.rewind();
            int srcRowStride = srcPlanes[i].getRowStride();
            int dstRowStride = dstPlanes[i].getRowStride();
            int srcPixStride = srcPlanes[i].getPixelStride();
            int dstPixStride = dstPlanes[i].getPixelStride();

            if (srcPixStride > 2 || dstPixStride > 2) {
                throw new IllegalArgumentException("source pixel stride " + srcPixStride +
                        " with destination pixel stride " + dstPixStride +
                        " is not supported");
            }

            if (srcRowStride == dstRowStride && srcPixStride == dstPixStride &&
                    srcPixStride == 1) {
                // Fast path, just copy the content in the byteBuffer all together.
                dstBuffer.put(srcBuffer);
            } else {
                Size effectivePlaneSize = getEffectivePlaneSizeForImage(src, i);
                int srcRowByteCount = srcRowStride;
                int dstRowByteCount = dstRowStride;
                byte[] srcDataRow = new byte[Math.max(srcRowStride, dstRowStride)];

                if (srcPixStride == dstPixStride && srcPixStride == 1) {
                    // Row by row copy case
                    for (int row = 0; row < effectivePlaneSize.getHeight(); row++) {
                        if (row == effectivePlaneSize.getHeight() - 1) {
                            // Special case for interleaved planes: need handle the last row
                            // carefully to avoid memory corruption. Check if we have enough bytes
                            // to copy.
                            srcRowByteCount = Math.min(srcRowByteCount, srcBuffer.remaining());
                            dstRowByteCount = Math.min(dstRowByteCount, dstBuffer.remaining());
                        }
                        srcBuffer.get(srcDataRow, /*offset*/0, srcRowByteCount);
                        dstBuffer.put(srcDataRow, /*offset*/0, dstRowByteCount);
                    }
                } else {
                    // Row by row per pixel copy case
                    byte[] dstDataRow = new byte[dstRowByteCount];
                    for (int row = 0; row < effectivePlaneSize.getHeight(); row++) {
                        if (row == effectivePlaneSize.getHeight() - 1) {
                            // Special case for interleaved planes: need handle the last row
                            // carefully to avoid memory corruption. Check if we have enough bytes
                            // to copy.
                            int remainingBytes = srcBuffer.remaining();
                            if (srcRowByteCount > remainingBytes) {
                                srcRowByteCount = remainingBytes;
                            }
                            remainingBytes = dstBuffer.remaining();
                            if (dstRowByteCount > remainingBytes) {
                                dstRowByteCount = remainingBytes;
                            }
                        }
                        srcBuffer.get(srcDataRow, /*offset*/0, srcRowByteCount);
                        int pos = dstBuffer.position();
                        dstBuffer.get(dstDataRow, /*offset*/0, dstRowByteCount);
                        dstBuffer.position(pos);
                        for (int x = 0; x < effectivePlaneSize.getWidth(); x++) {
                            dstDataRow[x * dstPixStride] = srcDataRow[x * srcPixStride];
                        }
                        dstBuffer.put(dstDataRow, /*offset*/0, dstRowByteCount);
                    }
                }
            }
            srcBuffer.position(srcPos);
            dstBuffer.rewind();
        }
    }

    private static Size getEffectivePlaneSizeForImage(Image image, int planeIdx) {
        switch (image.getFormat()) {
            case ImageFormat.YUV_420_888:
                if (planeIdx == 0) {
                    return new Size(image.getWidth(), image.getHeight());
                } else {
                    return new Size(image.getWidth() / 2, image.getHeight() / 2);
                }
            case ImageFormat.JPEG:
            case ImageFormat.RAW_SENSOR:
            case ImageFormat.RAW10:
            case ImageFormat.RAW12:
            case ImageFormat.DEPTH16:
                return new Size(image.getWidth(), image.getHeight());
            case ImageFormat.PRIVATE:
                return new Size(0, 0);
            default:
                throw new UnsupportedOperationException(
                        String.format("Invalid image format %d", image.getFormat()));
        }
    }

    /**
     * <p>
     * Checks whether the two images are strongly equal.
     * </p>
     * <p>
     * Two images are strongly equal if and only if the data, formats, sizes,
     * and timestamps are same. For {@link ImageFormat#PRIVATE PRIVATE} format
     * images, the image data is not not accessible thus the data comparison is
     * effectively skipped as the number of planes is zero.
     * </p>
     * <p>
     * Note that this method compares the pixel data even outside of the crop
     * region, which may not be necessary for general use case.
     * </p>
     *
     * @param lhsImg First image to be compared with.
     * @param rhsImg Second image to be compared with.
     * @return true if the two images are equal, false otherwise.
     * @throws IllegalArgumentException If either of image is null.
     */
    public static boolean isImageStronglyEqual(Image lhsImg, Image rhsImg) {
        if (lhsImg == null || rhsImg == null) {
            throw new IllegalArgumentException("Images should be non-null");
        }

        if (lhsImg.getFormat() != rhsImg.getFormat()) {
            Log.i(TAG, "lhsImg format " + lhsImg.getFormat() + " is different with rhsImg format "
                    + rhsImg.getFormat());
            return false;
        }

        if (lhsImg.getWidth() != rhsImg.getWidth()) {
            Log.i(TAG, "lhsImg width " + lhsImg.getWidth() + " is different with rhsImg width "
                    + rhsImg.getWidth());
            return false;
        }

        if (lhsImg.getHeight() != rhsImg.getHeight()) {
            Log.i(TAG, "lhsImg height " + lhsImg.getHeight() + " is different with rhsImg height "
                    + rhsImg.getHeight());
            return false;
        }

        if (lhsImg.getTimestamp() != rhsImg.getTimestamp()) {
            Log.i(TAG, "lhsImg timestamp " + lhsImg.getTimestamp()
                    + " is different with rhsImg timestamp " + rhsImg.getTimestamp());
            return false;
        }

        if (!lhsImg.getCropRect().equals(rhsImg.getCropRect())) {
            Log.i(TAG, "lhsImg crop rect " + lhsImg.getCropRect()
                    + " is different with rhsImg crop rect " + rhsImg.getCropRect());
            return false;
        }

        // Compare data inside of the image.
        Plane[] lhsPlanes = lhsImg.getPlanes();
        Plane[] rhsPlanes = rhsImg.getPlanes();
        ByteBuffer lhsBuffer = null;
        ByteBuffer rhsBuffer = null;
        for (int i = 0; i < lhsPlanes.length; i++) {
            lhsBuffer = lhsPlanes[i].getBuffer();
            rhsBuffer = rhsPlanes[i].getBuffer();
            lhsBuffer.rewind();
            rhsBuffer.rewind();
            // Special case for YUV420_888 buffer with different layout or
            // potentially differently interleaved U/V planes.
            if (lhsImg.getFormat() == ImageFormat.YUV_420_888 &&
                    (lhsPlanes[i].getPixelStride() != rhsPlanes[i].getPixelStride() ||
                     lhsPlanes[i].getRowStride() != rhsPlanes[i].getRowStride() ||
                     (lhsPlanes[i].getPixelStride() != 1))) {
                int width = getEffectivePlaneSizeForImage(lhsImg, i).getWidth();
                int height = getEffectivePlaneSizeForImage(lhsImg, i).getHeight();
                int rowSizeL = lhsPlanes[i].getRowStride();
                int rowSizeR = rhsPlanes[i].getRowStride();
                byte[] lhsRow = new byte[rowSizeL];
                byte[] rhsRow = new byte[rowSizeR];
                int pixStrideL = lhsPlanes[i].getPixelStride();
                int pixStrideR = rhsPlanes[i].getPixelStride();
                for (int r = 0; r < height; r++) {
                    if (r == height -1) {
                        rowSizeL = lhsBuffer.remaining();
                        rowSizeR = rhsBuffer.remaining();
                    }
                    lhsBuffer.get(lhsRow, /*offset*/0, rowSizeL);
                    rhsBuffer.get(rhsRow, /*offset*/0, rowSizeR);
                    for (int c = 0; c < width; c++) {
                        if (lhsRow[c * pixStrideL] != rhsRow[c * pixStrideR]) {
                            Log.i(TAG, String.format(
                                    "byte buffers for plane %d row %d col %d don't match.",
                                    i, r, c));
                            return false;
                        }
                    }
                }
            } else {
                // Compare entire buffer directly
                if (!lhsBuffer.equals(rhsBuffer)) {
                    Log.i(TAG, "byte buffers for plane " +  i + " don't match.");
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Set jpeg related keys in a capture request builder.
     *
     * @param builder The capture request builder to set the keys inl
     * @param exifData The exif data to set.
     * @param thumbnailSize The thumbnail size to set.
     * @param collector The camera error collector to collect errors.
     */
    public static void setJpegKeys(CaptureRequest.Builder builder, ExifTestData exifData,
            Size thumbnailSize, CameraErrorCollector collector) {
        builder.set(CaptureRequest.JPEG_THUMBNAIL_SIZE, thumbnailSize);
        builder.set(CaptureRequest.JPEG_GPS_LOCATION, exifData.gpsLocation);
        builder.set(CaptureRequest.JPEG_ORIENTATION, exifData.jpegOrientation);
        builder.set(CaptureRequest.JPEG_QUALITY, exifData.jpegQuality);
        builder.set(CaptureRequest.JPEG_THUMBNAIL_QUALITY,
                exifData.thumbnailQuality);

        // Validate request set and get.
        collector.expectEquals("JPEG thumbnail size request set and get should match",
                thumbnailSize, builder.get(CaptureRequest.JPEG_THUMBNAIL_SIZE));
        collector.expectTrue("GPS locations request set and get should match.",
                areGpsFieldsEqual(exifData.gpsLocation,
                builder.get(CaptureRequest.JPEG_GPS_LOCATION)));
        collector.expectEquals("JPEG orientation request set and get should match",
                exifData.jpegOrientation,
                builder.get(CaptureRequest.JPEG_ORIENTATION));
        collector.expectEquals("JPEG quality request set and get should match",
                exifData.jpegQuality, builder.get(CaptureRequest.JPEG_QUALITY));
        collector.expectEquals("JPEG thumbnail quality request set and get should match",
                exifData.thumbnailQuality,
                builder.get(CaptureRequest.JPEG_THUMBNAIL_QUALITY));
    }

    /**
     * Simple validation of JPEG image size and format.
     * <p>
     * Only validate the image object basic correctness. It is fast, but doesn't actually
     * check the buffer data. Assert is used here as it make no sense to
     * continue the test if the jpeg image captured has some serious failures.
     * </p>
     *
     * @param image The captured JPEG/HEIC image
     * @param expectedSize Expected capture JEPG/HEIC size
     * @param format JPEG/HEIC image format
     */
    public static void basicValidateBlobImage(Image image, Size expectedSize, int format) {
        Size imageSz = new Size(image.getWidth(), image.getHeight());
        assertTrue(
                String.format("Image size doesn't match (expected %s, actual %s) ",
                        expectedSize.toString(), imageSz.toString()), expectedSize.equals(imageSz));
        assertEquals("Image format should be " + ((format == ImageFormat.HEIC) ? "HEIC" : "JPEG"),
                format, image.getFormat());
        assertNotNull("Image plane shouldn't be null", image.getPlanes());
        assertEquals("Image plane number should be 1", 1, image.getPlanes().length);

        // Jpeg/Heic decoding validate was done in ImageReaderTest,
        // no need to duplicate the test here.
    }

    /**
     * Verify the EXIF and JPEG related keys in a capture result are expected.
     * - Capture request get values are same as were set.
     * - capture result's exif data is the same as was set by
     *   the capture request.
     * - new tags in the result set by the camera service are
     *   present and semantically correct.
     *
     * @param image The output JPEG/HEIC image to verify.
     * @param captureResult The capture result to verify.
     * @param expectedSize The expected JPEG/HEIC size.
     * @param expectedThumbnailSize The expected thumbnail size.
     * @param expectedExifData The expected EXIF data
     * @param staticInfo The static metadata for the camera device.
     * @param blobFilename The filename to dump the jpeg/heic to.
     * @param collector The camera error collector to collect errors.
     * @param format JPEG/HEIC format
     */
    public static void verifyJpegKeys(Image image, CaptureResult captureResult, Size expectedSize,
            Size expectedThumbnailSize, ExifTestData expectedExifData, StaticMetadata staticInfo,
            CameraErrorCollector collector, String debugFileNameBase, int format) throws Exception {

        basicValidateBlobImage(image, expectedSize, format);

        byte[] blobBuffer = getDataFromImage(image);
        // Have to dump into a file to be able to use ExifInterface
        String filePostfix = (format == ImageFormat.HEIC ? ".heic" : ".jpeg");
        String blobFilename = debugFileNameBase + "/verifyJpegKeys" + filePostfix;
        dumpFile(blobFilename, blobBuffer);
        ExifInterface exif = new ExifInterface(blobFilename);

        if (expectedThumbnailSize.equals(new Size(0,0))) {
            collector.expectTrue("Jpeg shouldn't have thumbnail when thumbnail size is (0, 0)",
                    !exif.hasThumbnail());
        } else {
            collector.expectTrue("Jpeg must have thumbnail for thumbnail size " +
                    expectedThumbnailSize, exif.hasThumbnail());
        }

        // Validate capture result vs. request
        Size resultThumbnailSize = captureResult.get(CaptureResult.JPEG_THUMBNAIL_SIZE);
        int orientationTested = expectedExifData.jpegOrientation;
        // Legacy shim always doesn't rotate thumbnail size
        if ((orientationTested == 90 || orientationTested == 270) &&
                staticInfo.isHardwareLevelAtLeastLimited()) {
            int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    /*defaultValue*/-1);
            if (exifOrientation == ExifInterface.ORIENTATION_UNDEFINED) {
                // Device physically rotated image+thumbnail data
                // Expect thumbnail size to be also rotated
                resultThumbnailSize = new Size(resultThumbnailSize.getHeight(),
                        resultThumbnailSize.getWidth());
            }
        }

        collector.expectEquals("JPEG thumbnail size result and request should match",
                expectedThumbnailSize, resultThumbnailSize);
        if (collector.expectKeyValueNotNull(captureResult, CaptureResult.JPEG_GPS_LOCATION) !=
                null) {
            collector.expectTrue("GPS location result and request should match.",
                    areGpsFieldsEqual(expectedExifData.gpsLocation,
                    captureResult.get(CaptureResult.JPEG_GPS_LOCATION)));
        }
        collector.expectEquals("JPEG orientation result and request should match",
                expectedExifData.jpegOrientation,
                captureResult.get(CaptureResult.JPEG_ORIENTATION));
        collector.expectEquals("JPEG quality result and request should match",
                expectedExifData.jpegQuality, captureResult.get(CaptureResult.JPEG_QUALITY));
        collector.expectEquals("JPEG thumbnail quality result and request should match",
                expectedExifData.thumbnailQuality,
                captureResult.get(CaptureResult.JPEG_THUMBNAIL_QUALITY));

        // Validate other exif tags for all non-legacy devices
        if (!staticInfo.isHardwareLevelLegacy()) {
            verifyJpegExifExtraTags(exif, expectedSize, captureResult, staticInfo, collector,
                    expectedExifData);
        }
    }

    /**
     * Get the degree of an EXIF orientation.
     */
    private static int getExifOrientationInDegree(int exifOrientation,
            CameraErrorCollector collector) {
        switch (exifOrientation) {
            case ExifInterface.ORIENTATION_NORMAL:
                return 0;
            case ExifInterface.ORIENTATION_ROTATE_90:
                return 90;
            case ExifInterface.ORIENTATION_ROTATE_180:
                return 180;
            case ExifInterface.ORIENTATION_ROTATE_270:
                return 270;
            default:
                collector.addMessage("It is impossible to get non 0, 90, 180, 270 degress exif" +
                        "info based on the request orientation range");
                return 0;
        }
    }

    /**
     * Validate and return the focal length.
     *
     * @param result Capture result to get the focal length
     * @return Focal length from capture result or -1 if focal length is not available.
     */
    private static float validateFocalLength(CaptureResult result, StaticMetadata staticInfo,
            CameraErrorCollector collector) {
        float[] focalLengths = staticInfo.getAvailableFocalLengthsChecked();
        Float resultFocalLength = result.get(CaptureResult.LENS_FOCAL_LENGTH);
        if (collector.expectTrue("Focal length is invalid",
                resultFocalLength != null && resultFocalLength > 0)) {
            List<Float> focalLengthList =
                    Arrays.asList(CameraTestUtils.toObject(focalLengths));
            collector.expectTrue("Focal length should be one of the available focal length",
                    focalLengthList.contains(resultFocalLength));
            return resultFocalLength;
        }
        return -1;
    }

    /**
     * Validate and return the aperture.
     *
     * @param result Capture result to get the aperture
     * @return Aperture from capture result or -1 if aperture is not available.
     */
    private static float validateAperture(CaptureResult result, StaticMetadata staticInfo,
            CameraErrorCollector collector) {
        float[] apertures = staticInfo.getAvailableAperturesChecked();
        Float resultAperture = result.get(CaptureResult.LENS_APERTURE);
        if (collector.expectTrue("Capture result aperture is invalid",
                resultAperture != null && resultAperture > 0)) {
            List<Float> apertureList =
                    Arrays.asList(CameraTestUtils.toObject(apertures));
            collector.expectTrue("Aperture should be one of the available apertures",
                    apertureList.contains(resultAperture));
            return resultAperture;
        }
        return -1;
    }

    /**
     * Return the closest value in an array of floats.
     */
    private static float getClosestValueInArray(float[] values, float target) {
        int minIdx = 0;
        float minDistance = Math.abs(values[0] - target);
        for(int i = 0; i < values.length; i++) {
            float distance = Math.abs(values[i] - target);
            if (minDistance > distance) {
                minDistance = distance;
                minIdx = i;
            }
        }

        return values[minIdx];
    }

    /**
     * Return if two Location's GPS field are the same.
     */
    private static boolean areGpsFieldsEqual(Location a, Location b) {
        if (a == null || b == null) {
            return false;
        }

        return a.getTime() == b.getTime() && a.getLatitude() == b.getLatitude() &&
                a.getLongitude() == b.getLongitude() && a.getAltitude() == b.getAltitude() &&
                a.getProvider() == b.getProvider();
    }

    /**
     * Verify extra tags in JPEG EXIF
     */
    private static void verifyJpegExifExtraTags(ExifInterface exif, Size jpegSize,
            CaptureResult result, StaticMetadata staticInfo, CameraErrorCollector collector,
            ExifTestData expectedExifData)
            throws ParseException {
        /**
         * TAG_IMAGE_WIDTH and TAG_IMAGE_LENGTH and TAG_ORIENTATION.
         * Orientation and exif width/height need to be tested carefully, two cases:
         *
         * 1. Device rotate the image buffer physically, then exif width/height may not match
         * the requested still capture size, we need swap them to check.
         *
         * 2. Device use the exif tag to record the image orientation, it doesn't rotate
         * the jpeg image buffer itself. In this case, the exif width/height should always match
         * the requested still capture size, and the exif orientation should always match the
         * requested orientation.
         *
         */
        int exifWidth = exif.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, /*defaultValue*/0);
        int exifHeight = exif.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, /*defaultValue*/0);
        Size exifSize = new Size(exifWidth, exifHeight);
        // Orientation could be missing, which is ok, default to 0.
        int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                /*defaultValue*/-1);
        // Get requested orientation from result, because they should be same.
        if (collector.expectKeyValueNotNull(result, CaptureResult.JPEG_ORIENTATION) != null) {
            int requestedOrientation = result.get(CaptureResult.JPEG_ORIENTATION);
            final int ORIENTATION_MIN = ExifInterface.ORIENTATION_UNDEFINED;
            final int ORIENTATION_MAX = ExifInterface.ORIENTATION_ROTATE_270;
            boolean orientationValid = collector.expectTrue(String.format(
                    "Exif orientation must be in range of [%d, %d]",
                    ORIENTATION_MIN, ORIENTATION_MAX),
                    exifOrientation >= ORIENTATION_MIN && exifOrientation <= ORIENTATION_MAX);
            if (orientationValid) {
                /**
                 * Device captured image doesn't respect the requested orientation,
                 * which means it rotates the image buffer physically. Then we
                 * should swap the exif width/height accordingly to compare.
                 */
                boolean deviceRotatedImage = exifOrientation == ExifInterface.ORIENTATION_UNDEFINED;

                if (deviceRotatedImage) {
                    // Case 1.
                    boolean needSwap = (requestedOrientation % 180 == 90);
                    if (needSwap) {
                        exifSize = new Size(exifHeight, exifWidth);
                    }
                } else {
                    // Case 2.
                    collector.expectEquals("Exif orientaiton should match requested orientation",
                            requestedOrientation, getExifOrientationInDegree(exifOrientation,
                            collector));
                }
            }
        }

        /**
         * Ideally, need check exifSize == jpegSize == actual buffer size. But
         * jpegSize == jpeg decode bounds size(from jpeg jpeg frame
         * header, not exif) was validated in ImageReaderTest, no need to
         * validate again here.
         */
        collector.expectEquals("Exif size should match jpeg capture size", jpegSize, exifSize);

        // TAG_DATETIME, it should be local time
        long currentTimeInMs = System.currentTimeMillis();
        long currentTimeInSecond = currentTimeInMs / 1000;
        Date date = new Date(currentTimeInMs);
        String localDatetime = new SimpleDateFormat("yyyy:MM:dd HH:").format(date);
        String dateTime = exif.getAttribute(ExifInterface.TAG_DATETIME);
        if (collector.expectTrue("Exif TAG_DATETIME shouldn't be null", dateTime != null)) {
            collector.expectTrue("Exif TAG_DATETIME is wrong",
                    dateTime.length() == EXIF_DATETIME_LENGTH);
            long exifTimeInSecond =
                    new SimpleDateFormat("yyyy:MM:dd HH:mm:ss").parse(dateTime).getTime() / 1000;
            long delta = currentTimeInSecond - exifTimeInSecond;
            collector.expectTrue("Capture time deviates too much from the current time",
                    Math.abs(delta) < EXIF_DATETIME_ERROR_MARGIN_SEC);
            // It should be local time.
            collector.expectTrue("Exif date time should be local time",
                    dateTime.startsWith(localDatetime));
        }

        boolean isExternalCamera = staticInfo.isExternalCamera();
        if (!isExternalCamera) {
            // TAG_FOCAL_LENGTH.
            float[] focalLengths = staticInfo.getAvailableFocalLengthsChecked();
            float exifFocalLength = (float)exif.getAttributeDouble(
                        ExifInterface.TAG_FOCAL_LENGTH, -1);
            collector.expectEquals("Focal length should match",
                    getClosestValueInArray(focalLengths, exifFocalLength),
                    exifFocalLength, EXIF_FOCAL_LENGTH_ERROR_MARGIN);
            // More checks for focal length.
            collector.expectEquals("Exif focal length should match capture result",
                    validateFocalLength(result, staticInfo, collector),
                    exifFocalLength, EXIF_FOCAL_LENGTH_ERROR_MARGIN);

            // TAG_EXPOSURE_TIME
            // ExifInterface API gives exposure time value in the form of float instead of rational
            String exposureTime = exif.getAttribute(ExifInterface.TAG_EXPOSURE_TIME);
            collector.expectNotNull("Exif TAG_EXPOSURE_TIME shouldn't be null", exposureTime);
            if (staticInfo.areKeysAvailable(CaptureResult.SENSOR_EXPOSURE_TIME)) {
                if (exposureTime != null) {
                    double exposureTimeValue = Double.parseDouble(exposureTime);
                    long expTimeResult = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
                    double expected = expTimeResult / 1e9;
                    double tolerance = expected * EXIF_EXPOSURE_TIME_ERROR_MARGIN_RATIO;
                    tolerance = Math.max(tolerance, EXIF_EXPOSURE_TIME_MIN_ERROR_MARGIN_SEC);
                    collector.expectEquals("Exif exposure time doesn't match", expected,
                            exposureTimeValue, tolerance);
                }
            }

            // TAG_APERTURE
            // ExifInterface API gives aperture value in the form of float instead of rational
            String exifAperture = exif.getAttribute(ExifInterface.TAG_APERTURE);
            collector.expectNotNull("Exif TAG_APERTURE shouldn't be null", exifAperture);
            if (staticInfo.areKeysAvailable(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES)) {
                float[] apertures = staticInfo.getAvailableAperturesChecked();
                if (exifAperture != null) {
                    float apertureValue = Float.parseFloat(exifAperture);
                    collector.expectEquals("Aperture value should match",
                            getClosestValueInArray(apertures, apertureValue),
                            apertureValue, EXIF_APERTURE_ERROR_MARGIN);
                    // More checks for aperture.
                    collector.expectEquals("Exif aperture length should match capture result",
                            validateAperture(result, staticInfo, collector),
                            apertureValue, EXIF_APERTURE_ERROR_MARGIN);
                }
            }

            // TAG_MAKE
            String make = exif.getAttribute(ExifInterface.TAG_MAKE);
            collector.expectEquals("Exif TAG_MAKE is incorrect", Build.MANUFACTURER, make);

            // TAG_MODEL
            String model = exif.getAttribute(ExifInterface.TAG_MODEL);
            collector.expectEquals("Exif TAG_MODEL is incorrect", Build.MODEL, model);


            // TAG_ISO
            int iso = exif.getAttributeInt(ExifInterface.TAG_ISO, /*defaultValue*/-1);
            if (staticInfo.areKeysAvailable(CaptureResult.SENSOR_SENSITIVITY) ||
                    staticInfo.areKeysAvailable(CaptureResult.CONTROL_POST_RAW_SENSITIVITY_BOOST)) {
                int expectedIso = 100;
                if (staticInfo.areKeysAvailable(CaptureResult.SENSOR_SENSITIVITY)) {
                    expectedIso = result.get(CaptureResult.SENSOR_SENSITIVITY);
                }
                if (staticInfo.areKeysAvailable(CaptureResult.CONTROL_POST_RAW_SENSITIVITY_BOOST)) {
                    expectedIso = expectedIso *
                            result.get(CaptureResult.CONTROL_POST_RAW_SENSITIVITY_BOOST);
                } else {
                    expectedIso *= 100;
                }
                collector.expectInRange("Exif TAG_ISO is incorrect", iso,
                        expectedIso/100,((expectedIso+50)/100)+MAX_ISO_MISMATCH);
            }
        } else {
            // External camera specific checks
            // TAG_MAKE
            String make = exif.getAttribute(ExifInterface.TAG_MAKE);
            collector.expectNotNull("Exif TAG_MAKE is null", make);

            // TAG_MODEL
            String model = exif.getAttribute(ExifInterface.TAG_MODEL);
            collector.expectNotNull("Exif TAG_MODEL is nuill", model);
        }


        /**
         * TAG_FLASH. TODO: For full devices, can check a lot more info
         * (http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html#Flash)
         */
        String flash = exif.getAttribute(ExifInterface.TAG_FLASH);
        collector.expectNotNull("Exif TAG_FLASH shouldn't be null", flash);

        /**
         * TAG_WHITE_BALANCE. TODO: For full devices, with the DNG tags, we
         * should be able to cross-check android.sensor.referenceIlluminant.
         */
        String whiteBalance = exif.getAttribute(ExifInterface.TAG_WHITE_BALANCE);
        collector.expectNotNull("Exif TAG_WHITE_BALANCE shouldn't be null", whiteBalance);

        // TAG_DATETIME_DIGITIZED (a.k.a Create time for digital cameras).
        String digitizedTime = exif.getAttribute(ExifInterface.TAG_DATETIME_DIGITIZED);
        collector.expectNotNull("Exif TAG_DATETIME_DIGITIZED shouldn't be null", digitizedTime);
        if (digitizedTime != null) {
            String expectedDateTime = exif.getAttribute(ExifInterface.TAG_DATETIME);
            collector.expectNotNull("Exif TAG_DATETIME shouldn't be null", expectedDateTime);
            if (expectedDateTime != null) {
                collector.expectEquals("dataTime should match digitizedTime",
                        expectedDateTime, digitizedTime);
            }
        }

        /**
         * TAG_SUBSEC_TIME. Since the sub second tag strings are truncated to at
         * most 9 digits in ExifInterface implementation, use getAttributeInt to
         * sanitize it. When the default value -1 is returned, it means that
         * this exif tag either doesn't exist or is a non-numerical invalid
         * string. Same rule applies to the rest of sub second tags.
         */
        int subSecTime = exif.getAttributeInt(ExifInterface.TAG_SUBSEC_TIME, /*defaultValue*/-1);
        collector.expectTrue("Exif TAG_SUBSEC_TIME value is null or invalid!", subSecTime >= 0);

        // TAG_SUBSEC_TIME_ORIG
        int subSecTimeOrig = exif.getAttributeInt(ExifInterface.TAG_SUBSEC_TIME_ORIG,
                /*defaultValue*/-1);
        collector.expectTrue("Exif TAG_SUBSEC_TIME_ORIG value is null or invalid!",
                subSecTimeOrig >= 0);

        // TAG_SUBSEC_TIME_DIG
        int subSecTimeDig = exif.getAttributeInt(ExifInterface.TAG_SUBSEC_TIME_DIG,
                /*defaultValue*/-1);
        collector.expectTrue(
                "Exif TAG_SUBSEC_TIME_DIG value is null or invalid!", subSecTimeDig >= 0);

        /**
         * TAG_GPS_DATESTAMP & TAG_GPS_TIMESTAMP.
         * The GPS timestamp information should be in seconds UTC time.
         */
        String gpsDatestamp = exif.getAttribute(ExifInterface.TAG_GPS_DATESTAMP);
        collector.expectNotNull("Exif TAG_GPS_DATESTAMP shouldn't be null", gpsDatestamp);
        String gpsTimestamp = exif.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP);
        collector.expectNotNull("Exif TAG_GPS_TIMESTAMP shouldn't be null", gpsTimestamp);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy:MM:dd hh:mm:ss z");
        String gpsExifTimeString = gpsDatestamp + " " + gpsTimestamp + " UTC";
        Date gpsDateTime = dateFormat.parse(gpsExifTimeString);
        Date expected = new Date(expectedExifData.gpsLocation.getTime());
        collector.expectEquals("Jpeg EXIF GPS time should match", expected, gpsDateTime);
    }


    /**
     * Immutable class wrapping the exif test data.
     */
    public static class ExifTestData {
        public final Location gpsLocation;
        public final int jpegOrientation;
        public final byte jpegQuality;
        public final byte thumbnailQuality;

        public ExifTestData(Location location, int orientation,
                byte jpgQuality, byte thumbQuality) {
            gpsLocation = location;
            jpegOrientation = orientation;
            jpegQuality = jpgQuality;
            thumbnailQuality = thumbQuality;
        }
    }

    public static Size getPreviewSizeBound(WindowManager windowManager, Size bound) {
        Display display = windowManager.getDefaultDisplay();

        int width = display.getWidth();
        int height = display.getHeight();

        if (height > width) {
            height = width;
            width = display.getHeight();
        }

        if (bound.getWidth() <= width &&
            bound.getHeight() <= height)
            return bound;
        else
            return new Size(width, height);
    }

    /**
     * Check if a particular stream configuration is supported by configuring it
     * to the device.
     */
    public static boolean isStreamConfigurationSupported(CameraDevice camera,
            List<Surface> outputSurfaces,
            CameraCaptureSession.StateCallback listener, Handler handler) {
        try {
            configureCameraSession(camera, outputSurfaces, listener, handler);
            return true;
        } catch (Exception e) {
            Log.i(TAG, "This stream configuration is not supported due to " + e.getMessage());
            return false;
        }
    }

    public final static class SessionConfigSupport {
        public final boolean error;
        public final boolean callSupported;
        public final boolean configSupported;

        public SessionConfigSupport(boolean error,
                boolean callSupported, boolean configSupported) {
            this.error = error;
            this.callSupported = callSupported;
            this.configSupported = configSupported;
        }
    }

    /**
     * Query whether a particular stream combination is supported.
     */
    public static void checkSessionConfigurationWithSurfaces(CameraDevice camera,
            Handler handler, List<Surface> outputSurfaces, InputConfiguration inputConfig,
            int operatingMode, boolean defaultSupport, String msg) {
        List<OutputConfiguration> outConfigurations = new ArrayList<>(outputSurfaces.size());
        for (Surface surface : outputSurfaces) {
            outConfigurations.add(new OutputConfiguration(surface));
        }

        checkSessionConfigurationSupported(camera, handler, outConfigurations,
                inputConfig, operatingMode, defaultSupport, msg);
    }

    public static void checkSessionConfigurationSupported(CameraDevice camera,
            Handler handler, List<OutputConfiguration> outputConfigs,
            InputConfiguration inputConfig, int operatingMode, boolean defaultSupport,
            String msg) {
        SessionConfigSupport sessionConfigSupported =
                isSessionConfigSupported(camera, handler, outputConfigs, inputConfig,
                operatingMode, defaultSupport);

        assertTrue(msg, !sessionConfigSupported.error && sessionConfigSupported.configSupported);
    }

    /**
     * Query whether a particular stream combination is supported.
     */
    public static SessionConfigSupport isSessionConfigSupported(CameraDevice camera,
            Handler handler, List<OutputConfiguration> outputConfigs,
            InputConfiguration inputConfig, int operatingMode, boolean defaultSupport) {
        boolean ret;
        BlockingSessionCallback sessionListener = new BlockingSessionCallback();

        SessionConfiguration sessionConfig = new SessionConfiguration(operatingMode, outputConfigs,
                new HandlerExecutor(handler), sessionListener);
        if (inputConfig != null) {
            sessionConfig.setInputConfiguration(inputConfig);
        }

        try {
            ret = camera.isSessionConfigurationSupported(sessionConfig);
        } catch (UnsupportedOperationException e) {
            // Camera doesn't support session configuration query
            return new SessionConfigSupport(false/*error*/,
                    false/*callSupported*/, defaultSupport/*configSupported*/);
        } catch (IllegalArgumentException e) {
            return new SessionConfigSupport(true/*error*/,
                    false/*callSupported*/, false/*configSupported*/);
        } catch (android.hardware.camera2.CameraAccessException e) {
            return new SessionConfigSupport(true/*error*/,
                    false/*callSupported*/, false/*configSupported*/);
        }

        return new SessionConfigSupport(false/*error*/,
                true/*callSupported*/, ret/*configSupported*/);
    }

    /**
     * Wait for numResultWait frames
     *
     * @param resultListener The capture listener to get capture result back.
     * @param numResultsWait Number of frame to wait
     * @param timeout Wait timeout in ms.
     *
     * @return the last result, or {@code null} if there was none
     */
    public static CaptureResult waitForNumResults(SimpleCaptureCallback resultListener,
            int numResultsWait, int timeout) {
        if (numResultsWait < 0 || resultListener == null) {
            throw new IllegalArgumentException(
                    "Input must be positive number and listener must be non-null");
        }

        CaptureResult result = null;
        for (int i = 0; i < numResultsWait; i++) {
            result = resultListener.getCaptureResult(timeout);
        }

        return result;
    }

    /**
     * Wait for any expected result key values available in a certain number of results.
     *
     * <p>
     * Check the result immediately if numFramesWait is 0.
     * </p>
     *
     * @param listener The capture listener to get capture result.
     * @param resultKey The capture result key associated with the result value.
     * @param expectedValues The list of result value need to be waited for,
     * return immediately if the list is empty.
     * @param numResultsWait Number of frame to wait before times out.
     * @param timeout result wait time out in ms.
     * @throws TimeoutRuntimeException If more than numResultsWait results are.
     * seen before the result matching myRequest arrives, or each individual wait
     * for result times out after 'timeout' ms.
     */
    public static <T> void waitForAnyResultValue(SimpleCaptureCallback listener,
            CaptureResult.Key<T> resultKey, List<T> expectedValues, int numResultsWait,
            int timeout) {
        if (numResultsWait < 0 || listener == null || expectedValues == null) {
            throw new IllegalArgumentException(
                    "Input must be non-negative number and listener/expectedValues "
                    + "must be non-null");
        }

        int i = 0;
        CaptureResult result;
        do {
            result = listener.getCaptureResult(timeout);
            T value = result.get(resultKey);
            for ( T expectedValue : expectedValues) {
                if (VERBOSE) {
                    Log.v(TAG, "Current result value for key " + resultKey.getName() + " is: "
                            + value.toString());
                }
                if (value.equals(expectedValue)) {
                    return;
                }
            }
        } while (i++ < numResultsWait);

        throw new TimeoutRuntimeException(
                "Unable to get the expected result value " + expectedValues + " for key " +
                        resultKey.getName() + " after waiting for " + numResultsWait + " results");
    }

    /**
     * Wait for expected result key value available in a certain number of results.
     *
     * <p>
     * Check the result immediately if numFramesWait is 0.
     * </p>
     *
     * @param listener The capture listener to get capture result
     * @param resultKey The capture result key associated with the result value
     * @param expectedValue The result value need to be waited for
     * @param numResultsWait Number of frame to wait before times out
     * @param timeout Wait time out.
     * @throws TimeoutRuntimeException If more than numResultsWait results are
     * seen before the result matching myRequest arrives, or each individual wait
     * for result times out after 'timeout' ms.
     */
    public static <T> void waitForResultValue(SimpleCaptureCallback listener,
            CaptureResult.Key<T> resultKey, T expectedValue, int numResultsWait, int timeout) {
        List<T> expectedValues = new ArrayList<T>();
        expectedValues.add(expectedValue);
        waitForAnyResultValue(listener, resultKey, expectedValues, numResultsWait, timeout);
    }

    /**
     * Wait for AE to be stabilized before capture: CONVERGED or FLASH_REQUIRED.
     *
     * <p>Waits for {@code android.sync.maxLatency} number of results first, to make sure
     * that the result is synchronized (or {@code numResultWaitForUnknownLatency} if the latency
     * is unknown.</p>
     *
     * <p>This is a no-op for {@code LEGACY} devices since they don't report
     * the {@code aeState} result.</p>
     *
     * @param resultListener The capture listener to get capture result back.
     * @param numResultWaitForUnknownLatency Number of frame to wait if camera device latency is
     *                                       unknown.
     * @param staticInfo corresponding camera device static metadata.
     * @param settingsTimeout wait timeout for settings application in ms.
     * @param resultTimeout wait timeout for result in ms.
     * @param numResultsWait Number of frame to wait before times out.
     */
    public static void waitForAeStable(SimpleCaptureCallback resultListener,
            int numResultWaitForUnknownLatency, StaticMetadata staticInfo,
            int settingsTimeout, int numResultWait) {
        waitForSettingsApplied(resultListener, numResultWaitForUnknownLatency, staticInfo,
                settingsTimeout);

        if (!staticInfo.isHardwareLevelAtLeastLimited()) {
            // No-op for metadata
            return;
        }
        List<Integer> expectedAeStates = new ArrayList<Integer>();
        expectedAeStates.add(new Integer(CaptureResult.CONTROL_AE_STATE_CONVERGED));
        expectedAeStates.add(new Integer(CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED));
        waitForAnyResultValue(resultListener, CaptureResult.CONTROL_AE_STATE, expectedAeStates,
                numResultWait, settingsTimeout);
    }

    /**
     * Wait for enough results for settings to be applied
     *
     * @param resultListener The capture listener to get capture result back.
     * @param numResultWaitForUnknownLatency Number of frame to wait if camera device latency is
     *                                       unknown.
     * @param staticInfo corresponding camera device static metadata.
     * @param timeout wait timeout in ms.
     */
    public static void waitForSettingsApplied(SimpleCaptureCallback resultListener,
            int numResultWaitForUnknownLatency, StaticMetadata staticInfo, int timeout) {
        int maxLatency = staticInfo.getSyncMaxLatency();
        if (maxLatency == CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN) {
            maxLatency = numResultWaitForUnknownLatency;
        }
        // Wait for settings to take effect
        waitForNumResults(resultListener, maxLatency, timeout);
    }

    public static Range<Integer> getSuitableFpsRangeForDuration(String cameraId,
            long frameDuration, StaticMetadata staticInfo) {
        // Add 0.05 here so Fps like 29.99 evaluated to 30
        int minBurstFps = (int) Math.floor(1e9 / frameDuration + 0.05f);
        boolean foundConstantMaxYUVRange = false;
        boolean foundYUVStreamingRange = false;
        boolean isExternalCamera = staticInfo.isExternalCamera();
        boolean isNIR = staticInfo.isNIRColorFilter();

        // Find suitable target FPS range - as high as possible that covers the max YUV rate
        // Also verify that there's a good preview rate as well
        List<Range<Integer> > fpsRanges = Arrays.asList(
                staticInfo.getAeAvailableTargetFpsRangesChecked());
        Range<Integer> targetRange = null;
        for (Range<Integer> fpsRange : fpsRanges) {
            if (fpsRange.getLower() == minBurstFps && fpsRange.getUpper() == minBurstFps) {
                foundConstantMaxYUVRange = true;
                targetRange = fpsRange;
            } else if (isExternalCamera && fpsRange.getUpper() == minBurstFps) {
                targetRange = fpsRange;
            }
            if (fpsRange.getLower() <= 15 && fpsRange.getUpper() == minBurstFps) {
                foundYUVStreamingRange = true;
            }

        }

        if (!isExternalCamera) {
            assertTrue(String.format("Cam %s: Target FPS range of (%d, %d) must be supported",
                    cameraId, minBurstFps, minBurstFps), foundConstantMaxYUVRange);
        }

        if (!isNIR) {
            assertTrue(String.format(
                    "Cam %s: Target FPS range of (x, %d) where x <= 15 must be supported",
                    cameraId, minBurstFps), foundYUVStreamingRange);
        }
        return targetRange;
    }
    /**
     * Get the candidate supported zoom ratios for testing
     *
     * <p>
     * This function returns the bounary values of supported zoom ratio range in addition to 1.0x
     * zoom ratio.
     * </p>
     */
    public static List<Float> getCandidateZoomRatios(StaticMetadata staticInfo) {
        List<Float> zoomRatios = new ArrayList<Float>();
        Range<Float> zoomRatioRange = staticInfo.getZoomRatioRangeChecked();
        zoomRatios.add(zoomRatioRange.getLower());
        if (zoomRatioRange.contains(1.0f) &&
                1.0f - zoomRatioRange.getLower() > ZOOM_RATIO_THRESHOLD &&
                zoomRatioRange.getUpper() - 1.0f > ZOOM_RATIO_THRESHOLD) {
            zoomRatios.add(1.0f);
        }
        zoomRatios.add(zoomRatioRange.getUpper());

        return zoomRatios;
    }

    private static final int PERFORMANCE_CLASS_R = Build.VERSION_CODES.R;
    private static final int PERFORMANCE_CLASS_S = Build.VERSION_CODES.R + 1;

    /**
     * Check whether this mobile device is R performance class as defined in CDD
     */
    public static boolean isRPerfClass() {
        return Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_R;
    }

    /**
     * Check whether this mobile device is S performance class as defined in CDD
     */
    public static boolean isSPerfClass() {
        return Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_S;
    }

    /**
     * Check whether a camera Id is a primary rear facing camera
     */
    public static boolean isPrimaryRearFacingCamera(CameraManager manager, String cameraId)
            throws Exception {
        return isPrimaryCamera(manager, cameraId, CameraCharacteristics.LENS_FACING_BACK);
    }

    /**
     * Check whether a camera Id is a primary front facing camera
     */
    public static boolean isPrimaryFrontFacingCamera(CameraManager manager, String cameraId)
            throws Exception {
        return isPrimaryCamera(manager, cameraId, CameraCharacteristics.LENS_FACING_FRONT);
    }

    private static boolean isPrimaryCamera(CameraManager manager, String cameraId,
            Integer lensFacing) throws Exception {
        CameraCharacteristics characteristics;
        Integer facing;

        String [] ids = manager.getCameraIdList();
        for (String id : ids) {
            characteristics = manager.getCameraCharacteristics(id);
            facing = characteristics.get(CameraCharacteristics.LENS_FACING);
            if (lensFacing.equals(facing)) {
                if (cameraId.equals(id)) {
                    return true;
                } else {
                    return false;
                }
            }
        }
        return false;
    }
}
