/*
 * Copyright 2020 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 static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
import com.android.compatibility.common.util.Stat;
import com.android.ex.camera2.blocking.BlockingSessionCallback;
import com.android.ex.camera2.blocking.BlockingExtensionSessionCallback;
import com.android.ex.camera2.blocking.BlockingStateCallback;
import com.android.ex.camera2.exceptions.TimeoutRuntimeException;

import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.HardwareBuffer;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraExtensionCharacteristics;
import android.hardware.camera2.CameraExtensionSession;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.cts.helpers.CameraErrorCollector;
import android.hardware.camera2.cts.helpers.StaticMetadata;
import android.hardware.camera2.cts.testcases.Camera2AndroidTestRule;
import android.hardware.camera2.params.ExtensionSessionConfiguration;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.SessionConfiguration;
import android.media.ExifInterface;
import android.media.Image;
import android.media.ImageReader;
import android.os.SystemClock;
import android.util.Range;
import android.util.Size;

import static android.hardware.camera2.cts.CameraTestUtils.*;
import static android.hardware.cts.helpers.CameraUtils.*;

import android.util.Log;
import android.view.Surface;
import android.view.TextureView;

import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@RunWith(Parameterized.class)
public class CameraExtensionSessionTest extends Camera2ParameterizedTestCase {
    private static final String TAG = "CameraExtensionSessionTest";
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
    private static final long WAIT_FOR_COMMAND_TO_COMPLETE_MS = 5000;
    private static final long REPEATING_REQUEST_TIMEOUT_MS = 5000;
    public static final int MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS = 10000;

    private SurfaceTexture mSurfaceTexture = null;
    private Camera2AndroidTestRule mTestRule = null;
    private CameraErrorCollector mCollector =  null;

    private DeviceReportLog mReportLog;

    @Override
    public void setUp() throws Exception {
        super.setUp();
        mTestRule = new Camera2AndroidTestRule(mContext);
        mTestRule.before();
        mCollector = new CameraErrorCollector();
    }

    @Override
    public void tearDown() throws Exception {
        if (mTestRule != null) {
            mTestRule.after();
        }
        if (mSurfaceTexture != null) {
            mSurfaceTexture.release();
            mSurfaceTexture = null;
        }
        if (mCollector != null) {
            try {
                mCollector.verify();
            } catch (Throwable e) {
                throw new Exception(e.getMessage());
            }
        }
        super.tearDown();
    }

    @Rule
    public ActivityTestRule<CameraExtensionTestActivity> mActivityRule =
            new ActivityTestRule<>(CameraExtensionTestActivity.class);

    private void updatePreviewSurfaceTexture() {
        if (mSurfaceTexture != null) {
            return;
        }

        TextureView textureView = mActivityRule.getActivity().getTextureView();
        mSurfaceTexture = getAvailableSurfaceTexture(WAIT_FOR_COMMAND_TO_COMPLETE_MS, textureView);
        assertNotNull("Failed to acquire valid preview surface texture!", mSurfaceTexture);
    }

    // Verify that camera extension sessions can be created and closed as expected.
    @Test
    public void testBasicExtensionLifecycle() throws Exception {
        for (String id : mCameraIdsUnderTest) {
            StaticMetadata staticMeta =
                    new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
            if (!staticMeta.isColorOutputSupported()) {
                continue;
            }
            updatePreviewSurfaceTexture();
            CameraExtensionCharacteristics extensionChars =
                    mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
            List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
            for (Integer extension : supportedExtensions) {
                List<Size> extensionSizes = extensionChars.getExtensionSupportedSizes(extension,
                        mSurfaceTexture.getClass());
                Size maxSize = CameraTestUtils.getMaxSize(extensionSizes.toArray(new Size[0]));
                mSurfaceTexture.setDefaultBufferSize(maxSize.getWidth(), maxSize.getHeight());
                OutputConfiguration outputConfig = new OutputConfiguration(
                        OutputConfiguration.SURFACE_GROUP_ID_NONE,
                        new Surface(mSurfaceTexture));
                List<OutputConfiguration> outputConfigs = new ArrayList<>();
                outputConfigs.add(outputConfig);

                BlockingExtensionSessionCallback sessionListener =
                        new BlockingExtensionSessionCallback(
                                mock(CameraExtensionSession.StateCallback.class));
                ExtensionSessionConfiguration configuration =
                        new ExtensionSessionConfiguration(extension, outputConfigs,
                                new HandlerExecutor(mTestRule.getHandler()), sessionListener);

                try {
                    mTestRule.openDevice(id);
                    CameraDevice camera = mTestRule.getCamera();
                    camera.createExtensionSession(configuration);
                    CameraExtensionSession extensionSession = sessionListener.waitAndGetSession(
                            SESSION_CONFIGURE_TIMEOUT_MS);

                    extensionSession.close();
                    sessionListener.getStateWaiter().waitForState(
                            BlockingExtensionSessionCallback.SESSION_CLOSED,
                            SESSION_CLOSE_TIMEOUT_MS);
                } finally {
                    mTestRule.closeDevice(id);
                }
            }
        }
    }

    // Verify that regular camera sessions close as expected after creating a camera extension
    // session.
    @Test
    public void testCloseCaptureSession() throws Exception {
        for (String id : mCameraIdsUnderTest) {
            StaticMetadata staticMeta =
                    new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
            if (!staticMeta.isColorOutputSupported()) {
                continue;
            }
            updatePreviewSurfaceTexture();
            CameraExtensionCharacteristics extensionChars =
                    mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
            List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
            for (Integer extension : supportedExtensions) {
                List<Size> extensionSizes = extensionChars.getExtensionSupportedSizes(extension,
                        mSurfaceTexture.getClass());
                Size maxSize = CameraTestUtils.getMaxSize(extensionSizes.toArray(new Size[0]));
                mSurfaceTexture.setDefaultBufferSize(maxSize.getWidth(), maxSize.getHeight());
                Surface repeatingSurface = new Surface(mSurfaceTexture);
                OutputConfiguration textureOutput = new OutputConfiguration(
                        OutputConfiguration.SURFACE_GROUP_ID_NONE, repeatingSurface);
                List<OutputConfiguration> outputs = new ArrayList<>();
                outputs.add(textureOutput);
                BlockingSessionCallback regularSessionListener = new BlockingSessionCallback(
                        mock(CameraCaptureSession.StateCallback.class));
                SessionConfiguration regularConfiguration = new SessionConfiguration(
                        SessionConfiguration.SESSION_REGULAR, outputs,
                        new HandlerExecutor(mTestRule.getHandler()), regularSessionListener);

                BlockingExtensionSessionCallback sessionListener =
                        new BlockingExtensionSessionCallback(mock(
                                CameraExtensionSession.StateCallback.class));
                ExtensionSessionConfiguration configuration =
                        new ExtensionSessionConfiguration(extension, outputs,
                                new HandlerExecutor(mTestRule.getHandler()), sessionListener);

                try {
                    mTestRule.openDevice(id);
                    mTestRule.getCamera().createCaptureSession(regularConfiguration);

                    CameraCaptureSession session =
                            regularSessionListener
                                    .waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
                    assertNotNull(session);

                    CameraDevice camera = mTestRule.getCamera();
                    camera.createExtensionSession(configuration);
                    CameraExtensionSession extensionSession = sessionListener.waitAndGetSession(
                            SESSION_CONFIGURE_TIMEOUT_MS);
                    assertNotNull(extensionSession);

                    regularSessionListener.getStateWaiter().waitForState(
                            BlockingExtensionSessionCallback.SESSION_CLOSED,
                            SESSION_CLOSE_TIMEOUT_MS);

                    extensionSession.close();
                    sessionListener.getStateWaiter().waitForState(
                            BlockingExtensionSessionCallback.SESSION_CLOSED,
                            SESSION_CLOSE_TIMEOUT_MS);
                } finally {
                    mTestRule.closeDevice(id);
                }
            }
        }
    }

    // Verify that camera extension sessions close as expected when creating a regular capture
    // session.
    @Test
    public void testCloseExtensionSession() throws Exception {
        for (String id : mCameraIdsUnderTest) {
            StaticMetadata staticMeta =
                    new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
            if (!staticMeta.isColorOutputSupported()) {
                continue;
            }
            updatePreviewSurfaceTexture();
            CameraExtensionCharacteristics extensionChars =
                    mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
            List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
            for (Integer extension : supportedExtensions) {
                List<Size> extensionSizes = extensionChars.getExtensionSupportedSizes(extension,
                        mSurfaceTexture.getClass());
                Size maxSize = CameraTestUtils.getMaxSize(extensionSizes.toArray(new Size[0]));
                mSurfaceTexture.setDefaultBufferSize(maxSize.getWidth(), maxSize.getHeight());
                Surface surface = new Surface(mSurfaceTexture);
                OutputConfiguration textureOutput = new OutputConfiguration(
                        OutputConfiguration.SURFACE_GROUP_ID_NONE, surface);
                List<OutputConfiguration> outputs = new ArrayList<>();
                outputs.add(textureOutput);
                BlockingSessionCallback regularSessionListener = new BlockingSessionCallback(
                        mock(CameraCaptureSession.StateCallback.class));
                SessionConfiguration regularConfiguration = new SessionConfiguration(
                        SessionConfiguration.SESSION_REGULAR, outputs,
                        new HandlerExecutor(mTestRule.getHandler()), regularSessionListener);

                BlockingExtensionSessionCallback sessionListener =
                        new BlockingExtensionSessionCallback(mock(
                                CameraExtensionSession.StateCallback.class));
                ExtensionSessionConfiguration configuration =
                        new ExtensionSessionConfiguration(extension, outputs,
                                new HandlerExecutor(mTestRule.getHandler()), sessionListener);

                try {
                    mTestRule.openDevice(id);
                    CameraDevice camera = mTestRule.getCamera();
                    camera.createExtensionSession(configuration);
                    CameraExtensionSession extensionSession = sessionListener.waitAndGetSession(
                            SESSION_CONFIGURE_TIMEOUT_MS);
                    assertNotNull(extensionSession);

                    mTestRule.getCamera().createCaptureSession(regularConfiguration);
                    sessionListener.getStateWaiter().waitForState(
                            BlockingExtensionSessionCallback.SESSION_CLOSED,
                            SESSION_CLOSE_TIMEOUT_MS);

                    CameraCaptureSession session =
                            regularSessionListener.waitAndGetSession(
                                    SESSION_CONFIGURE_TIMEOUT_MS);
                    session.close();
                    regularSessionListener.getStateWaiter().waitForState(
                            BlockingSessionCallback.SESSION_CLOSED, SESSION_CLOSE_TIMEOUT_MS);
                } finally {
                    mTestRule.closeDevice(id);
                }
            }
        }
    }

    // Verify camera device query
    @Test
    public void testGetDevice() throws Exception {
        for (String id : mCameraIdsUnderTest) {
            StaticMetadata staticMeta =
                    new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
            if (!staticMeta.isColorOutputSupported()) {
                continue;
            }
            updatePreviewSurfaceTexture();
            CameraExtensionCharacteristics extensionChars =
                    mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
            List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
            for (Integer extension : supportedExtensions) {
                List<Size> extensionSizes = extensionChars.getExtensionSupportedSizes(extension,
                        mSurfaceTexture.getClass());
                Size maxSize = CameraTestUtils.getMaxSize(extensionSizes.toArray(new Size[0]));
                mSurfaceTexture.setDefaultBufferSize(maxSize.getWidth(), maxSize.getHeight());
                OutputConfiguration privateOutput = new OutputConfiguration(
                        OutputConfiguration.SURFACE_GROUP_ID_NONE,
                        new Surface(mSurfaceTexture));
                List<OutputConfiguration> outputConfigs = new ArrayList<>();
                outputConfigs.add(privateOutput);

                BlockingExtensionSessionCallback sessionListener =
                        new BlockingExtensionSessionCallback(
                                mock(CameraExtensionSession.StateCallback.class));
                ExtensionSessionConfiguration configuration =
                        new ExtensionSessionConfiguration(extension, outputConfigs,
                                new HandlerExecutor(mTestRule.getHandler()), sessionListener);

                try {
                    mTestRule.openDevice(id);
                    CameraDevice camera = mTestRule.getCamera();
                    camera.createExtensionSession(configuration);
                    CameraExtensionSession extensionSession = sessionListener.waitAndGetSession(
                            SESSION_CONFIGURE_TIMEOUT_MS);

                    assertEquals("Unexpected/Invalid camera device", mTestRule.getCamera(),
                            extensionSession.getDevice());
                } finally {
                    mTestRule.closeDevice(id);
                }

                try {
                    sessionListener.getStateWaiter().waitForState(
                            BlockingExtensionSessionCallback.SESSION_CLOSED,
                            SESSION_CLOSE_TIMEOUT_MS);
                    fail("should get TimeoutRuntimeException due to previously closed camera "
                            + "device");
                } catch (TimeoutRuntimeException e) {
                    // Expected, per API spec we should not receive any further session callbacks
                    // besides the device state 'onClosed' callback.
                }
            }
        }
    }

    // Test case for repeating/stopRepeating on all supported extensions and expected state/capture
    // callbacks.
    @Test
    public void testRepeatingCapture() throws Exception {
        for (String id : mCameraIdsUnderTest) {
            StaticMetadata staticMeta =
                    new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
            if (!staticMeta.isColorOutputSupported()) {
                continue;
            }
            updatePreviewSurfaceTexture();
            CameraExtensionCharacteristics extensionChars =
                    mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
            List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
            for (Integer extension : supportedExtensions) {
                List<Size> extensionSizes = extensionChars.getExtensionSupportedSizes(extension,
                        mSurfaceTexture.getClass());
                Size maxSize =
                        CameraTestUtils.getMaxSize(extensionSizes.toArray(new Size[0]));
                mSurfaceTexture.setDefaultBufferSize(maxSize.getWidth(),
                        maxSize.getHeight());
                Surface texturedSurface = new Surface(mSurfaceTexture);

                List<OutputConfiguration> outputConfigs = new ArrayList<>();
                outputConfigs.add(new OutputConfiguration(
                        OutputConfiguration.SURFACE_GROUP_ID_NONE, texturedSurface));

                BlockingExtensionSessionCallback sessionListener =
                        new BlockingExtensionSessionCallback(mock(
                                CameraExtensionSession.StateCallback.class));
                ExtensionSessionConfiguration configuration =
                        new ExtensionSessionConfiguration(extension, outputConfigs,
                                new HandlerExecutor(mTestRule.getHandler()),
                                sessionListener);

                boolean captureResultsSupported =
                        !extensionChars.getAvailableCaptureResultKeys(extension).isEmpty();

                try {
                    mTestRule.openDevice(id);
                    CameraDevice camera = mTestRule.getCamera();
                    camera.createExtensionSession(configuration);
                    CameraExtensionSession extensionSession =
                            sessionListener.waitAndGetSession(
                                    SESSION_CONFIGURE_TIMEOUT_MS);
                    assertNotNull(extensionSession);

                    CaptureRequest.Builder captureBuilder =
                            mTestRule.getCamera().createCaptureRequest(
                                    android.hardware.camera2.CameraDevice.TEMPLATE_PREVIEW);
                    captureBuilder.addTarget(texturedSurface);
                    CameraExtensionSession.ExtensionCaptureCallback captureCallbackMock =
                            mock(CameraExtensionSession.ExtensionCaptureCallback.class);
                    SimpleCaptureCallback simpleCaptureCallback =
                            new SimpleCaptureCallback(captureCallbackMock,
                                    extensionChars.getAvailableCaptureResultKeys(extension),
                                    mCollector);
                    CaptureRequest request = captureBuilder.build();
                    int sequenceId = extensionSession.setRepeatingRequest(request,
                            new HandlerExecutor(mTestRule.getHandler()), simpleCaptureCallback);

                    verify(captureCallbackMock,
                            timeout(REPEATING_REQUEST_TIMEOUT_MS).atLeastOnce())
                            .onCaptureStarted(eq(extensionSession), eq(request), anyLong());
                    verify(captureCallbackMock,
                            timeout(REPEATING_REQUEST_TIMEOUT_MS).atLeastOnce())
                            .onCaptureProcessStarted(extensionSession, request);
                    if (captureResultsSupported) {
                        verify(captureCallbackMock,
                                timeout(MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS).atLeastOnce())
                                .onCaptureResultAvailable(eq(extensionSession), eq(request),
                                        any(TotalCaptureResult.class));
                    }

                    extensionSession.stopRepeating();

                    verify(captureCallbackMock,
                            timeout(MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS).times(1))
                            .onCaptureSequenceCompleted(extensionSession, sequenceId);

                    verify(captureCallbackMock, times(0))
                            .onCaptureSequenceAborted(any(CameraExtensionSession.class),
                                    anyInt());

                    extensionSession.close();

                    sessionListener.getStateWaiter().waitForState(
                            BlockingExtensionSessionCallback.SESSION_CLOSED,
                            SESSION_CLOSE_TIMEOUT_MS);

                    assertTrue("The sum of onCaptureProcessStarted and onCaptureFailed" +
                                    " callbacks must be greater or equal than the number of calls" +
                                    " to onCaptureStarted!",
                            simpleCaptureCallback.getTotalFramesArrived() +
                                    simpleCaptureCallback.getTotalFramesFailed() >=
                                    simpleCaptureCallback.getTotalFramesStarted());
                    assertTrue(String.format("The last repeating request surface timestamp " +
                                    "%d must be less than or equal to the last " +
                                    "onCaptureStarted " +
                                    "timestamp %d", mSurfaceTexture.getTimestamp(),
                            simpleCaptureCallback.getLastTimestamp()),
                            mSurfaceTexture.getTimestamp() <=
                                    simpleCaptureCallback.getLastTimestamp());
                } finally {
                    mTestRule.closeDevice(id);
                    texturedSurface.release();
                }
            }
        }
    }

    // Test case for multi-frame only capture on all supported extensions and expected state
    // callbacks. Verify still frame output, measure the average capture latency and if possible
    // ensure that the value is within the reported range.
    @Test
    public void testMultiFrameCapture() throws Exception {
        final int IMAGE_COUNT = 10;
        final int SUPPORTED_CAPTURE_OUTPUT_FORMATS[] = {
                ImageFormat.YUV_420_888,
                ImageFormat.JPEG
        };
        for (String id : mCameraIdsUnderTest) {
            StaticMetadata staticMeta =
                    new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
            if (!staticMeta.isColorOutputSupported()) {
                continue;
            }
            updatePreviewSurfaceTexture();
            CameraExtensionCharacteristics extensionChars =
                    mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
            List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
            for (Integer extension : supportedExtensions) {
                for (int captureFormat : SUPPORTED_CAPTURE_OUTPUT_FORMATS) {
                    List<Size> extensionSizes = extensionChars.getExtensionSupportedSizes(extension,
                            captureFormat);
                    if (extensionSizes.isEmpty()) {
                        continue;
                    }
                    Size maxSize = CameraTestUtils.getMaxSize(extensionSizes.toArray(new Size[0]));
                    SimpleImageReaderListener imageListener = new SimpleImageReaderListener(false,
                            1);
                    ImageReader extensionImageReader = CameraTestUtils.makeImageReader(maxSize,
                            captureFormat, /*maxImages*/ 1, imageListener,
                            mTestRule.getHandler());
                    Surface imageReaderSurface = extensionImageReader.getSurface();
                    OutputConfiguration readerOutput = new OutputConfiguration(
                            OutputConfiguration.SURFACE_GROUP_ID_NONE, imageReaderSurface);
                    List<OutputConfiguration> outputConfigs = new ArrayList<>();
                    outputConfigs.add(readerOutput);

                    BlockingExtensionSessionCallback sessionListener =
                            new BlockingExtensionSessionCallback(mock(
                                    CameraExtensionSession.StateCallback.class));
                    ExtensionSessionConfiguration configuration =
                            new ExtensionSessionConfiguration(extension, outputConfigs,
                                    new HandlerExecutor(mTestRule.getHandler()),
                                    sessionListener);
                    String streamName = "test_extension_capture";
                    mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
                    mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
                    mReportLog.addValue("extension_id", extension, ResultType.NEUTRAL,
                            ResultUnit.NONE);
                    double[] captureTimes = new double[IMAGE_COUNT];
                    boolean captureResultsSupported =
                            !extensionChars.getAvailableCaptureResultKeys(extension).isEmpty();

                    try {
                        mTestRule.openDevice(id);
                        CameraDevice camera = mTestRule.getCamera();
                        camera.createExtensionSession(configuration);
                        CameraExtensionSession extensionSession =
                                sessionListener.waitAndGetSession(
                                        SESSION_CONFIGURE_TIMEOUT_MS);
                        assertNotNull(extensionSession);

                        CaptureRequest.Builder captureBuilder =
                                mTestRule.getCamera().createCaptureRequest(
                                        CameraDevice.TEMPLATE_STILL_CAPTURE);
                        captureBuilder.addTarget(imageReaderSurface);
                        CameraExtensionSession.ExtensionCaptureCallback captureMockCallback =
                                mock(CameraExtensionSession.ExtensionCaptureCallback.class);
                        SimpleCaptureCallback captureCallback =
                                new SimpleCaptureCallback(captureMockCallback,
                                        extensionChars.getAvailableCaptureResultKeys(extension),
                                        mCollector);

                        for (int i = 0; i < IMAGE_COUNT; i++) {
                            int jpegOrientation = (i * 90) % 360; // degrees [0..270]
                            if (captureFormat == ImageFormat.JPEG) {
                                captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,
                                        jpegOrientation);
                            }
                            CaptureRequest request = captureBuilder.build();
                            long startTimeMs = SystemClock.elapsedRealtime();
                            int sequenceId = extensionSession.capture(request,
                                    new HandlerExecutor(mTestRule.getHandler()), captureCallback);

                            Image img =
                                    imageListener.getImage(MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS);
                            captureTimes[i] = SystemClock.elapsedRealtime() - startTimeMs;
                            if (captureFormat == ImageFormat.JPEG) {
                                verifyJpegOrientation(img, maxSize, jpegOrientation);
                            } else {
                                validateImage(img, maxSize.getWidth(), maxSize.getHeight(),
                                        captureFormat, null);
                            }
                            img.close();

                            verify(captureMockCallback, times(1))
                                    .onCaptureStarted(eq(extensionSession), eq(request), anyLong());
                            verify(captureMockCallback,
                                    timeout(MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS).times(1))
                                    .onCaptureProcessStarted(extensionSession, request);
                            verify(captureMockCallback,
                                    timeout(MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS).times(1))
                                    .onCaptureSequenceCompleted(extensionSession, sequenceId);
                            if (captureResultsSupported) {
                                verify(captureMockCallback,
                                        timeout(MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS).times(1))
                                        .onCaptureResultAvailable(eq(extensionSession), eq(request),
                                                any(TotalCaptureResult.class));
                            }
                        }

                        long avgCaptureLatency = (long) Stat.getAverage(captureTimes);
                        String resultFormat = "avg_latency size: " + maxSize.toString() +
                                " image format: " + captureFormat;
                        mReportLog.addValue(resultFormat, avgCaptureLatency,
                                ResultType.LOWER_BETTER, ResultUnit.MS);

                        verify(captureMockCallback, times(0))
                                .onCaptureSequenceAborted(any(CameraExtensionSession.class),
                                        anyInt());
                        verify(captureMockCallback, times(0))
                                .onCaptureFailed(any(CameraExtensionSession.class),
                                        any(CaptureRequest.class));
                        Range<Long> latencyRange =
                                extensionChars.getEstimatedCaptureLatencyRangeMillis(extension,
                                        maxSize, captureFormat);
                        if (latencyRange != null) {
                            String msg = String.format("Camera [%s]: The measured average "
                                            + "capture latency of %d ms. for extension type %d  "
                                            + "with image format: %d and size: %dx%d must be "
                                            + "within the advertised range of [%d, %d] ms.",
                                    id, avgCaptureLatency, extension, captureFormat,
                                    maxSize.getWidth(), maxSize.getHeight(),
                                    latencyRange.getLower(), latencyRange.getUpper());
                            assertTrue(msg, latencyRange.contains(avgCaptureLatency));
                        }

                        extensionSession.close();

                        sessionListener.getStateWaiter().waitForState(
                                BlockingExtensionSessionCallback.SESSION_CLOSED,
                                SESSION_CLOSE_TIMEOUT_MS);
                    } finally {
                        mTestRule.closeDevice(id);
                        extensionImageReader.close();
                        mReportLog.submit(InstrumentationRegistry.getInstrumentation());
                    }
                }
            }
        }
    }

    // Verify concurrent extension sessions behavior
    @Test
    public void testConcurrentSessions() throws Exception {
        Set<Set<String>> concurrentCameraIdSet =
                mTestRule.getCameraManager().getConcurrentCameraIds();
        if (concurrentCameraIdSet.isEmpty()) {
            return;
        }

        for (String id : mCameraIdsUnderTest) {
            StaticMetadata staticMeta =
                    new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
            if (!staticMeta.isColorOutputSupported()) {
                continue;
            }
            CameraExtensionCharacteristics extensionChars =
                    mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
            List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
            if (supportedExtensions.isEmpty()) {
                continue;
            }

            Set<String> concurrentCameraIds = null;
            for (Set<String> entry : concurrentCameraIdSet) {
                if (entry.contains(id)) {
                    concurrentCameraIds = entry;
                    break;
                }
            }
            if (concurrentCameraIds == null) {
                continue;
            }

            String concurrentCameraId = null;
            CameraExtensionCharacteristics concurrentExtensionChars = null;
            for (String entry : concurrentCameraIds) {
                if (entry.equals(id)) {
                    continue;
                }
                if (!(new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(
                        entry))).isColorOutputSupported()) {
                    continue;
                }
                CameraExtensionCharacteristics chars =
                        mTestRule.getCameraManager().getCameraExtensionCharacteristics(entry);
                if (chars.getSupportedExtensions().isEmpty()) {
                    continue;
                }
                concurrentCameraId = entry;
                concurrentExtensionChars = chars;
                break;
            }
            if ((concurrentCameraId == null) || (concurrentExtensionChars == null)) {
                continue;
            }

            updatePreviewSurfaceTexture();
            int extensionId = supportedExtensions.get(0);
            List<Size> extensionSizes = extensionChars.getExtensionSupportedSizes(extensionId,
                    mSurfaceTexture.getClass());
            Size maxSize = CameraTestUtils.getMaxSize(extensionSizes.toArray(new Size[0]));
            mSurfaceTexture.setDefaultBufferSize(maxSize.getWidth(), maxSize.getHeight());
            OutputConfiguration outputConfig = new OutputConfiguration(
                    OutputConfiguration.SURFACE_GROUP_ID_NONE,
                    new Surface(mSurfaceTexture));
            List<OutputConfiguration> outputConfigs = new ArrayList<>();
            outputConfigs.add(outputConfig);

            BlockingExtensionSessionCallback sessionListener =
                    new BlockingExtensionSessionCallback(
                            mock(CameraExtensionSession.StateCallback.class));
            ExtensionSessionConfiguration configuration =
                    new ExtensionSessionConfiguration(extensionId, outputConfigs,
                            new HandlerExecutor(mTestRule.getHandler()), sessionListener);

            CameraDevice concurrentCameraDevice = null;
            ImageReader extensionImageReader = null;
            try {
                mTestRule.openDevice(id);
                CameraDevice camera = mTestRule.getCamera();
                camera.createExtensionSession(configuration);
                CameraExtensionSession extensionSession = sessionListener.waitAndGetSession(
                        SESSION_CONFIGURE_TIMEOUT_MS);
                assertNotNull(extensionSession);

                concurrentCameraDevice = CameraTestUtils.openCamera(mTestRule.getCameraManager(),
                        concurrentCameraId, new BlockingStateCallback(), mTestRule.getHandler());
                assertNotNull(concurrentCameraDevice);
                int concurrentExtensionId =
                        concurrentExtensionChars.getSupportedExtensions().get(0);
                List<Size> captureSizes = concurrentExtensionChars.getExtensionSupportedSizes(
                        concurrentExtensionId, mSurfaceTexture.getClass());
                assertFalse("No SurfaceTexture output supported", captureSizes.isEmpty());
                Size captureMaxSize =
                        CameraTestUtils.getMaxSize(captureSizes.toArray(new Size[0]));

                extensionImageReader = ImageReader.newInstance(
                        captureMaxSize.getWidth(), captureMaxSize.getHeight(), ImageFormat.PRIVATE,
                        /*maxImages*/ 1, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
                Surface imageReaderSurface = extensionImageReader.getSurface();
                OutputConfiguration readerOutput = new OutputConfiguration(
                        OutputConfiguration.SURFACE_GROUP_ID_NONE, imageReaderSurface);
                outputConfigs = new ArrayList<>();
                outputConfigs.add(readerOutput);
                CameraExtensionSession.StateCallback mockSessionListener =
                        mock(CameraExtensionSession.StateCallback.class);
                ExtensionSessionConfiguration concurrentConfiguration =
                        new ExtensionSessionConfiguration(concurrentExtensionId, outputConfigs,
                                new HandlerExecutor(mTestRule.getHandler()),
                                mockSessionListener);
                concurrentCameraDevice.createExtensionSession(concurrentConfiguration);
                // Trying to initialize multiple concurrent extension sessions is expected to fail
                verify(mockSessionListener, timeout(SESSION_CONFIGURE_TIMEOUT_MS).times(1))
                        .onConfigureFailed(any(CameraExtensionSession.class));
                verify(mockSessionListener, times(0)).onConfigured(
                        any(CameraExtensionSession.class));

                extensionSession.close();
                sessionListener.getStateWaiter().waitForState(
                        BlockingExtensionSessionCallback.SESSION_CLOSED,
                        SESSION_CLOSE_TIMEOUT_MS);

                // Initialization of another extension session must now be possible
                BlockingExtensionSessionCallback concurrentSessionListener =
                        new BlockingExtensionSessionCallback(
                                mock(CameraExtensionSession.StateCallback.class));
                concurrentConfiguration = new ExtensionSessionConfiguration(concurrentExtensionId,
                        outputConfigs, new HandlerExecutor(mTestRule.getHandler()),
                        concurrentSessionListener);
                concurrentCameraDevice.createExtensionSession(concurrentConfiguration);
                extensionSession = concurrentSessionListener.waitAndGetSession(
                        SESSION_CONFIGURE_TIMEOUT_MS);
                assertNotNull(extensionSession);
                extensionSession.close();
                concurrentSessionListener.getStateWaiter().waitForState(
                        BlockingExtensionSessionCallback.SESSION_CLOSED,
                        SESSION_CLOSE_TIMEOUT_MS);
            } finally {
                mTestRule.closeDevice(id);
                if (concurrentCameraDevice != null) {
                    concurrentCameraDevice.close();
                }
                if (extensionImageReader != null) {
                    extensionImageReader.close();
                }
            }
        }
    }

    // Test case combined repeating with multi frame capture on all supported extensions.
    // Verify still frame output.
    @Test
    public void testRepeatingAndCaptureCombined() throws Exception {
        for (String id : mCameraIdsUnderTest) {
            StaticMetadata staticMeta =
                    new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
            if (!staticMeta.isColorOutputSupported()) {
                continue;
            }
            updatePreviewSurfaceTexture();
            CameraExtensionCharacteristics extensionChars =
                    mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
            List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
            for (Integer extension : supportedExtensions) {
                int captureFormat = ImageFormat.JPEG;
                List<Size> captureSizes = extensionChars.getExtensionSupportedSizes(extension,
                        captureFormat);
                assertFalse("No Jpeg output supported", captureSizes.isEmpty());
                Size captureMaxSize =
                        CameraTestUtils.getMaxSize(captureSizes.toArray(new Size[0]));

                SimpleImageReaderListener imageListener = new SimpleImageReaderListener(false
                        , 1);
                ImageReader extensionImageReader = CameraTestUtils.makeImageReader(
                        captureMaxSize, captureFormat, /*maxImages*/ 1, imageListener,
                        mTestRule.getHandler());
                Surface imageReaderSurface = extensionImageReader.getSurface();
                OutputConfiguration readerOutput = new OutputConfiguration(
                        OutputConfiguration.SURFACE_GROUP_ID_NONE, imageReaderSurface);
                List<OutputConfiguration> outputConfigs = new ArrayList<>();
                outputConfigs.add(readerOutput);

                // Pick a supported preview/repeating size with aspect ratio close to the
                // multi-frame capture size
                List<Size> repeatingSizes = extensionChars.getExtensionSupportedSizes(extension,
                        mSurfaceTexture.getClass());
                Size maxRepeatingSize =
                        CameraTestUtils.getMaxSize(repeatingSizes.toArray(new Size[0]));
                List<Size> previewSizes = getSupportedPreviewSizes(id,
                        mTestRule.getCameraManager(),
                        getPreviewSizeBound(mTestRule.getWindowManager(), PREVIEW_SIZE_BOUND));
                List<Size> supportedPreviewSizes =
                        previewSizes.stream().filter(repeatingSizes::contains).collect(
                                Collectors.toList());
                if (!supportedPreviewSizes.isEmpty()) {
                    float targetAr =
                            ((float) captureMaxSize.getWidth()) / captureMaxSize.getHeight();
                    for (Size s : supportedPreviewSizes) {
                        float currentAr = ((float) s.getWidth()) / s.getHeight();
                        if (Math.abs(targetAr - currentAr) < 0.01) {
                            maxRepeatingSize = s;
                            break;
                        }
                    }
                }

                boolean captureResultsSupported =
                        !extensionChars.getAvailableCaptureResultKeys(extension).isEmpty();

                mSurfaceTexture.setDefaultBufferSize(maxRepeatingSize.getWidth(),
                        maxRepeatingSize.getHeight());
                Surface texturedSurface = new Surface(mSurfaceTexture);
                outputConfigs.add(new OutputConfiguration(
                        OutputConfiguration.SURFACE_GROUP_ID_NONE, texturedSurface));

                BlockingExtensionSessionCallback sessionListener =
                        new BlockingExtensionSessionCallback(mock(
                                CameraExtensionSession.StateCallback.class));
                ExtensionSessionConfiguration configuration =
                        new ExtensionSessionConfiguration(extension, outputConfigs,
                                new HandlerExecutor(mTestRule.getHandler()),
                                sessionListener);
                try {
                    mTestRule.openDevice(id);
                    CameraDevice camera = mTestRule.getCamera();
                    camera.createExtensionSession(configuration);
                    CameraExtensionSession extensionSession =
                            sessionListener.waitAndGetSession(
                                    SESSION_CONFIGURE_TIMEOUT_MS);
                    assertNotNull(extensionSession);

                    CaptureRequest.Builder captureBuilder =
                            mTestRule.getCamera().createCaptureRequest(
                                    android.hardware.camera2.CameraDevice.TEMPLATE_PREVIEW);
                    captureBuilder.addTarget(texturedSurface);
                    CameraExtensionSession.ExtensionCaptureCallback repeatingCallbackMock =
                            mock(CameraExtensionSession.ExtensionCaptureCallback.class);
                    SimpleCaptureCallback repeatingCaptureCallback =
                            new SimpleCaptureCallback(repeatingCallbackMock,
                                    extensionChars.getAvailableCaptureResultKeys(extension),
                                    mCollector);
                    CaptureRequest repeatingRequest = captureBuilder.build();
                    int repeatingSequenceId =
                            extensionSession.setRepeatingRequest(repeatingRequest,
                                    new HandlerExecutor(mTestRule.getHandler()),
                                    repeatingCaptureCallback);

                    Thread.sleep(REPEATING_REQUEST_TIMEOUT_MS);

                    verify(repeatingCallbackMock, atLeastOnce())
                            .onCaptureStarted(eq(extensionSession), eq(repeatingRequest),
                                    anyLong());
                    verify(repeatingCallbackMock, atLeastOnce())
                            .onCaptureProcessStarted(extensionSession, repeatingRequest);
                    if (captureResultsSupported) {
                        verify(repeatingCallbackMock,
                                timeout(MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS).atLeastOnce())
                                .onCaptureResultAvailable(eq(extensionSession),
                                        eq(repeatingRequest), any(TotalCaptureResult.class));
                    }

                    captureBuilder = mTestRule.getCamera().createCaptureRequest(
                            android.hardware.camera2.CameraDevice.TEMPLATE_STILL_CAPTURE);
                    captureBuilder.addTarget(imageReaderSurface);
                    CameraExtensionSession.ExtensionCaptureCallback captureCallback =
                            mock(CameraExtensionSession.ExtensionCaptureCallback.class);

                    CaptureRequest captureRequest = captureBuilder.build();
                    int captureSequenceId = extensionSession.capture(captureRequest,
                            new HandlerExecutor(mTestRule.getHandler()), captureCallback);

                    Image img =
                            imageListener.getImage(MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS);
                    validateImage(img, captureMaxSize.getWidth(),
                            captureMaxSize.getHeight(), captureFormat, null);
                    img.close();

                    verify(captureCallback, times(1))
                            .onCaptureStarted(eq(extensionSession), eq(captureRequest),
                                    anyLong());
                    verify(captureCallback, timeout(MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS).times(1))
                            .onCaptureProcessStarted(extensionSession, captureRequest);
                    if (captureResultsSupported) {
                        verify(captureCallback,
                                timeout(MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS).times(1))
                                .onCaptureResultAvailable(eq(extensionSession),
                                        eq(captureRequest), any(TotalCaptureResult.class));
                    }
                    verify(captureCallback, timeout(MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS).times(1))
                            .onCaptureSequenceCompleted(extensionSession,
                                    captureSequenceId);
                    verify(captureCallback, times(0))
                            .onCaptureSequenceAborted(any(CameraExtensionSession.class),
                                    anyInt());
                    verify(captureCallback, times(0))
                            .onCaptureFailed(any(CameraExtensionSession.class),
                                    any(CaptureRequest.class));

                    extensionSession.stopRepeating();

                    verify(repeatingCallbackMock,
                            timeout(MULTI_FRAME_CAPTURE_IMAGE_TIMEOUT_MS).times(1))
                            .onCaptureSequenceCompleted(extensionSession, repeatingSequenceId);

                    verify(repeatingCallbackMock, times(0))
                            .onCaptureSequenceAborted(any(CameraExtensionSession.class),
                                    anyInt());

                    extensionSession.close();

                    sessionListener.getStateWaiter().waitForState(
                            BlockingExtensionSessionCallback.SESSION_CLOSED,
                            SESSION_CLOSE_TIMEOUT_MS);

                    assertTrue("The sum of onCaptureProcessStarted and onCaptureFailed" +
                                    " callbacks must be greater or equal than the number of calls" +
                                    " to onCaptureStarted!",
                            repeatingCaptureCallback.getTotalFramesArrived() +
                                    repeatingCaptureCallback.getTotalFramesFailed() >=
                            repeatingCaptureCallback.getTotalFramesStarted());
                    assertTrue(String.format("The last repeating request surface timestamp " +
                                    "%d must be less than or equal to the last " +
                                    "onCaptureStarted " +
                                    "timestamp %d", mSurfaceTexture.getTimestamp(),
                            repeatingCaptureCallback.getLastTimestamp()),
                            mSurfaceTexture.getTimestamp() <=
                                    repeatingCaptureCallback.getLastTimestamp());

                } finally {
                    mTestRule.closeDevice(id);
                    texturedSurface.release();
                    extensionImageReader.close();
                }
            }
        }
    }

    private void verifyJpegOrientation(Image img, Size jpegSize, int requestedOrientation)
            throws IOException {
        byte[] blobBuffer = getDataFromImage(img);
        String blobFilename = mTestRule.getDebugFileNameBase() + "/verifyJpegKeys.jpeg";
        dumpFile(blobFilename, blobBuffer);
        ExifInterface exif = new ExifInterface(blobFilename);
        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);
        int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                /*defaultValue*/ ExifInterface.ORIENTATION_UNDEFINED);
        final int ORIENTATION_MIN = ExifInterface.ORIENTATION_UNDEFINED;
        final int ORIENTATION_MAX = ExifInterface.ORIENTATION_ROTATE_270;
        assertTrue(String.format("Exif orientation must be in range of [%d, %d]",
                ORIENTATION_MIN, ORIENTATION_MAX),
                exifOrientation >= ORIENTATION_MIN && exifOrientation <= ORIENTATION_MAX);

        /**
         * 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.
            assertEquals("Exif orientation should match requested orientation",
                    requestedOrientation, getExifOrientationInDegree(exifOrientation));
        }

        assertEquals("Exif size should match jpeg capture size", jpegSize, exifSize);
    }

    private static int getExifOrientationInDegree(int exifOrientation) {
        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:
                fail("It is impossible to get non 0, 90, 180, 270 degress exif" +
                        "info based on the request orientation range");
                return -1;
        }
    }

    public static class SimpleCaptureCallback
            extends CameraExtensionSession.ExtensionCaptureCallback {
        private long mLastTimestamp = -1;
        private int mNumFramesArrived = 0;
        private int mNumFramesStarted = 0;
        private int mNumFramesFailed = 0;
        private boolean mNonIncreasingTimestamps = false;
        private final CameraExtensionSession.ExtensionCaptureCallback mProxy;
        private final HashSet<CaptureResult.Key> mSupportedResultKeys;
        private final CameraErrorCollector mCollector;

        public SimpleCaptureCallback(CameraExtensionSession.ExtensionCaptureCallback proxy,
                Set<CaptureResult.Key> supportedResultKeys, CameraErrorCollector errorCollector) {
            mProxy = proxy;
            mSupportedResultKeys = new HashSet<>(supportedResultKeys);
            mCollector = errorCollector;
        }

        @Override
        public void onCaptureStarted(CameraExtensionSession session,
                                     CaptureRequest request, long timestamp) {

            if (timestamp < mLastTimestamp) {
                mNonIncreasingTimestamps = true;
            }
            mLastTimestamp = timestamp;
            mNumFramesStarted++;
            if (mProxy != null) {
                mProxy.onCaptureStarted(session, request, timestamp);
            }
        }

        @Override
        public void onCaptureProcessStarted(CameraExtensionSession session,
                                            CaptureRequest request) {
            mNumFramesArrived++;
            if (mProxy != null) {
                mProxy.onCaptureProcessStarted(session, request);
            }
        }

        @Override
        public void onCaptureFailed(CameraExtensionSession session,
                                    CaptureRequest request) {
            mNumFramesFailed++;
            if (mProxy != null) {
                mProxy.onCaptureFailed(session, request);
            }
        }

        @Override
        public void onCaptureSequenceAborted(CameraExtensionSession session,
                                             int sequenceId) {
            if (mProxy != null) {
                mProxy.onCaptureSequenceAborted(session, sequenceId);
            }
        }

        @Override
        public void onCaptureSequenceCompleted(CameraExtensionSession session,
                                               int sequenceId) {
            if (mProxy != null) {
                mProxy.onCaptureSequenceCompleted(session, sequenceId);
            }
        }

        @Override
        public void  onCaptureResultAvailable(CameraExtensionSession session,
                CaptureRequest request, TotalCaptureResult result) {
            if (mSupportedResultKeys.isEmpty()) {
                mCollector.addMessage("Capture results not supported, but " +
                        "onCaptureResultAvailable still got triggered!");
                return;
            }

            List<CaptureResult.Key<?>> resultKeys = result.getKeys();
            for (CaptureResult.Key<?> resultKey : resultKeys) {
                mCollector.expectTrue("Capture result " + resultKey + " is not among the"
                        + " supported result keys!", mSupportedResultKeys.contains(resultKey));
            }

            Integer jpegOrientation = request.get(CaptureRequest.JPEG_ORIENTATION);
            if (jpegOrientation != null) {
                Integer resultJpegOrientation = result.get(CaptureResult.JPEG_ORIENTATION);
                mCollector.expectTrue("Request Jpeg orientation: " + jpegOrientation +
                        " doesn't match with result: " + resultJpegOrientation,
                        jpegOrientation.equals(resultJpegOrientation));
            }

            Byte jpegQuality = request.get(CaptureRequest.JPEG_QUALITY);
            if (jpegQuality != null) {
                Byte resultJpegQuality = result.get(CaptureResult.JPEG_QUALITY);
                mCollector.expectTrue("Request Jpeg quality: " + jpegQuality +
                        " doesn't match with result: " + resultJpegQuality,
                        jpegQuality.equals(resultJpegQuality));
            }

            if (mProxy != null) {
                mProxy.onCaptureResultAvailable(session, request, result);
            }
        }

        public int getTotalFramesArrived() {
            return mNumFramesArrived;
        }

        public int getTotalFramesStarted() {
            return mNumFramesStarted;
        }

        public int getTotalFramesFailed() {
            return mNumFramesFailed;
        }

        public long getLastTimestamp() throws IllegalStateException {
            if (mNonIncreasingTimestamps) {
                throw new IllegalStateException("Non-monotonically increasing timestamps!");
            }
            return mLastTimestamp;
        }
    }

    @Test
    public void testIllegalArguments() throws Exception {
        for (String id : mCameraIdsUnderTest) {
            StaticMetadata staticMeta =
                    new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
            if (!staticMeta.isColorOutputSupported()) {
                continue;
            }
            updatePreviewSurfaceTexture();
            CameraExtensionCharacteristics extensionChars =
                    mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
            List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
            for (Integer extension : supportedExtensions) {
                List<OutputConfiguration> outputConfigs = new ArrayList<>();
                BlockingExtensionSessionCallback sessionListener =
                        new BlockingExtensionSessionCallback(mock(
                                CameraExtensionSession.StateCallback.class));
                ExtensionSessionConfiguration configuration =
                        new ExtensionSessionConfiguration(extension, outputConfigs,
                                new HandlerExecutor(mTestRule.getHandler()),
                                sessionListener);

                try {
                    mTestRule.openDevice(id);
                    CameraDevice camera = mTestRule.getCamera();
                    try {
                        camera.createExtensionSession(configuration);
                        fail("should get IllegalArgumentException due to absent output surfaces");
                    } catch (IllegalArgumentException e) {
                        // Expected, we can proceed further
                    }

                    int captureFormat = ImageFormat.YUV_420_888;
                    List<Size> captureSizes = extensionChars.getExtensionSupportedSizes(extension,
                            captureFormat);
                    if (captureSizes.isEmpty()) {
                        captureFormat = ImageFormat.JPEG;
                        captureSizes = extensionChars.getExtensionSupportedSizes(extension,
                                captureFormat);
                    }
                    Size captureMaxSize =
                            CameraTestUtils.getMaxSize(captureSizes.toArray(new Size[0]));

                    mSurfaceTexture.setDefaultBufferSize(1, 1);
                    Surface texturedSurface = new Surface(mSurfaceTexture);
                    outputConfigs.add(new OutputConfiguration(
                            OutputConfiguration.SURFACE_GROUP_ID_NONE, texturedSurface));
                    configuration = new ExtensionSessionConfiguration(extension, outputConfigs,
                            new HandlerExecutor(mTestRule.getHandler()), sessionListener);

                    try {
                        camera.createExtensionSession(configuration);
                        fail("should get IllegalArgumentException due to illegal repeating request"
                                + " output surface");
                    } catch (IllegalArgumentException e) {
                        // Expected, we can proceed further
                    } finally {
                        outputConfigs.clear();
                    }

                    SimpleImageReaderListener imageListener = new SimpleImageReaderListener(false,
                            1);
                    Size invalidCaptureSize = new Size(1, 1);
                    ImageReader extensionImageReader = CameraTestUtils.makeImageReader(
                            invalidCaptureSize, captureFormat, /*maxImages*/ 1,
                            imageListener, mTestRule.getHandler());
                    Surface imageReaderSurface = extensionImageReader.getSurface();
                    OutputConfiguration readerOutput = new OutputConfiguration(
                            OutputConfiguration.SURFACE_GROUP_ID_NONE, imageReaderSurface);
                    outputConfigs.add(readerOutput);
                    configuration = new ExtensionSessionConfiguration(extension, outputConfigs,
                            new HandlerExecutor(mTestRule.getHandler()), sessionListener);

                    try{
                        camera.createExtensionSession(configuration);
                        fail("should get IllegalArgumentException due to illegal multi-frame"
                                + " request output surface");
                    } catch (IllegalArgumentException e) {
                        // Expected, we can proceed further
                    } finally {
                        outputConfigs.clear();
                        extensionImageReader.close();
                    }

                    // Pick a supported preview/repeating size with aspect ratio close to the
                    // multi-frame capture size
                    List<Size> repeatingSizes = extensionChars.getExtensionSupportedSizes(extension,
                            mSurfaceTexture.getClass());
                    Size maxRepeatingSize =
                            CameraTestUtils.getMaxSize(repeatingSizes.toArray(new Size[0]));
                    List<Size> previewSizes = getSupportedPreviewSizes(id,
                            mTestRule.getCameraManager(),
                            getPreviewSizeBound(mTestRule.getWindowManager(), PREVIEW_SIZE_BOUND));
                    List<Size> supportedPreviewSizes =
                            previewSizes.stream().filter(repeatingSizes::contains).collect(
                                    Collectors.toList());
                    if (!supportedPreviewSizes.isEmpty()) {
                        float targetAr =
                                ((float) captureMaxSize.getWidth()) / captureMaxSize.getHeight();
                        for (Size s : supportedPreviewSizes) {
                            float currentAr = ((float) s.getWidth()) / s.getHeight();
                            if (Math.abs(targetAr - currentAr) < 0.01) {
                                maxRepeatingSize = s;
                                break;
                            }
                        }
                    }

                    imageListener = new SimpleImageReaderListener(false, 1);
                    extensionImageReader = CameraTestUtils.makeImageReader(captureMaxSize,
                            captureFormat, /*maxImages*/ 1, imageListener, mTestRule.getHandler());
                    imageReaderSurface = extensionImageReader.getSurface();
                    readerOutput = new OutputConfiguration(OutputConfiguration.SURFACE_GROUP_ID_NONE,
                            imageReaderSurface);
                    outputConfigs.add(readerOutput);

                    mSurfaceTexture.setDefaultBufferSize(maxRepeatingSize.getWidth(),
                            maxRepeatingSize.getHeight());
                    texturedSurface = new Surface(mSurfaceTexture);
                    outputConfigs.add(new OutputConfiguration(
                            OutputConfiguration.SURFACE_GROUP_ID_NONE, texturedSurface));

                    configuration = new ExtensionSessionConfiguration(extension, outputConfigs,
                            new HandlerExecutor(mTestRule.getHandler()), sessionListener);
                    camera.createExtensionSession(configuration);
                    CameraExtensionSession extensionSession =
                            sessionListener.waitAndGetSession(
                                    SESSION_CONFIGURE_TIMEOUT_MS);
                    assertNotNull(extensionSession);

                    CaptureRequest.Builder captureBuilder =
                            mTestRule.getCamera().createCaptureRequest(
                                    android.hardware.camera2.CameraDevice.TEMPLATE_PREVIEW);
                    captureBuilder.addTarget(imageReaderSurface);
                    CameraExtensionSession.ExtensionCaptureCallback repeatingCallbackMock =
                            mock(CameraExtensionSession.ExtensionCaptureCallback.class);
                    SimpleCaptureCallback repeatingCaptureCallback =
                            new SimpleCaptureCallback(repeatingCallbackMock,
                                    extensionChars.getAvailableCaptureResultKeys(extension),
                                    mCollector);
                    CaptureRequest repeatingRequest = captureBuilder.build();
                    try {
                        extensionSession.setRepeatingRequest(repeatingRequest,
                                new HandlerExecutor(mTestRule.getHandler()),
                                repeatingCaptureCallback);
                        fail("should get IllegalArgumentException due to illegal repeating request"
                                + " output target");
                    } catch (IllegalArgumentException e) {
                        // Expected, we can proceed further
                    }

                    captureBuilder = mTestRule.getCamera().createCaptureRequest(
                            android.hardware.camera2.CameraDevice.TEMPLATE_STILL_CAPTURE);
                    captureBuilder.addTarget(texturedSurface);
                    CameraExtensionSession.ExtensionCaptureCallback captureCallback =
                            mock(CameraExtensionSession.ExtensionCaptureCallback.class);

                    CaptureRequest captureRequest = captureBuilder.build();
                    try {
                        extensionSession.capture(captureRequest,
                                new HandlerExecutor(mTestRule.getHandler()), captureCallback);
                        fail("should get IllegalArgumentException due to illegal multi-frame"
                                + " request output target");
                    } catch (IllegalArgumentException e) {
                        // Expected, we can proceed further
                    }

                    extensionSession.close();

                    sessionListener.getStateWaiter().waitForState(
                            BlockingExtensionSessionCallback.SESSION_CLOSED,
                            SESSION_CLOSE_TIMEOUT_MS);

                    texturedSurface.release();
                    extensionImageReader.close();

                    try {
                        extensionSession.setRepeatingRequest(captureRequest,
                                new HandlerExecutor(mTestRule.getHandler()), captureCallback);
                        fail("should get IllegalStateException due to closed session");
                    } catch (IllegalStateException e) {
                        // Expected, we can proceed further
                    }

                    try {
                        extensionSession.stopRepeating();
                        fail("should get IllegalStateException due to closed session");
                    } catch (IllegalStateException e) {
                        // Expected, we can proceed further
                    }

                    try {
                        extensionSession.capture(captureRequest,
                                new HandlerExecutor(mTestRule.getHandler()), captureCallback);
                        fail("should get IllegalStateException due to closed session");
                    } catch (IllegalStateException e) {
                        // Expected, we can proceed further
                    }
                } finally {
                    mTestRule.closeDevice(id);
                }
            }
        }
    }
}
