/*
 * 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 static junit.framework.Assert.*;

import static org.mockito.Mockito.*;

import android.app.Instrumentation;
import android.app.NotificationManager;
import android.app.UiAutomation;
import android.content.pm.PackageManager;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraDevice.StateCallback;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.cts.Camera2ParameterizedTestCase;
import android.hardware.camera2.cts.CameraTestUtils.HandlerExecutor;
import android.hardware.camera2.cts.CameraTestUtils.MockStateCallback;
import android.hardware.camera2.cts.helpers.CameraErrorCollector;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Pair;

import androidx.test.InstrumentationRegistry;

import com.android.compatibility.common.util.PropertyUtil;
import com.android.ex.camera2.blocking.BlockingStateCallback;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * <p>Basic test for CameraManager class.</p>
 */

@RunWith(Parameterized.class)
public class CameraManagerTest extends Camera2ParameterizedTestCase {
    private static final String TAG = "CameraManagerTest";
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
    private static final int NUM_CAMERA_REOPENS = 10;
    private static final int AVAILABILITY_TIMEOUT_MS = 10;

    private PackageManager mPackageManager;
    private NoopCameraListener mListener;
    private HandlerThread mHandlerThread;
    private Handler mHandler;
    private BlockingStateCallback mCameraListener;
    private CameraErrorCollector mCollector;
    private Set<Set<String>> mConcurrentCameraIdCombinations;

    /** Load validation jni on initialization. */
    static {
        System.loadLibrary("ctscamera2_jni");
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();
        mPackageManager = mContext.getPackageManager();
        assertNotNull("Can't get package manager", mPackageManager);
        mListener = new NoopCameraListener();

        /**
         * Workaround for mockito and JB-MR2 incompatibility
         *
         * Avoid java.lang.IllegalArgumentException: dexcache == null
         * https://code.google.com/p/dexmaker/issues/detail?id=2
         */
        System.setProperty("dexmaker.dexcache", mContext.getCacheDir().toString());

        mCameraListener = spy(new BlockingStateCallback());

        mHandlerThread = new HandlerThread(TAG);
        mHandlerThread.start();
        mHandler = new Handler(mHandlerThread.getLooper());
        mCollector = new CameraErrorCollector();
        mConcurrentCameraIdCombinations =
                CameraTestUtils.getConcurrentCameraIds(mCameraManager, mAdoptShellPerm);
    }

    @Override
    public void tearDown() throws Exception {
        mHandlerThread.quitSafely();
        mHandler = null;

        try {
            mCollector.verify();
        } catch (Throwable e) {
            // When new Exception(e) is used, exception info will be printed twice.
            throw new Exception(e.getMessage());
        } finally {
            super.tearDown();
        }
    }

    /**
     * Verifies that the reason is in the range of public-only codes.
     */
    private static int checkCameraAccessExceptionReason(CameraAccessException e) {
        int reason = e.getReason();

        switch (reason) {
            case CameraAccessException.CAMERA_DISABLED:
            case CameraAccessException.CAMERA_DISCONNECTED:
            case CameraAccessException.CAMERA_ERROR:
            case CameraAccessException.CAMERA_IN_USE:
            case CameraAccessException.MAX_CAMERAS_IN_USE:
                return reason;
        }

        fail("Invalid CameraAccessException code: " + reason);

        return -1; // unreachable
    }

    @Test
    public void testCameraManagerGetDeviceIdList() throws Exception {
        String[] ids = mCameraIdsUnderTest;
        if (VERBOSE) Log.v(TAG, "CameraManager ids: " + Arrays.toString(ids));

        if (mAdoptShellPerm) {
            Log.v(TAG, "Camera related features may not be accurate for system cameras, skipping");
            return;
        }

        /**
         * Test: that if there is at least one reported id, then the system must have
         * the FEATURE_CAMERA_ANY feature.
         */
        assertTrue("System camera feature and camera id list don't match",
                ids.length == 0 ||
                mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY));

