blob: 934aff857ec752bb9d9c406e06465d9f91a4b677 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.plugins.camera;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.CaptureResult.Key;
import android.hardware.camera2.TotalCaptureResult;
import io.flutter.plugins.camera.CameraCaptureCallback.CameraCaptureStateListener;
import io.flutter.plugins.camera.types.CameraCaptureProperties;
import io.flutter.plugins.camera.types.CaptureTimeoutsWrapper;
import io.flutter.plugins.camera.types.Timeout;
import io.flutter.plugins.camera.utils.TestUtils;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.mockito.MockedStatic;
public class CameraCaptureCallbackStatesTest extends TestCase {
private final Integer aeState;
private final Integer afState;
private final CameraState cameraState;
private final boolean isTimedOut;
private Runnable validate;
private CameraCaptureCallback cameraCaptureCallback;
private CameraCaptureStateListener mockCaptureStateListener;
private CameraCaptureSession mockCameraCaptureSession;
private CaptureRequest mockCaptureRequest;
private CaptureResult mockPartialCaptureResult;
private CaptureTimeoutsWrapper mockCaptureTimeouts;
private CameraCaptureProperties mockCaptureProps;
private TotalCaptureResult mockTotalCaptureResult;
private MockedStatic<Timeout> mockedStaticTimeout;
private Timeout mockTimeout;
public static TestSuite suite() {
TestSuite suite = new TestSuite();
setUpPreviewStateTest(suite);
setUpWaitingFocusTests(suite);
setUpWaitingPreCaptureStartTests(suite);
setUpWaitingPreCaptureDoneTests(suite);
return suite;
}
protected CameraCaptureCallbackStatesTest(
String name, CameraState cameraState, Integer afState, Integer aeState) {
this(name, cameraState, afState, aeState, false);
}
protected CameraCaptureCallbackStatesTest(
String name, CameraState cameraState, Integer afState, Integer aeState, boolean isTimedOut) {
super(name);
this.aeState = aeState;
this.afState = afState;
this.cameraState = cameraState;
this.isTimedOut = isTimedOut;
}
@Override
@SuppressWarnings("unchecked")
protected void setUp() throws Exception {
super.setUp();
mockedStaticTimeout = mockStatic(Timeout.class);
mockCaptureStateListener = mock(CameraCaptureStateListener.class);
mockCameraCaptureSession = mock(CameraCaptureSession.class);
mockCaptureRequest = mock(CaptureRequest.class);
mockPartialCaptureResult = mock(CaptureResult.class);
mockTotalCaptureResult = mock(TotalCaptureResult.class);
mockTimeout = mock(Timeout.class);
mockCaptureTimeouts = mock(CaptureTimeoutsWrapper.class);
mockCaptureProps = mock(CameraCaptureProperties.class);
when(mockCaptureTimeouts.getPreCaptureFocusing()).thenReturn(mockTimeout);
when(mockCaptureTimeouts.getPreCaptureMetering()).thenReturn(mockTimeout);
Key<Integer> mockAeStateKey = mock(Key.class);
Key<Integer> mockAfStateKey = mock(Key.class);
TestUtils.setFinalStatic(CaptureResult.class, "CONTROL_AE_STATE", mockAeStateKey);
TestUtils.setFinalStatic(CaptureResult.class, "CONTROL_AF_STATE", mockAfStateKey);
mockedStaticTimeout.when(() -> Timeout.create(1000)).thenReturn(mockTimeout);
cameraCaptureCallback =
CameraCaptureCallback.create(
mockCaptureStateListener, mockCaptureTimeouts, mockCaptureProps);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
mockedStaticTimeout.close();
TestUtils.setFinalStatic(CaptureResult.class, "CONTROL_AE_STATE", null);
TestUtils.setFinalStatic(CaptureResult.class, "CONTROL_AF_STATE", null);
}
@Override
protected void runTest() throws Throwable {
when(mockPartialCaptureResult.get(CaptureResult.CONTROL_AF_STATE)).thenReturn(afState);
when(mockPartialCaptureResult.get(CaptureResult.CONTROL_AE_STATE)).thenReturn(aeState);
when(mockTotalCaptureResult.get(CaptureResult.CONTROL_AF_STATE)).thenReturn(afState);
when(mockTotalCaptureResult.get(CaptureResult.CONTROL_AE_STATE)).thenReturn(aeState);
cameraCaptureCallback.setCameraState(cameraState);
if (isTimedOut) {
when(mockTimeout.getIsExpired()).thenReturn(true);
cameraCaptureCallback.onCaptureCompleted(
mockCameraCaptureSession, mockCaptureRequest, mockTotalCaptureResult);
} else {
cameraCaptureCallback.onCaptureProgressed(
mockCameraCaptureSession, mockCaptureRequest, mockPartialCaptureResult);
}
validate.run();
}
private static void setUpPreviewStateTest(TestSuite suite) {
CameraCaptureCallbackStatesTest previewStateTest =
new CameraCaptureCallbackStatesTest(
"process_should_not_converge_or_pre_capture_when_state_is_preview",
CameraState.STATE_PREVIEW,
null,
null);
previewStateTest.validate =
() -> {
verify(previewStateTest.mockCaptureStateListener, never()).onConverged();
verify(previewStateTest.mockCaptureStateListener, never()).onConverged();
assertEquals(
CameraState.STATE_PREVIEW, previewStateTest.cameraCaptureCallback.getCameraState());
};
suite.addTest(previewStateTest);
}
private static void setUpWaitingFocusTests(TestSuite suite) {
Integer[] actionableAfStates =
new Integer[] {
CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED,
CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED
};
Integer[] nonActionableAfStates =
new Integer[] {
CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN,
CaptureResult.CONTROL_AF_STATE_INACTIVE,
CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED,
CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN,
CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED
};
Map<Integer, Boolean> aeStatesConvergeMap =
new HashMap<Integer, Boolean>() {
{
put(null, true);
put(CaptureResult.CONTROL_AE_STATE_CONVERGED, true);
put(CaptureResult.CONTROL_AE_STATE_PRECAPTURE, false);
put(CaptureResult.CONTROL_AE_STATE_LOCKED, false);
put(CaptureResult.CONTROL_AE_STATE_SEARCHING, false);
put(CaptureResult.CONTROL_AE_STATE_INACTIVE, false);
put(CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED, false);
}
};
CameraCaptureCallbackStatesTest nullStateTest =
new CameraCaptureCallbackStatesTest(
"process_should_not_converge_or_pre_capture_when_afstate_is_null",
CameraState.STATE_WAITING_FOCUS,
null,
null);
nullStateTest.validate =
() -> {
verify(nullStateTest.mockCaptureStateListener, never()).onConverged();
verify(nullStateTest.mockCaptureStateListener, never()).onConverged();
assertEquals(
CameraState.STATE_WAITING_FOCUS,
nullStateTest.cameraCaptureCallback.getCameraState());
};
suite.addTest(nullStateTest);
for (Integer afState : actionableAfStates) {
aeStatesConvergeMap.forEach(
(aeState, shouldConverge) -> {
CameraCaptureCallbackStatesTest focusLockedTest =
new CameraCaptureCallbackStatesTest(
"process_should_converge_when_af_state_is_"
+ afState
+ "_and_ae_state_is_"
+ aeState,
CameraState.STATE_WAITING_FOCUS,
afState,
aeState);
focusLockedTest.validate =
() -> {
if (shouldConverge) {
verify(focusLockedTest.mockCaptureStateListener, times(1)).onConverged();
verify(focusLockedTest.mockCaptureStateListener, never()).onPrecapture();
} else {
verify(focusLockedTest.mockCaptureStateListener, times(1)).onPrecapture();
verify(focusLockedTest.mockCaptureStateListener, never()).onConverged();
}
assertEquals(
CameraState.STATE_WAITING_FOCUS,
focusLockedTest.cameraCaptureCallback.getCameraState());
};
suite.addTest(focusLockedTest);
});
}
for (Integer afState : nonActionableAfStates) {
CameraCaptureCallbackStatesTest focusLockedTest =
new CameraCaptureCallbackStatesTest(
"process_should_do_nothing_when_af_state_is_" + afState,
CameraState.STATE_WAITING_FOCUS,
afState,
null);
focusLockedTest.validate =
() -> {
verify(focusLockedTest.mockCaptureStateListener, never()).onConverged();
verify(focusLockedTest.mockCaptureStateListener, never()).onPrecapture();
assertEquals(
CameraState.STATE_WAITING_FOCUS,
focusLockedTest.cameraCaptureCallback.getCameraState());
};
suite.addTest(focusLockedTest);
}
for (Integer afState : nonActionableAfStates) {
aeStatesConvergeMap.forEach(
(aeState, shouldConverge) -> {
CameraCaptureCallbackStatesTest focusLockedTest =
new CameraCaptureCallbackStatesTest(
"process_should_converge_when_af_state_is_"
+ afState
+ "_and_ae_state_is_"
+ aeState,
CameraState.STATE_WAITING_FOCUS,
afState,
aeState,
true);
focusLockedTest.validate =
() -> {
if (shouldConverge) {
verify(focusLockedTest.mockCaptureStateListener, times(1)).onConverged();
verify(focusLockedTest.mockCaptureStateListener, never()).onPrecapture();
} else {
verify(focusLockedTest.mockCaptureStateListener, times(1)).onPrecapture();
verify(focusLockedTest.mockCaptureStateListener, never()).onConverged();
}
assertEquals(
CameraState.STATE_WAITING_FOCUS,
focusLockedTest.cameraCaptureCallback.getCameraState());
};
suite.addTest(focusLockedTest);
});
}
}
private static void setUpWaitingPreCaptureStartTests(TestSuite suite) {
Map<Integer, CameraState> cameraStateMap =
new HashMap<Integer, CameraState>() {
{
put(null, CameraState.STATE_WAITING_PRECAPTURE_DONE);
put(
CaptureResult.CONTROL_AE_STATE_INACTIVE,
CameraState.STATE_WAITING_PRECAPTURE_START);
put(
CaptureResult.CONTROL_AE_STATE_SEARCHING,
CameraState.STATE_WAITING_PRECAPTURE_START);
put(
CaptureResult.CONTROL_AE_STATE_CONVERGED,
CameraState.STATE_WAITING_PRECAPTURE_DONE);
put(CaptureResult.CONTROL_AE_STATE_LOCKED, CameraState.STATE_WAITING_PRECAPTURE_START);
put(
CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED,
CameraState.STATE_WAITING_PRECAPTURE_DONE);
put(
CaptureResult.CONTROL_AE_STATE_PRECAPTURE,
CameraState.STATE_WAITING_PRECAPTURE_DONE);
}
};
cameraStateMap.forEach(
(aeState, cameraState) -> {
CameraCaptureCallbackStatesTest testCase =
new CameraCaptureCallbackStatesTest(
"process_should_update_camera_state_to_waiting_pre_capture_done_when_ae_state_is_"
+ aeState,
CameraState.STATE_WAITING_PRECAPTURE_START,
null,
aeState);
testCase.validate =
() -> assertEquals(cameraState, testCase.cameraCaptureCallback.getCameraState());
suite.addTest(testCase);
});
cameraStateMap.forEach(
(aeState, cameraState) -> {
if (cameraState == CameraState.STATE_WAITING_PRECAPTURE_DONE) {
return;
}
CameraCaptureCallbackStatesTest testCase =
new CameraCaptureCallbackStatesTest(
"process_should_update_camera_state_to_waiting_pre_capture_done_when_ae_state_is_"
+ aeState,
CameraState.STATE_WAITING_PRECAPTURE_START,
null,
aeState,
true);
testCase.validate =
() ->
assertEquals(
CameraState.STATE_WAITING_PRECAPTURE_DONE,
testCase.cameraCaptureCallback.getCameraState());
suite.addTest(testCase);
});
}
private static void setUpWaitingPreCaptureDoneTests(TestSuite suite) {
Integer[] onConvergeStates =
new Integer[] {
null,
CaptureResult.CONTROL_AE_STATE_CONVERGED,
CaptureResult.CONTROL_AE_STATE_LOCKED,
CaptureResult.CONTROL_AE_STATE_SEARCHING,
CaptureResult.CONTROL_AE_STATE_INACTIVE,
CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED,
};
for (Integer aeState : onConvergeStates) {
CameraCaptureCallbackStatesTest shouldConvergeTest =
new CameraCaptureCallbackStatesTest(
"process_should_converge_when_ae_state_is_" + aeState,
CameraState.STATE_WAITING_PRECAPTURE_DONE,
null,
null);
shouldConvergeTest.validate =
() -> verify(shouldConvergeTest.mockCaptureStateListener, times(1)).onConverged();
suite.addTest(shouldConvergeTest);
}
CameraCaptureCallbackStatesTest shouldNotConvergeTest =
new CameraCaptureCallbackStatesTest(
"process_should_not_converge_when_ae_state_is_pre_capture",
CameraState.STATE_WAITING_PRECAPTURE_DONE,
null,
CaptureResult.CONTROL_AE_STATE_PRECAPTURE);
shouldNotConvergeTest.validate =
() -> verify(shouldNotConvergeTest.mockCaptureStateListener, never()).onConverged();
suite.addTest(shouldNotConvergeTest);
CameraCaptureCallbackStatesTest shouldConvergeWhenTimedOutTest =
new CameraCaptureCallbackStatesTest(
"process_should_not_converge_when_ae_state_is_pre_capture",
CameraState.STATE_WAITING_PRECAPTURE_DONE,
null,
CaptureResult.CONTROL_AE_STATE_PRECAPTURE,
true);
shouldConvergeWhenTimedOutTest.validate =
() ->
verify(shouldConvergeWhenTimedOutTest.mockCaptureStateListener, times(1)).onConverged();
suite.addTest(shouldConvergeWhenTimedOutTest);
}
}