Loading services/core/java/com/android/server/wm/CameraCompatFreeformPolicy.java +2 −4 Original line number Diff line number Diff line Loading @@ -109,10 +109,10 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa } @Override public boolean onCameraOpened(@NonNull ActivityRecord cameraActivity, public void onCameraOpened(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId) { if (!isTreatmentEnabledForActivity(cameraActivity)) { return false; return; } final int existingCameraCompatMode = cameraActivity.mAppCompatController .getAppCompatCameraOverrides() Loading @@ -124,11 +124,9 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa cameraActivity.mAppCompatController.getAppCompatCameraOverrides() .setFreeformCameraCompatMode(newCameraCompatMode); forceUpdateActivityAndTask(cameraActivity); return true; } else { mIsCameraCompatTreatmentPending = false; } return false; } @Override Loading services/core/java/com/android/server/wm/CameraStateMonitor.java +22 −28 Original line number Diff line number Diff line Loading @@ -73,16 +73,6 @@ class CameraStateMonitor { private final ArrayList<CameraCompatStateListener> mCameraStateListeners = new ArrayList<>(); /** * {@link CameraCompatStateListener} which returned {@code true} on the last {@link * CameraCompatStateListener#onCameraOpened(ActivityRecord, String)}, if any. * * <p>This allows the {@link CameraStateMonitor} to notify a particular listener when camera * closes, so they can revert any changes. */ @Nullable private CameraCompatStateListener mCurrentListenerForCameraActivity; private final CameraManager.AvailabilityCallback mAvailabilityCallback = new CameraManager.AvailabilityCallback() { @Override Loading Loading @@ -167,12 +157,7 @@ class CameraStateMonitor { @NonNull String cameraId) { for (int i = 0; i < mCameraStateListeners.size(); i++) { CameraCompatStateListener listener = mCameraStateListeners.get(i); boolean activeCameraTreatment = listener.onCameraOpened( cameraActivity, cameraId); if (activeCameraTreatment) { mCurrentListenerForCameraActivity = listener; break; } listener.onCameraOpened(cameraActivity, cameraId); } } Loading Loading @@ -226,17 +211,28 @@ class CameraStateMonitor { return; } if (mCurrentListenerForCameraActivity != null) { boolean closeSuccessful = mCurrentListenerForCameraActivity.onCameraClosed(cameraId); if (closeSuccessful) { final boolean closeSuccessfulForAllListeners = notifyListenersCameraClosed(cameraId); if (closeSuccessfulForAllListeners) { // Finish cleaning up. mCameraIdPackageBiMapping.removeCameraId(cameraId); mCurrentListenerForCameraActivity = null; } else { // Not ready to process closure yet - the camera activity might be refreshing. // Try again later. rescheduleRemoveCameraActivity(cameraId); } } } /** * @return {@code false} if any listeners have reported issues processing the close. */ private boolean notifyListenersCameraClosed(@NonNull String cameraId) { boolean closeSuccessfulForAllListeners = true; for (int i = 0; i < mCameraStateListeners.size(); i++) { closeSuccessfulForAllListeners &= mCameraStateListeners.get(i).onCameraClosed(cameraId); } return closeSuccessfulForAllListeners; } // TODO(b/335165310): verify that this works in multi instance and permission dialogs. Loading Loading @@ -286,11 +282,9 @@ class CameraStateMonitor { interface CameraCompatStateListener { /** * Notifies the compat listener that an activity has opened camera. * * @return true if the treatment has been applied. */ // TODO(b/336474959): try to decouple `cameraId` from the listeners. boolean onCameraOpened(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId); void onCameraOpened(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId); /** * Notifies the compat listener that camera is closed. * Loading services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java +2 −4 Original line number Diff line number Diff line Loading @@ -298,7 +298,7 @@ final class DisplayRotationCompatPolicy implements CameraStateMonitor.CameraComp } @Override public boolean onCameraOpened(@NonNull ActivityRecord cameraActivity, public void onCameraOpened(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId) { mCameraTask = cameraActivity.getTask(); // Checking whether an activity in fullscreen rather than the task as this camera Loading @@ -306,7 +306,7 @@ final class DisplayRotationCompatPolicy implements CameraStateMonitor.CameraComp if (cameraActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { recomputeConfigurationForCameraCompatIfNeeded(cameraActivity); mDisplayContent.updateOrientation(); return true; return; } // Checking that the whole app is in multi-window mode as we shouldn't show toast // for the activity embedding case. Loading @@ -320,7 +320,6 @@ final class DisplayRotationCompatPolicy implements CameraStateMonitor.CameraComp (String) packageManager.getApplicationLabel( packageManager.getApplicationInfo(cameraActivity.packageName, /* flags */ 0))); return true; } catch (PackageManager.NameNotFoundException e) { ProtoLog.e(WM_DEBUG_ORIENTATION, "DisplayRotationCompatPolicy: Multi-window toast not shown as " Loading @@ -328,7 +327,6 @@ final class DisplayRotationCompatPolicy implements CameraStateMonitor.CameraComp cameraActivity.packageName); } } return false; } @VisibleForTesting Loading services/tests/wmtests/src/com/android/server/wm/CameraStateMonitorTests.java +18 −54 Original line number Diff line number Diff line Loading @@ -43,10 +43,10 @@ import org.junit.runner.RunWith; import java.util.concurrent.Executor; /** * Tests for {@link DisplayRotationCompatPolicy}. * Tests for {@link CameraStateMonitor}. * * Build/Install/Run: * atest WmTests:DisplayRotationCompatPolicyTests * atest WmTests:CameraStateMonitorTests */ @SmallTest @Presubmit Loading @@ -68,23 +68,14 @@ public final class CameraStateMonitorTests extends WindowTestsBase { private ActivityRecord mActivity; private Task mTask; // Simulates a listener which will not react to the change on a particular activity. private final FakeCameraCompatStateListener mNotInterestedListener = new FakeCameraCompatStateListener( /*onCameraOpenedReturnValue=*/ false, /*simulateUnsuccessfulCloseOnce=*/ false); // Simulates a listener which will react to the change on a particular activity - for example // put the activity in a camera compat mode. private final FakeCameraCompatStateListener mInterestedListener = new FakeCameraCompatStateListener( /*onCameraOpenedReturnValue=*/ true, /*simulateUnsuccessfulCloseOnce=*/ false); private final FakeCameraCompatStateListener mListener = new FakeCameraCompatStateListener(/* simulateUnsuccessfulCloseOnce= */ false); // Simulates a listener which for some reason cannot process `onCameraClosed` event once it // first arrives - this means that the update needs to be postponed. private final FakeCameraCompatStateListener mListenerCannotClose = new FakeCameraCompatStateListener( /*onCameraOpenedReturnValue=*/ true, /*simulateUnsuccessfulCloseOnce=*/ true); new FakeCameraCompatStateListener(/* simulateUnsuccessfulCloseOnce= */ true); @Before public void setUp() throws Exception { Loading Loading @@ -129,44 +120,31 @@ public final class CameraStateMonitorTests extends WindowTestsBase { @After public void tearDown() { // Remove all listeners. mCameraStateMonitor.removeCameraStateListener(mNotInterestedListener); mCameraStateMonitor.removeCameraStateListener(mInterestedListener); mCameraStateMonitor.removeCameraStateListener(mListener); mCameraStateMonitor.removeCameraStateListener(mListenerCannotClose); // Reset the listener's state. mNotInterestedListener.resetCounters(); mInterestedListener.resetCounters(); mListener.resetCounters(); mListenerCannotClose.resetCounters(); } @Test public void testOnCameraOpened_listenerAdded_notifiesCameraOpened() { mCameraStateMonitor.addCameraStateListener(mNotInterestedListener); mCameraStateMonitor.addCameraStateListener(mListener); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); assertEquals(1, mNotInterestedListener.mOnCameraOpenedCounter); assertEquals(1, mListener.mOnCameraOpenedCounter); } @Test public void testOnCameraOpened_listenerReturnsFalse_doesNotNotifyCameraClosed() { mCameraStateMonitor.addCameraStateListener(mNotInterestedListener); // Listener returns false on `onCameraOpened`. mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); assertEquals(0, mNotInterestedListener.mOnCameraClosedCounter); } @Test public void testOnCameraOpened_listenerReturnsTrue_notifyCameraClosed() { mCameraStateMonitor.addCameraStateListener(mInterestedListener); public void testOnCameraOpened_cameraClosed_notifyCameraClosed() { mCameraStateMonitor.addCameraStateListener(mListener); // Listener returns true on `onCameraOpened`. mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); assertEquals(1, mInterestedListener.mOnCameraClosedCounter); assertEquals(1, mListener.mOnCameraClosedCounter); } @Test Loading @@ -182,32 +160,22 @@ public final class CameraStateMonitorTests extends WindowTestsBase { @Test public void testReconnectedToDifferentCamera_notifiesListener() { mCameraStateMonitor.addCameraStateListener(mInterestedListener); mCameraStateMonitor.addCameraStateListener(mListener); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_2, TEST_PACKAGE_1); assertEquals(2, mInterestedListener.mOnCameraOpenedCounter); assertEquals(2, mListener.mOnCameraOpenedCounter); } @Test public void testDifferentAppConnectedToCamera_notifiesListener() { mCameraStateMonitor.addCameraStateListener(mInterestedListener); mCameraStateMonitor.addCameraStateListener(mListener); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_2); assertEquals(2, mInterestedListener.mOnCameraOpenedCounter); } @Test public void testCameraAlreadyClosed_notifiesListenerOnce() { mCameraStateMonitor.addCameraStateListener(mInterestedListener); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); assertEquals(1, mInterestedListener.mOnCameraClosedCounter); assertEquals(2, mListener.mOnCameraOpenedCounter); } private void configureActivity(@NonNull String packageName) { Loading @@ -232,7 +200,6 @@ public final class CameraStateMonitorTests extends WindowTestsBase { int mOnCameraOpenedCounter = 0; int mOnCameraClosedCounter = 0; boolean mOnCameraOpenedReturnValue = true; private boolean mOnCameraClosedReturnValue = true; /** Loading @@ -242,17 +209,14 @@ public final class CameraStateMonitorTests extends WindowTestsBase { * subsequent calls. This fake implementation tests the * retry mechanism in {@link CameraStateMonitor}. */ FakeCameraCompatStateListener(boolean onCameraOpenedReturnValue, boolean simulateUnsuccessfulCloseOnce) { mOnCameraOpenedReturnValue = onCameraOpenedReturnValue; FakeCameraCompatStateListener(boolean simulateUnsuccessfulCloseOnce) { mOnCameraClosedReturnValue = !simulateUnsuccessfulCloseOnce; } @Override public boolean onCameraOpened(@NonNull ActivityRecord cameraActivity, public void onCameraOpened(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId) { mOnCameraOpenedCounter++; return mOnCameraOpenedReturnValue; } @Override Loading Loading
services/core/java/com/android/server/wm/CameraCompatFreeformPolicy.java +2 −4 Original line number Diff line number Diff line Loading @@ -109,10 +109,10 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa } @Override public boolean onCameraOpened(@NonNull ActivityRecord cameraActivity, public void onCameraOpened(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId) { if (!isTreatmentEnabledForActivity(cameraActivity)) { return false; return; } final int existingCameraCompatMode = cameraActivity.mAppCompatController .getAppCompatCameraOverrides() Loading @@ -124,11 +124,9 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa cameraActivity.mAppCompatController.getAppCompatCameraOverrides() .setFreeformCameraCompatMode(newCameraCompatMode); forceUpdateActivityAndTask(cameraActivity); return true; } else { mIsCameraCompatTreatmentPending = false; } return false; } @Override Loading
services/core/java/com/android/server/wm/CameraStateMonitor.java +22 −28 Original line number Diff line number Diff line Loading @@ -73,16 +73,6 @@ class CameraStateMonitor { private final ArrayList<CameraCompatStateListener> mCameraStateListeners = new ArrayList<>(); /** * {@link CameraCompatStateListener} which returned {@code true} on the last {@link * CameraCompatStateListener#onCameraOpened(ActivityRecord, String)}, if any. * * <p>This allows the {@link CameraStateMonitor} to notify a particular listener when camera * closes, so they can revert any changes. */ @Nullable private CameraCompatStateListener mCurrentListenerForCameraActivity; private final CameraManager.AvailabilityCallback mAvailabilityCallback = new CameraManager.AvailabilityCallback() { @Override Loading Loading @@ -167,12 +157,7 @@ class CameraStateMonitor { @NonNull String cameraId) { for (int i = 0; i < mCameraStateListeners.size(); i++) { CameraCompatStateListener listener = mCameraStateListeners.get(i); boolean activeCameraTreatment = listener.onCameraOpened( cameraActivity, cameraId); if (activeCameraTreatment) { mCurrentListenerForCameraActivity = listener; break; } listener.onCameraOpened(cameraActivity, cameraId); } } Loading Loading @@ -226,17 +211,28 @@ class CameraStateMonitor { return; } if (mCurrentListenerForCameraActivity != null) { boolean closeSuccessful = mCurrentListenerForCameraActivity.onCameraClosed(cameraId); if (closeSuccessful) { final boolean closeSuccessfulForAllListeners = notifyListenersCameraClosed(cameraId); if (closeSuccessfulForAllListeners) { // Finish cleaning up. mCameraIdPackageBiMapping.removeCameraId(cameraId); mCurrentListenerForCameraActivity = null; } else { // Not ready to process closure yet - the camera activity might be refreshing. // Try again later. rescheduleRemoveCameraActivity(cameraId); } } } /** * @return {@code false} if any listeners have reported issues processing the close. */ private boolean notifyListenersCameraClosed(@NonNull String cameraId) { boolean closeSuccessfulForAllListeners = true; for (int i = 0; i < mCameraStateListeners.size(); i++) { closeSuccessfulForAllListeners &= mCameraStateListeners.get(i).onCameraClosed(cameraId); } return closeSuccessfulForAllListeners; } // TODO(b/335165310): verify that this works in multi instance and permission dialogs. Loading Loading @@ -286,11 +282,9 @@ class CameraStateMonitor { interface CameraCompatStateListener { /** * Notifies the compat listener that an activity has opened camera. * * @return true if the treatment has been applied. */ // TODO(b/336474959): try to decouple `cameraId` from the listeners. boolean onCameraOpened(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId); void onCameraOpened(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId); /** * Notifies the compat listener that camera is closed. * Loading
services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java +2 −4 Original line number Diff line number Diff line Loading @@ -298,7 +298,7 @@ final class DisplayRotationCompatPolicy implements CameraStateMonitor.CameraComp } @Override public boolean onCameraOpened(@NonNull ActivityRecord cameraActivity, public void onCameraOpened(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId) { mCameraTask = cameraActivity.getTask(); // Checking whether an activity in fullscreen rather than the task as this camera Loading @@ -306,7 +306,7 @@ final class DisplayRotationCompatPolicy implements CameraStateMonitor.CameraComp if (cameraActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { recomputeConfigurationForCameraCompatIfNeeded(cameraActivity); mDisplayContent.updateOrientation(); return true; return; } // Checking that the whole app is in multi-window mode as we shouldn't show toast // for the activity embedding case. Loading @@ -320,7 +320,6 @@ final class DisplayRotationCompatPolicy implements CameraStateMonitor.CameraComp (String) packageManager.getApplicationLabel( packageManager.getApplicationInfo(cameraActivity.packageName, /* flags */ 0))); return true; } catch (PackageManager.NameNotFoundException e) { ProtoLog.e(WM_DEBUG_ORIENTATION, "DisplayRotationCompatPolicy: Multi-window toast not shown as " Loading @@ -328,7 +327,6 @@ final class DisplayRotationCompatPolicy implements CameraStateMonitor.CameraComp cameraActivity.packageName); } } return false; } @VisibleForTesting Loading
services/tests/wmtests/src/com/android/server/wm/CameraStateMonitorTests.java +18 −54 Original line number Diff line number Diff line Loading @@ -43,10 +43,10 @@ import org.junit.runner.RunWith; import java.util.concurrent.Executor; /** * Tests for {@link DisplayRotationCompatPolicy}. * Tests for {@link CameraStateMonitor}. * * Build/Install/Run: * atest WmTests:DisplayRotationCompatPolicyTests * atest WmTests:CameraStateMonitorTests */ @SmallTest @Presubmit Loading @@ -68,23 +68,14 @@ public final class CameraStateMonitorTests extends WindowTestsBase { private ActivityRecord mActivity; private Task mTask; // Simulates a listener which will not react to the change on a particular activity. private final FakeCameraCompatStateListener mNotInterestedListener = new FakeCameraCompatStateListener( /*onCameraOpenedReturnValue=*/ false, /*simulateUnsuccessfulCloseOnce=*/ false); // Simulates a listener which will react to the change on a particular activity - for example // put the activity in a camera compat mode. private final FakeCameraCompatStateListener mInterestedListener = new FakeCameraCompatStateListener( /*onCameraOpenedReturnValue=*/ true, /*simulateUnsuccessfulCloseOnce=*/ false); private final FakeCameraCompatStateListener mListener = new FakeCameraCompatStateListener(/* simulateUnsuccessfulCloseOnce= */ false); // Simulates a listener which for some reason cannot process `onCameraClosed` event once it // first arrives - this means that the update needs to be postponed. private final FakeCameraCompatStateListener mListenerCannotClose = new FakeCameraCompatStateListener( /*onCameraOpenedReturnValue=*/ true, /*simulateUnsuccessfulCloseOnce=*/ true); new FakeCameraCompatStateListener(/* simulateUnsuccessfulCloseOnce= */ true); @Before public void setUp() throws Exception { Loading Loading @@ -129,44 +120,31 @@ public final class CameraStateMonitorTests extends WindowTestsBase { @After public void tearDown() { // Remove all listeners. mCameraStateMonitor.removeCameraStateListener(mNotInterestedListener); mCameraStateMonitor.removeCameraStateListener(mInterestedListener); mCameraStateMonitor.removeCameraStateListener(mListener); mCameraStateMonitor.removeCameraStateListener(mListenerCannotClose); // Reset the listener's state. mNotInterestedListener.resetCounters(); mInterestedListener.resetCounters(); mListener.resetCounters(); mListenerCannotClose.resetCounters(); } @Test public void testOnCameraOpened_listenerAdded_notifiesCameraOpened() { mCameraStateMonitor.addCameraStateListener(mNotInterestedListener); mCameraStateMonitor.addCameraStateListener(mListener); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); assertEquals(1, mNotInterestedListener.mOnCameraOpenedCounter); assertEquals(1, mListener.mOnCameraOpenedCounter); } @Test public void testOnCameraOpened_listenerReturnsFalse_doesNotNotifyCameraClosed() { mCameraStateMonitor.addCameraStateListener(mNotInterestedListener); // Listener returns false on `onCameraOpened`. mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); assertEquals(0, mNotInterestedListener.mOnCameraClosedCounter); } @Test public void testOnCameraOpened_listenerReturnsTrue_notifyCameraClosed() { mCameraStateMonitor.addCameraStateListener(mInterestedListener); public void testOnCameraOpened_cameraClosed_notifyCameraClosed() { mCameraStateMonitor.addCameraStateListener(mListener); // Listener returns true on `onCameraOpened`. mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); assertEquals(1, mInterestedListener.mOnCameraClosedCounter); assertEquals(1, mListener.mOnCameraClosedCounter); } @Test Loading @@ -182,32 +160,22 @@ public final class CameraStateMonitorTests extends WindowTestsBase { @Test public void testReconnectedToDifferentCamera_notifiesListener() { mCameraStateMonitor.addCameraStateListener(mInterestedListener); mCameraStateMonitor.addCameraStateListener(mListener); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_2, TEST_PACKAGE_1); assertEquals(2, mInterestedListener.mOnCameraOpenedCounter); assertEquals(2, mListener.mOnCameraOpenedCounter); } @Test public void testDifferentAppConnectedToCamera_notifiesListener() { mCameraStateMonitor.addCameraStateListener(mInterestedListener); mCameraStateMonitor.addCameraStateListener(mListener); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_2); assertEquals(2, mInterestedListener.mOnCameraOpenedCounter); } @Test public void testCameraAlreadyClosed_notifiesListenerOnce() { mCameraStateMonitor.addCameraStateListener(mInterestedListener); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); assertEquals(1, mInterestedListener.mOnCameraClosedCounter); assertEquals(2, mListener.mOnCameraOpenedCounter); } private void configureActivity(@NonNull String packageName) { Loading @@ -232,7 +200,6 @@ public final class CameraStateMonitorTests extends WindowTestsBase { int mOnCameraOpenedCounter = 0; int mOnCameraClosedCounter = 0; boolean mOnCameraOpenedReturnValue = true; private boolean mOnCameraClosedReturnValue = true; /** Loading @@ -242,17 +209,14 @@ public final class CameraStateMonitorTests extends WindowTestsBase { * subsequent calls. This fake implementation tests the * retry mechanism in {@link CameraStateMonitor}. */ FakeCameraCompatStateListener(boolean onCameraOpenedReturnValue, boolean simulateUnsuccessfulCloseOnce) { mOnCameraOpenedReturnValue = onCameraOpenedReturnValue; FakeCameraCompatStateListener(boolean simulateUnsuccessfulCloseOnce) { mOnCameraClosedReturnValue = !simulateUnsuccessfulCloseOnce; } @Override public boolean onCameraOpened(@NonNull ActivityRecord cameraActivity, public void onCameraOpened(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId) { mOnCameraOpenedCounter++; return mOnCameraOpenedReturnValue; } @Override Loading