        /**
         * Test: that if the device has front or rear facing cameras, then there
         * must be matched system features.
         */
        boolean externalCameraConnected = false;
        String mainBackId = null, mainFrontId = null;
        Map<String, Integer> lensFacingMap = new HashMap<String, Integer>();
        for (int i = 0; i < ids.length; i++) {
            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
            assertNotNull("Can't get camera characteristics for camera " + ids[i], props);
            Integer lensFacing = props.get(CameraCharacteristics.LENS_FACING);
            lensFacingMap.put(ids[i], lensFacing);
            assertNotNull("Can't get lens facing info", lensFacing);
            if (lensFacing == CameraCharacteristics.LENS_FACING_FRONT) {
                assertTrue("System doesn't have front camera feature",
                        mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT));
                if (mainFrontId == null) {
                    mainFrontId = ids[i];
                }
            } else if (lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
                assertTrue("System doesn't have back camera feature",
                        mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA));
                if (mainBackId == null) {
                    mainBackId = ids[i];
                }
            } else if (lensFacing == CameraCharacteristics.LENS_FACING_EXTERNAL) {
                externalCameraConnected = true;
                assertTrue("System doesn't have external camera feature",
                        mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
            } else {
                fail("Unknown camera lens facing " + lensFacing.toString());
            }
        }

        // Test an external camera is connected if FEATURE_CAMERA_EXTERNAL is advertised
        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL)) {
            assertTrue("External camera is not connected on device with FEATURE_CAMERA_EXTERNAL",
                    externalCameraConnected);
        }

        /**
         * Test: that if there is one camera device, then the system must have some
         * specific features.
         */
        assertTrue("Missing system feature: FEATURE_CAMERA_ANY",
               ids.length == 0
            || mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY));
        assertTrue("Missing system feature: FEATURE_CAMERA, FEATURE_CAMERA_FRONT or FEATURE_CAMERA_EXTERNAL",
               ids.length == 0
            || mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)
            || mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)
            || mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));

        testConcurrentCameraFeature(mainFrontId, mainBackId);
    }

    /**
     * Returns true if mConcurrentCameraIdCombinations has at least one combination containing both
     * mainFrontId and mainBackId.
     * Returns false otherwise.
     */
    private boolean containsMainFrontBackConcurrentCombination(String mainFrontId,
            String mainBackId) {
        if (mainFrontId == null || mainBackId == null) {
            return false;
        }
        boolean combinationFound = false;

        // Go through all combinations and see that at least one combination has a main
        // front + main back camera.
        for (Set<String> cameraIdCombination : mConcurrentCameraIdCombinations) {
            boolean frontFacingFound = false, backFacingFound = false;
            for (String cameraId : cameraIdCombination) {
                if (cameraId.equals(mainFrontId)) {
                    frontFacingFound = true;
                } else if (cameraId.equals(mainBackId)) {
                    backFacingFound = true;
                }
                if (frontFacingFound && backFacingFound) {
                    combinationFound = true;
                    break;
                }
            }
            if (combinationFound) {
                break;
            }
        }
        return combinationFound;
    }

    /**
     * Test the consistency of the statement: If FEATURE_CAMERA_CONCURRENT is advertised,
     * CameraManager.getConcurrentCameraIds()
     * returns a combination which contains the main front id and main back id, and vice versa.
     */
    private void testConcurrentCameraFeature(String mainFrontId, String mainBackId) {
        boolean frontBackFeatureAdvertised =
                  mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_CONCURRENT);
        if (frontBackFeatureAdvertised) {
            assertTrue("FEATURE_CAMERA_CONCURRENT advertised but main front id is null",
                        mainFrontId != null);
            assertTrue("FEATURE_CAMERA_CONCURRENT advertised but main back id is null",
                        mainBackId != null);
        }

        boolean concurrentMainFrontBackCombinationFound =
                containsMainFrontBackConcurrentCombination(mainFrontId, mainBackId);

        if(mCameraIdsUnderTest.length > 0) {
            assertTrue("System camera feature FEATURE_CAMERA_CONCURRENT = "
                    + frontBackFeatureAdvertised
                    + " and device actually having a main front back combination which can operate "
                    + "concurrently = " + concurrentMainFrontBackCombinationFound
                    +  " do not match",
                    frontBackFeatureAdvertised == concurrentMainFrontBackCombinationFound);
        }
    }

    // Test: that properties can be queried from each device, without exceptions.
    @Test
    public void testCameraManagerGetCameraCharacteristics() throws Exception {
        String[] ids = mCameraIdsUnderTest;
        for (int i = 0; i < ids.length; i++) {
            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
            assertNotNull(
                    String.format("Can't get camera characteristics from: ID %s", ids[i]), props);
        }
    }

    // Test: that properties queried between the Java SDK and the C++ NDK are equivalent.
    @Test
    public void testCameraCharacteristicsNdkFromSdk() throws Exception {
        String[] ids = mCameraIdsUnderTest;
        for (int i = 0; i < ids.length; i++) {
            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
            Integer lensFacing = props.get(CameraCharacteristics.LENS_FACING);
            assertNotNull("Can't get lens facing info", lensFacing);

            assertTrue(validateACameraMetadataFromCameraMetadataCriticalTagsNative(
                props, lensFacing.intValue()));
        }
    }

    // Returns true if `props` has lens facing `lensFacing` when queried from the NDK via
    // ACameraMetadata_fromCameraMetadata().
    private static native boolean validateACameraMetadataFromCameraMetadataCriticalTagsNative(
        CameraCharacteristics props, int lensFacing);

    // Test: that an exception is thrown if an invalid device id is passed down.
    @Test
    public void testCameraManagerInvalidDevice() throws Exception {
        String[] ids = mCameraIdsUnderTest;
        // Create an invalid id by concatenating all the valid ids together.
        StringBuilder invalidId = new StringBuilder();
        invalidId.append("INVALID");
        for (int i = 0; i < ids.length; i++) {
            invalidId.append(ids[i]);
        }

        try {
            mCameraManager.getCameraCharacteristics(
                invalidId.toString());
            fail(String.format("Accepted invalid camera ID: %s", invalidId.toString()));
        } catch (IllegalArgumentException e) {
            // This is the exception that should be thrown in this case.
        }
    }

    // Test: that each camera device can be opened one at a time, several times.
    @Test
    public void testCameraManagerOpenCamerasSerially() throws Exception {
        testCameraManagerOpenCamerasSerially(/*useExecutor*/ false);
        testCameraManagerOpenCamerasSerially(/*useExecutor*/ true);
    }

    private void testCameraManagerOpenCamerasSerially(boolean useExecutor) throws Exception {
        final Executor executor = useExecutor ? new HandlerExecutor(mHandler) : null;
        String[] ids = mCameraIdsUnderTest;
        for (int i = 0; i < ids.length; i++) {
            for (int j = 0; j < NUM_CAMERA_REOPENS; j++) {
                CameraDevice camera = null;
                try {
                    MockStateCallback mockListener = MockStateCallback.mock();
                    mCameraListener = new BlockingStateCallback(mockListener);

                    if (useExecutor) {
                        mCameraManager.openCamera(ids[i], executor, mCameraListener);
                    } else {
                        mCameraManager.openCamera(ids[i], mCameraListener, mHandler);
                    }

                    // Block until unConfigured
                    mCameraListener.waitForState(BlockingStateCallback.STATE_OPENED,
                            CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);

                    // Ensure state transitions are in right order:
                    // -- 1) Opened
                    // Ensure no other state transitions have occurred:
                    camera = verifyCameraStateOpened(ids[i], mockListener);
                } finally {
                    if (camera != null) {
                        camera.close();
                    }
                }
            }
        }
    }

    /**
     * Test: one or more camera devices can be open at the same time, or the right error state
     * is set if this can't be done.
     */
    @Test
    public void testCameraManagerOpenAllCameras() throws Exception {
        testCameraManagerOpenAllCameras(/*useExecutor*/ false);
        testCameraManagerOpenAllCameras(/*useExecutor*/ true);
    }

    private void testCameraManagerOpenAllCameras(boolean useExecutor) throws Exception {
        String[] ids = mCameraIdsUnderTest;
        assertNotNull("Camera ids shouldn't be null", ids);

        // Skip test if the device doesn't have multiple cameras.
        if (ids.length <= 1) {
            return;
        }

        final Executor executor = useExecutor ? new HandlerExecutor(mHandler) : null;
        List<CameraDevice> cameraList = new ArrayList<CameraDevice>();
        List<MockStateCallback> listenerList = new ArrayList<MockStateCallback>();
        List<BlockingStateCallback> blockingListenerList = new ArrayList<BlockingStateCallback>();
        try {
            for (int i = 0; i < ids.length; i++) {
                // Ignore state changes from other cameras
                MockStateCallback mockListener = MockStateCallback.mock();
                mCameraListener = new BlockingStateCallback(mockListener);

                /**
                 * Track whether or not we got a synchronous error from openCamera.
                 *
                 * A synchronous error must also be accompanied by an asynchronous
                 * StateCallback#onError callback.
                 */
                boolean expectingError = false;

                String cameraId = ids[i];
                try {
                    if (useExecutor) {
                        mCameraManager.openCamera(cameraId, executor, mCameraListener);
                    } else {
                        mCameraManager.openCamera(cameraId, mCameraListener, mHandler);
                    }
                } catch (CameraAccessException e) {
                    int reason = checkCameraAccessExceptionReason(e);
                    if (reason == CameraAccessException.CAMERA_DISCONNECTED ||
                            reason == CameraAccessException.CAMERA_DISABLED) {
                        // TODO: We should handle a Disabled camera by passing here and elsewhere
                        fail("Camera must not be disconnected or disabled for this test" + ids[i]);
                    } else {
                        expectingError = true;
                    }
                }

                List<Integer> expectedStates = new ArrayList<Integer>();
                expectedStates.add(BlockingStateCallback.STATE_OPENED);
                expectedStates.add(BlockingStateCallback.STATE_ERROR);
                int state = mCameraListener.waitForAnyOfStates(
                        expectedStates, CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);

                // It's possible that we got an asynchronous error transition only. This is ok.
                if (expectingError) {
                    assertEquals("Throwing a CAMERA_ERROR exception must be accompanied with a " +
                            "StateCallback#onError callback",
                            BlockingStateCallback.STATE_ERROR, state);
                }

                /**
                 * Two situations are considered passing:
                 * 1) The camera opened successfully.
                 *     => No error must be set.
                 * 2) The camera did not open because there were too many other cameras opened.
                 *     => Only MAX_CAMERAS_IN_USE error must be set.
                 *
                 * Any other situation is considered a failure.
                 *
                 * For simplicity we treat disconnecting asynchronously as a failure, so
                 * camera devices should not be physically unplugged during this test.
                 */

                CameraDevice camera;
                if (state == BlockingStateCallback.STATE_ERROR) {
                    // Camera did not open because too many other cameras were opened
                    // => onError called exactly once with a non-null camera
                    assertTrue("At least one camera must be opened successfully",
                            cameraList.size() > 0);

                    ArgumentCaptor<CameraDevice> argument =
                            ArgumentCaptor.forClass(CameraDevice.class);

                    verify(mockListener)
                            .onError(
                                    argument.capture(),
                                    eq(CameraDevice.StateCallback.ERROR_MAX_CAMERAS_IN_USE)
                            );
                    verifyNoMoreInteractions(mockListener);

                    camera = argument.getValue();
                    assertNotNull("Expected a non-null camera for the error transition for ID: "
                            + ids[i], camera);
                } else if (state == BlockingStateCallback.STATE_OPENED) {
                    // Camera opened successfully.
                    // => onOpened called exactly once
                    camera = verifyCameraStateOpened(cameraId,
                            mockListener);
                } else {
                    fail("Unexpected state " + state);
                    camera = null; // unreachable. but need this for java compiler
                }

                // Keep track of cameras so we can close it later
                cameraList.add(camera);
                listenerList.add(mockListener);
                blockingListenerList.add(mCameraListener);
            }
        } finally {
            for (int i = 0; i < cameraList.size(); i++) {
                // With conflicting devices, opening of one camera could result in the other camera
                // being disconnected. To handle such case, reset the mock before close.
                reset(listenerList.get(i));
                cameraList.get(i).close();
            }
            for (BlockingStateCallback blockingListener : blockingListenerList) {
                blockingListener.waitForState(
                        BlockingStateCallback.STATE_CLOSED,
                        CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
            }
        }

        /*
         * Ensure that no state transitions have bled through from one camera to another
         * after closing the cameras.
         */
        int i = 0;
        for (MockStateCallback listener : listenerList) {
            CameraDevice camera = cameraList.get(i);

            verify(listener).onClosed(eq(camera));
            verifyNoMoreInteractions(listener);
            i++;
            // Only a #close can happen on the camera since we were done with it.
            // Also nothing else should've happened between the close and the open.
        }
    }

    /**
     * Verifies the camera in this listener was opened and then unconfigured exactly once.
     *
     * <p>This assumes that no other action to the camera has been done (e.g.
     * it hasn't been configured, or closed, or disconnected). Verification is
     * performed immediately without any timeouts.</p>
     *
     * <p>This checks that the state has previously changed first for opened and then unconfigured.
     * Any other state transitions will fail. A test failure is thrown if verification fails.</p>
     *
     * @param cameraId Camera identifier
     * @param listener Listener which was passed to {@link CameraManager#openCamera}
     *
     * @return The camera device (non-{@code null}).
     */
    private static CameraDevice verifyCameraStateOpened(String cameraId,
            MockStateCallback listener) {
        ArgumentCaptor<CameraDevice> argument =
                ArgumentCaptor.forClass(CameraDevice.class);
        InOrder inOrder = inOrder(listener);

        /**
         * State transitions (in that order):
         *  1) onOpened
         *
         * No other transitions must occur for successful #openCamera
         */
        inOrder.verify(listener)
                .onOpened(argument.capture());

        CameraDevice camera = argument.getValue();
        assertNotNull(
                String.format("Failed to open camera device ID: %s", cameraId),
                camera);

        // Do not use inOrder here since that would skip anything called before onOpened
        verifyNoMoreInteractions(listener);

        return camera;
    }

    /**
     * Test: that opening the same device multiple times and make sure the right
     * error state is set.
     */
    @Test
    public void testCameraManagerOpenCameraTwice() throws Exception {
        testCameraManagerOpenCameraTwice(/*useExecutor*/ false);
        testCameraManagerOpenCameraTwice(/*useExecutor*/ true);
    }

    private void testCameraManagerOpenCameraTwice(boolean useExecutor) throws Exception {
        String[] ids = mCameraIdsUnderTest;
        final Executor executor = useExecutor ? new HandlerExecutor(mHandler) : null;

        // Test across every camera device.
        for (int i = 0; i < ids.length; ++i) {
            CameraDevice successCamera = null;
            mCollector.setCameraId(ids[i]);

            try {
                MockStateCallback mockSuccessListener = MockStateCallback.mock();
                MockStateCallback mockFailListener = MockStateCallback.mock();

                BlockingStateCallback successListener =
                        new BlockingStateCallback(mockSuccessListener);
                BlockingStateCallback failListener =
                        new BlockingStateCallback(mockFailListener);

                if (useExecutor) {
                    mCameraManager.openCamera(ids[i], executor, successListener);
                    mCameraManager.openCamera(ids[i], executor, failListener);
                } else {
                    mCameraManager.openCamera(ids[i], successListener, mHandler);
                    mCameraManager.openCamera(ids[i], failListener, mHandler);
                }

                successListener.waitForState(BlockingStateCallback.STATE_OPENED,
                        CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
                ArgumentCaptor<CameraDevice> argument =
                        ArgumentCaptor.forClass(CameraDevice.class);
                verify(mockSuccessListener, atLeastOnce()).onOpened(argument.capture());
                verify(mockSuccessListener, atLeastOnce()).onDisconnected(argument.capture());

                failListener.waitForState(BlockingStateCallback.STATE_OPENED,
                        CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
                verify(mockFailListener, atLeastOnce()).onOpened(argument.capture());

                successCamera = verifyCameraStateOpened(
                        ids[i], mockFailListener);

                verifyNoMoreInteractions(mockFailListener);
            } finally {
                if (successCamera != null) {
                    successCamera.close();
                }
            }
        }
    }

    private class NoopCameraListener extends CameraManager.AvailabilityCallback {
        @Override
        public void onCameraAvailable(String cameraId) {
            // No-op
        }

        @Override
        public void onCameraUnavailable(String cameraId) {
            // No-op
        }
    }

    /**
     * Test: that the APIs to register and unregister a listener run successfully;
     * doesn't test that the listener actually gets invoked at the right time.
     * Registering a listener multiple times should have no effect, and unregistering
     * a listener that isn't registered should have no effect.
     */
    @Test
    public void testCameraManagerListener() throws Exception {
        mCameraManager.unregisterAvailabilityCallback(mListener);
        // Test Handler API
        mCameraManager.registerAvailabilityCallback(mListener, mHandler);
        mCameraManager.registerAvailabilityCallback(mListener, mHandler);
        mCameraManager.unregisterAvailabilityCallback(mListener);
        mCameraManager.unregisterAvailabilityCallback(mListener);
        // Test Executor API
        Executor executor = new HandlerExecutor(mHandler);
        mCameraManager.registerAvailabilityCallback(executor, mListener);
        mCameraManager.registerAvailabilityCallback(executor, mListener);
        mCameraManager.unregisterAvailabilityCallback(mListener);
        mCameraManager.unregisterAvailabilityCallback(mListener);
    }

    /**
     * Test that the availability callbacks fire when expected
     */
    @Test
    public void testCameraManagerListenerCallbacks() throws Exception {
        if (mOverrideCameraId != null) {
            // Testing is done for individual camera. Skip.
            return;
        }
        testCameraManagerListenerCallbacks(/*useExecutor*/ false);
        testCameraManagerListenerCallbacks(/*useExecutor*/ true);
    }

    private <T> void verifyAvailabilityCbsReceived(HashSet<T> expectedCameras,
            LinkedBlockingQueue<T> queue, LinkedBlockingQueue<T> otherQueue,
            boolean available) throws Exception {
        while (expectedCameras.size() > 0) {
            T id = queue.poll(AVAILABILITY_TIMEOUT_MS,
                    java.util.concurrent.TimeUnit.MILLISECONDS);
            assertTrue("Did not receive initial " + (available ? "available" : "unavailable")
                    + " notices for some cameras", id != null);
            expectedCameras.remove(id);
        }
        // Verify no unavailable/available cameras were reported
        assertTrue("Some camera devices are initially " + (available ? "unavailable" : "available"),
                otherQueue.size() == 0);
    }

    private void verifySingleAvailabilityCbsReceived(LinkedBlockingQueue<String> expectedEventQueue,
            LinkedBlockingQueue<String> unExpectedEventQueue, String expectedId,
            String expectedStr, String unExpectedStr) throws Exception {
        String candidateId = expectedEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
                java.util.concurrent.TimeUnit.MILLISECONDS);
        assertNotNull("No " + expectedStr + " notice for expected ID " + expectedId, candidateId);
        assertTrue("Received " + expectedStr + " notice for wrong ID, " +
                "expected " + expectedId + ", got " + candidateId, expectedId.equals(candidateId));
        assertTrue("Received >  1 " + expectedStr + " callback for id " + expectedId,
                expectedEventQueue.size() == 0);
        assertTrue(unExpectedStr + " events received unexpectedly",
                unExpectedEventQueue.size() == 0);
    }

    private void testCameraManagerListenerCallbacks(boolean useExecutor) throws Exception {

        final LinkedBlockingQueue<String> availableEventQueue = new LinkedBlockingQueue<>();
        final LinkedBlockingQueue<String> unavailableEventQueue = new LinkedBlockingQueue<>();
        final Executor executor = useExecutor ? new HandlerExecutor(mHandler) : null;

        final LinkedBlockingQueue<Pair<String, String>> availablePhysicalCamEventQueue =
                new LinkedBlockingQueue<>();
        final LinkedBlockingQueue<Pair<String, String>> unavailablePhysicalCamEventQueue =
                new LinkedBlockingQueue<>();

        final LinkedBlockingQueue<String> onCameraOpenedEventQueue = new LinkedBlockingQueue<>();
        final LinkedBlockingQueue<String> onCameraClosedEventQueue = new LinkedBlockingQueue<>();

        CameraManager.AvailabilityCallback ac = new CameraManager.AvailabilityCallback() {
            @Override
            public void onCameraAvailable(String cameraId) {
                // We allow this callback irrespective of mAdoptShellPerm since for this particular
                // test, in the case when shell permissions are adopted we test all cameras, for
                // simplicity. This is since when mAdoptShellPerm is false, we can't test for
                // onCameraOpened/Closed callbacks (no CAMERA_OPEN_CLOSE_LISTENER permissions).
                // So, to test all cameras, we test them when we adopt shell permission identity.
                super.onCameraAvailable(cameraId);
                availableEventQueue.offer(cameraId);
            }

            @Override
            public void onCameraUnavailable(String cameraId) {
                super.onCameraUnavailable(cameraId);
                unavailableEventQueue.offer(cameraId);
            }

            @Override
            public void onPhysicalCameraAvailable(String cameraId, String physicalCameraId) {
                super.onPhysicalCameraAvailable(cameraId, physicalCameraId);
                availablePhysicalCamEventQueue.offer(new Pair<>(cameraId, physicalCameraId));
            }

            @Override
            public void onPhysicalCameraUnavailable(String cameraId, String physicalCameraId) {
                super.onPhysicalCameraUnavailable(cameraId, physicalCameraId);
                unavailablePhysicalCamEventQueue.offer(new Pair<>(cameraId, physicalCameraId));
            }

            @Override
            public void onCameraOpened(String cameraId, String packageId) {
                super.onCameraOpened(cameraId, packageId);
                String curPackageId = mContext.getPackageName();
                assertTrue("Opening package should be " + curPackageId + ", was " + packageId,
                        curPackageId.equals(packageId));
                onCameraOpenedEventQueue.offer(cameraId);
            }

            @Override
            public void onCameraClosed(String cameraId) {
                super.onCameraClosed(cameraId);
                onCameraClosedEventQueue.offer(cameraId);
            }

        };

        if (useExecutor) {
            mCameraManager.registerAvailabilityCallback(executor, ac);
        } else {
            mCameraManager.registerAvailabilityCallback(ac, mHandler);
        }
        String[] cameras = mCameraIdsUnderTest;
        if (mAdoptShellPerm) {
            //when mAdoptShellPerm is false, we can't test for
            // onCameraOpened/Closed callbacks (no CAMERA_OPEN_CLOSE_LISTENER permissions).
            // So, to test all cameras, we test them when we adopt shell permission identity.
            cameras = mCameraManager.getCameraIdListNoLazy();
        }

        if (cameras.length == 0) {
            Log.i(TAG, "No cameras present, skipping test mAdoprPerm");
            return;
        }

        // Verify we received available for all cameras' initial state in a reasonable amount of time
        HashSet<String> expectedAvailableCameras = new HashSet<String>(Arrays.asList(cameras));
        verifyAvailabilityCbsReceived(expectedAvailableCameras, availableEventQueue,
                unavailableEventQueue, true /*available*/);

        // Verify transitions for individual cameras
        for (String id : cameras) {
            MockStateCallback mockListener = MockStateCallback.mock();
            mCameraListener = new BlockingStateCallback(mockListener);

            // Clear logical camera callback queue in case the initial state of certain physical
            // cameras are unavailable.
            unavailablePhysicalCamEventQueue.clear();

            if (useExecutor) {
                mCameraManager.openCamera(id, executor, mCameraListener);
            } else {
                mCameraManager.openCamera(id, mCameraListener, mHandler);
            }

            // Block until opened
            mCameraListener.waitForState(BlockingStateCallback.STATE_OPENED,
                    CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
            // Then verify only open happened, and get the camera handle
            CameraDevice camera = verifyCameraStateOpened(id, mockListener);

            verifySingleAvailabilityCbsReceived(unavailableEventQueue,
                        availableEventQueue, id, "unavailability", "Availability");
            if (mAdoptShellPerm) {
                // Verify that we see the expected 'onCameraOpened' event.
                verifySingleAvailabilityCbsReceived(onCameraOpenedEventQueue,
                        onCameraClosedEventQueue, id, "onCameraOpened", "onCameraClosed");
            }

            // Verify that we see the expected 'unavailable' events if this camera is a physical
            // camera of another logical multi-camera
            HashSet<Pair<String, String>> relatedLogicalCameras = new HashSet<>();
            for (String multiCamId : cameras) {
                CameraCharacteristics props = mCameraManager.getCameraCharacteristics(multiCamId);
                Set<String> physicalIds = props.getPhysicalCameraIds();
                if (physicalIds.contains(id)) {
                    relatedLogicalCameras.add(new Pair<String, String>(multiCamId, id));
                }
            }

            HashSet<Pair<String, String>> expectedLogicalCameras =
                    new HashSet<>(relatedLogicalCameras);
            verifyAvailabilityCbsReceived(expectedLogicalCameras,
                    unavailablePhysicalCamEventQueue, availablePhysicalCamEventQueue,
                    false /*available*/);

            // Verify that we see the expected 'available' event after closing the camera

            camera.close();
            mCameraListener.waitForState(BlockingStateCallback.STATE_CLOSED,
                    CameraTestUtils.CAMERA_CLOSE_TIMEOUT_MS);

            verifySingleAvailabilityCbsReceived(availableEventQueue, unavailableEventQueue,
                    id, "availability", "Unavailability");

            if (mAdoptShellPerm) {
                verifySingleAvailabilityCbsReceived(onCameraClosedEventQueue,
                        onCameraOpenedEventQueue, id, "onCameraClosed", "onCameraOpened");
            }

            expectedLogicalCameras = new HashSet<Pair<String, String>>(relatedLogicalCameras);
            verifyAvailabilityCbsReceived(expectedLogicalCameras,
                    availablePhysicalCamEventQueue, unavailablePhysicalCamEventQueue,
                    true /*available*/);
        }

        // Verify that we can unregister the listener and see no more events
        assertTrue("Availability events received unexpectedly",
                availableEventQueue.size() == 0);
        assertTrue("Unavailability events received unexpectedly",
                    unavailableEventQueue.size() == 0);

        mCameraManager.unregisterAvailabilityCallback(ac);

        {
            // Open an arbitrary camera and make sure we don't hear about it

            MockStateCallback mockListener = MockStateCallback.mock();
            mCameraListener = new BlockingStateCallback(mockListener);

            if (useExecutor) {
                mCameraManager.openCamera(cameras[0], executor, mCameraListener);
            } else {
                mCameraManager.openCamera(cameras[0], mCameraListener, mHandler);
            }

            // Block until opened
            mCameraListener.waitForState(BlockingStateCallback.STATE_OPENED,
                    CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
            // Then verify only open happened, and close the camera
            CameraDevice camera = verifyCameraStateOpened(cameras[0], mockListener);

            camera.close();

            mCameraListener.waitForState(BlockingStateCallback.STATE_CLOSED,
                    CameraTestUtils.CAMERA_CLOSE_TIMEOUT_MS);

            // No unavailability or availability callback should have occured
            String candidateId = unavailableEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
                    java.util.concurrent.TimeUnit.MILLISECONDS);
            assertTrue(String.format("Received unavailability notice for ID %s unexpectedly ",
                            candidateId),
                    candidateId == null);

            candidateId = availableEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
                    java.util.concurrent.TimeUnit.MILLISECONDS);
            assertTrue(String.format("Received availability notice for ID %s unexpectedly ",
                            candidateId),
                    candidateId == null);

            Pair<String, String> candidatePhysicalIds = unavailablePhysicalCamEventQueue.poll(
                    AVAILABILITY_TIMEOUT_MS, java.util.concurrent.TimeUnit.MILLISECONDS);
            assertTrue("Received unavailability physical camera notice unexpectedly ",
                    candidatePhysicalIds == null);

            candidatePhysicalIds = availablePhysicalCamEventQueue.poll(
                    AVAILABILITY_TIMEOUT_MS, java.util.concurrent.TimeUnit.MILLISECONDS);
            assertTrue("Received availability notice for physical camera unexpectedly ",
                    candidatePhysicalIds == null);
        }

        if (mAdoptShellPerm) {
            // Open an arbitrary camera and make sure subsequently subscribed listener receives
            // correct onCameraOpened/onCameraClosed callbacks

            MockStateCallback mockListener = MockStateCallback.mock();
            mCameraListener = new BlockingStateCallback(mockListener);

            if (useExecutor) {
                mCameraManager.openCamera(cameras[0], executor, mCameraListener);
            } else {
                mCameraManager.openCamera(cameras[0], mCameraListener, mHandler);
            }

            // Block until opened
            mCameraListener.waitForState(BlockingStateCallback.STATE_OPENED,
                    CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
            // Then verify only open happened, and close the camera
            CameraDevice camera = verifyCameraStateOpened(cameras[0], mockListener);

            if (useExecutor) {
                mCameraManager.registerAvailabilityCallback(executor, ac);
            } else {
                mCameraManager.registerAvailabilityCallback(ac, mHandler);
            }

            // Verify that we see the expected 'onCameraOpened' event.
            verifySingleAvailabilityCbsReceived(onCameraOpenedEventQueue,
                    onCameraClosedEventQueue, cameras[0], "onCameraOpened", "onCameraClosed");

            camera.close();

            mCameraListener.waitForState(BlockingStateCallback.STATE_CLOSED,
                    CameraTestUtils.CAMERA_CLOSE_TIMEOUT_MS);

            verifySingleAvailabilityCbsReceived(onCameraClosedEventQueue,
                    onCameraOpenedEventQueue, cameras[0], "onCameraClosed", "onCameraOpened");
        }
    } // testCameraManagerListenerCallbacks

    // Verify no LEGACY-level devices appear on devices first launched in the Q release or newer
    @Test
    @AppModeFull(reason = "Instant apps can't access Test API")
    public void testNoLegacyOnQ() throws Exception {
        if(PropertyUtil.getFirstApiLevel() < Build.VERSION_CODES.Q){
            // LEGACY still allowed for devices upgrading to Q
            return;
        }
        String[] ids = mCameraIdsUnderTest;
        for (int i = 0; i < ids.length; i++) {
            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
            assertNotNull(
                    String.format("Can't get camera characteristics from: ID %s", ids[i]), props);
            Integer hardwareLevel = props.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
            assertNotNull(
                    String.format("Can't get hardware level from: ID %s", ids[i]), hardwareLevel);
            assertTrue(String.format(
                            "Camera device %s cannot be LEGACY level for devices launching on Q",
                            ids[i]),
                    hardwareLevel != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY);
        }
    }

    @Test
    public void testCameraManagerWithDnD() throws Exception {
        String[] cameras = mCameraIdsUnderTest;
        if (cameras.length == 0) {
            Log.i(TAG, "No cameras present, skipping test");
            return;
        }
        // Allow the test package to adjust notification policy
        toggleNotificationPolicyAccess(mContext.getPackageName(),
                InstrumentationRegistry.getInstrumentation(), true);

        // Enable DnD filtering

        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
        try {
            nm.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);

            // Try to use the camera API

            for (String cameraId : cameras) {
                try {
                    CameraCharacteristics c = mCameraManager.getCameraCharacteristics(cameraId);
                    assertTrue("Unable to get camera characteristics when DnD is enabled",
                            c != null);
                } catch (RuntimeException e) {
                    fail("RuntimeException thrown when attempting to access camera " +
                            "characteristics with DnD enabled. " +
                            "https://android-review.googlesource.com/c/platform/frameworks/base/+" +
                            "/747089/ may be missing.");
                }
            }
        } finally {
            // Restore notifications to normal

            nm.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
        }
    }

    @Test
    public void testCameraManagerAutomotiveCameras() throws Exception {
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
            // Execute this test only on the automotive device implementations
            Log.i(TAG, "Skips this test on non automotive device implementations");
            return;
        }

        String[] cameraIds = mCameraIdsUnderTest;
        if (cameraIds.length < 1) {
            Log.i(TAG, "No cameras present, skipping test");
            return;
        }

        /**
         * On automotive device implementations, all cameras must have android.automotive.location
         * and android.automotive.lens.facing in their static metadata.  Also,
         * android.lens.poseTranslation and android.lens.poseRotation must present in a camera's
         * static metadata, and android.lens.poseReference should be set as
         * LENS_POSE_REFERENCE_AUTOMOTIVE in following conditions.
         *
         * - android.automotive.location has AUTOMOTIVE_LOCATION_EXTERIOR_OTHER or
         *   AUTOMOTIVE_LOCATION_EXTRA_OTHER
         * - android.automotive.lens.facing has AUTOMOTIVE_LENS_FACING_EXTERIOR_OTHER or
         *   AUTOMOTIVE_LENS_FACING_INTERIOR_OTHER
         * - One or more camera has the same android.automotive.location and
         *   android.automotive.lens.facing values
         */
        Map<Pair<Integer, Integer>, ArrayList<String>> cameraGroup = new HashMap<>();
        for (String cameraId : cameraIds) {
            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(cameraId);
            assertNotNull(
                    String.format("Can't get camera characteristics from: ID %s", cameraId), props);

            Integer lensFacing = props.get(CameraCharacteristics.LENS_FACING);
            if (lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_EXTERNAL) {
                // Automotive device implementations may have external cameras but they are exempted
                // from this test case.
                continue;
            }

            Integer cameraLocation = props.get(CameraCharacteristics.AUTOMOTIVE_LOCATION);
            assertNotNull(
                    String.format("Can't get a camera location from: ID %s", cameraId),
                    cameraLocation);

            int[] automotiveLensFacing = props.get(CameraCharacteristics.AUTOMOTIVE_LENS_FACING);
            assertNotNull(
                    String.format("Can't get a lens facing direction from: ID %s", cameraId),
                    automotiveLensFacing);

            if (cameraLocation == CameraCharacteristics.AUTOMOTIVE_LOCATION_EXTERIOR_OTHER ||
                    cameraLocation == CameraCharacteristics.AUTOMOTIVE_LOCATION_EXTRA_OTHER ||
                    automotiveLensFacing[0] ==
                            CameraCharacteristics.AUTOMOTIVE_LENS_FACING_EXTERIOR_OTHER ||
                    automotiveLensFacing[0] ==
                            CameraCharacteristics.AUTOMOTIVE_LENS_FACING_INTERIOR_OTHER) {
                checkAutomotiveLensPoseCharacteristics(cameraId, props);
            } else {
                Pair<Integer, Integer> key = new Pair<>(cameraLocation, automotiveLensFacing[0]);
                if (cameraGroup.containsKey(key)) {
                    cameraGroup.get(key).add(cameraId);
                } else {
                    cameraGroup.put(key, new ArrayList<>(Arrays.asList(cameraId)));
                }
            }
        }

        for (Map.Entry<Pair<Integer, Integer>, ArrayList<String>> entry : cameraGroup.entrySet()) {
            ArrayList<String> cameraIdsToVerify = entry.getValue();
            if (cameraIdsToVerify.size() > 1) {
                for (String id : cameraIdsToVerify) {
                    CameraCharacteristics props = mCameraManager.getCameraCharacteristics(id);
                    checkAutomotiveLensPoseCharacteristics(id, props);
                }
            }
        }
    }

    private void checkAutomotiveLensPoseCharacteristics(String cameraId,
            CameraCharacteristics props) {
        Integer reference = props.get(CameraCharacteristics.LENS_POSE_REFERENCE);
        assertNotNull(
                String.format("Can't get a lens pose reference from: ID %s", cameraId),
                reference);
        assertTrue("Lens pose reference must be AUTOMOTIVE",
                reference == CameraCharacteristics.LENS_POSE_REFERENCE_AUTOMOTIVE);
        float[] translation = props.get(CameraCharacteristics.LENS_POSE_TRANSLATION);
        assertNotNull(
                String.format("Can't get a lens pose translation from: ID %s", cameraId),
                translation);
        float[] rotation = props.get(CameraCharacteristics.LENS_POSE_ROTATION);
        assertNotNull(
                String.format("Can't get a lens pose rotation from: ID %s", cameraId),
                rotation);
    }


    private void toggleNotificationPolicyAccess(String packageName,
            Instrumentation instrumentation, boolean on) throws IOException {

        String command = " cmd notification " + (on ? "allow_dnd " : "disallow_dnd ") + packageName;

        runCommand(command, instrumentation);

        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
        assertEquals("Notification Policy Access Grant is " +
                nm.isNotificationPolicyAccessGranted() + " not " + on, on,
                nm.isNotificationPolicyAccessGranted());
    }

    private void runCommand(String command, Instrumentation instrumentation) throws IOException {
        UiAutomation uiAutomation = instrumentation.getUiAutomation();
        // Execute command
        ParcelFileDescriptor fd = mUiAutomation.executeShellCommand(command);
        assertNotNull("Failed to execute shell command: " + command, fd);
        // Wait for the command to finish by reading until EOF
        try (InputStream in = new FileInputStream(fd.getFileDescriptor())) {
            byte[] buffer = new byte[4096];
            while (in.read(buffer) > 0) {}
        } catch (IOException e) {
            throw new IOException("Could not read stdout of command: " + command, e);
        }
    }

}
