summaryrefslogtreecommitdiffstats
path: root/camera2
diff options
context:
space:
mode:
authorSol Boucher <solb@google.com>2014-08-25 11:42:50 -0700
committerSol Boucher <solb@google.com>2014-08-26 18:27:59 -0700
commit984a086412a94ebea1bd9af8cd8bbf4afab38034 (patch)
tree2f79b7886436c56a4ba619654ddfb4eba38493eb /camera2
parentf27e71f979e803a3ac00f4057eb909886d957a3e (diff)
downloadandroid_frameworks_ex-984a086412a94ebea1bd9af8cd8bbf4afab38034.tar.gz
android_frameworks_ex-984a086412a94ebea1bd9af8cd8bbf4afab38034.tar.bz2
android_frameworks_ex-984a086412a94ebea1bd9af8cd8bbf4afab38034.zip
camera2-portability: Optimize out some camera2 AE precaptures
If it's already converged and the flash isn't being forced on, there's no need to force the precapture routine, which would delay our capture significantly. Also use onCaptureProgressed() instead of onCaptureCompleted() when possible. Change-Id: I0bb7956498b0070382cd5b39b7ccdc0cc0765913
Diffstat (limited to 'camera2')
-rw-r--r--camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java259
-rw-r--r--camera2/utils/src/com/android/ex/camera2/utils/Camera2RequestSettingsSet.java17
-rw-r--r--camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2UtilsTest.java40
3 files changed, 241 insertions, 75 deletions
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java
index d139c62..2a30063 100644
--- a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java
+++ b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java
@@ -198,6 +198,9 @@ class AndroidCamera2AgentImpl extends CameraAgent {
// Available whenever setAutoFocusMoveCallback() was last invoked with a non-null argument:
private CameraAFMoveCallback mPassiveAfCallback;
+ // Gets reset on every state change
+ private int mCurrentAeState = CaptureResult.CONTROL_AE_STATE_INACTIVE;
+
Camera2Handler(Looper looper) {
super(looper);
}
@@ -263,7 +266,7 @@ class AndroidCamera2AgentImpl extends CameraAgent {
mPhotoSize = null;
mCameraIndex = 0;
mCameraId = null;
- mCameraState.setState(AndroidCamera2StateHolder.CAMERA_UNOPENED);
+ changeState(AndroidCamera2StateHolder.CAMERA_UNOPENED);
break;
}
@@ -289,15 +292,15 @@ class AndroidCamera2AgentImpl extends CameraAgent {
}
mOneshotPreviewingCallback = (CameraStartPreviewCallback) msg.obj;
- mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
+ changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
try {
mSession.setRepeatingRequest(
mPersistentSettings.createRequest(mCamera,
CameraDevice.TEMPLATE_PREVIEW, mPreviewSurface),
- /*listener*/mCameraFocusStateListener, /*handler*/this);
+ /*listener*/mCameraResultStateListener, /*handler*/this);
} catch(CameraAccessException ex) {
Log.w(TAG, "Unable to start preview", ex);
- mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
+ changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
}
break;
}
@@ -310,7 +313,7 @@ class AndroidCamera2AgentImpl extends CameraAgent {
}
mSession.stopRepeating();
- mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
+ changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
break;
}
@@ -368,19 +371,39 @@ class AndroidCamera2AgentImpl extends CameraAgent {
}
// The earliest we can reliably tell whether the autofocus has locked in
- // response to our latest request is when our one-time capture completes.
+ // response to our latest request is when our one-time capture progresses.
// However, it will probably take longer than that, so once that happens,
// just start checking the repeating preview requests as they complete.
final CameraAFCallback callback = (CameraAFCallback) msg.obj;
CameraCaptureSession.CaptureListener deferredCallbackSetter =
new CameraCaptureSession.CaptureListener() {
+ private boolean mAlreadyDispatched = false;
+
+ @Override
+ public void onCaptureProgressed(CameraCaptureSession session,
+ CaptureRequest request,
+ CaptureResult result) {
+ checkAfState(result);
+ }
+
@Override
public void onCaptureCompleted(CameraCaptureSession session,
CaptureRequest request,
TotalCaptureResult result) {
- // Now our mCameraFocusStateListener will invoke the callback the
- // first time it finds the focus motor to be locked.
- mOneshotAfCallback = callback;
+ checkAfState(result);
+ }
+
+ private void checkAfState(CaptureResult result) {
+ if (result.get(CaptureResult.CONTROL_AF_STATE) != null &&
+ !mAlreadyDispatched) {
+ // Now our mCameraResultStateListener will invoke the callback
+ // the first time it finds the focus motor to be locked.
+ mAlreadyDispatched = true;
+ mOneshotAfCallback = callback;
+ // This is an optimization: check the AF state of this frame
+ // instead of simply waiting for the next.
+ mCameraResultStateListener.monitorControlStates(result);
+ }
}
@Override
@@ -392,7 +415,7 @@ class AndroidCamera2AgentImpl extends CameraAgent {
}};
// Send a one-time capture to trigger the camera driver to lock focus.
- mCameraState.setState(AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED);
+ changeState(AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED);
Camera2RequestSettingsSet trigger =
new Camera2RequestSettingsSet(mPersistentSettings);
trigger.set(CaptureRequest.CONTROL_AF_TRIGGER,
@@ -404,7 +427,7 @@ class AndroidCamera2AgentImpl extends CameraAgent {
/*listener*/deferredCallbackSetter, /*handler*/ this);
} catch(CameraAccessException ex) {
Log.e(TAG, "Unable to lock autofocus", ex);
- mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
+ changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
}
break;
}
@@ -418,7 +441,7 @@ class AndroidCamera2AgentImpl extends CameraAgent {
}
// Send a one-time capture to trigger the camera driver to resume scanning.
- mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
+ changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
Camera2RequestSettingsSet cancel =
new Camera2RequestSettingsSet(mPersistentSettings);
cancel.set(CaptureRequest.CONTROL_AF_TRIGGER,
@@ -430,8 +453,7 @@ class AndroidCamera2AgentImpl extends CameraAgent {
/*listener*/null, /*handler*/this);
} catch(CameraAccessException ex) {
Log.e(TAG, "Unable to cancel autofocus", ex);
- mCameraState.setState(
- AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED);
+ changeState(AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED);
}
break;
}
@@ -486,8 +508,21 @@ class AndroidCamera2AgentImpl extends CameraAgent {
final CaptureAvailableListener listener =
(CaptureAvailableListener) msg.obj;
- if (mLegacyDevice) {
- // Just snap the shot
+ if (mLegacyDevice ||
+ (mCurrentAeState == CaptureResult.CONTROL_AE_STATE_CONVERGED &&
+ !mPersistentSettings.matches(CaptureRequest.CONTROL_AE_MODE,
+ CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH) &&
+ !mPersistentSettings.matches(CaptureRequest.FLASH_MODE,
+ CaptureRequest.FLASH_MODE_SINGLE)))
+ {
+ // Legacy devices don't support the precapture state keys and instead
+ // perform autoexposure convergence automatically upon capture.
+
+ // On other devices, as long as it has already converged, it determined
+ // that flash was not required, and we're not going to invalidate the
+ // current exposure levels by forcing the force on, we can save
+ // significant capture time by not forcing a recalculation.
+ Log.i(TAG, "Skipping pre-capture autoexposure convergence");
mCaptureReader.setOnImageAvailableListener(listener, /*handler*/this);
try {
mSession.capture(
@@ -496,17 +531,42 @@ class AndroidCamera2AgentImpl extends CameraAgent {
mCaptureReader.getSurface()),
listener, /*handler*/this);
} catch (CameraAccessException ex) {
- Log.e(TAG, "Unable to initiate legacy capture", ex);
+ Log.e(TAG, "Unable to initiate immediate capture", ex);
}
} else {
- // Not a legacy device, so we need to let AE converge before capturing
+ // We need to let AE converge before capturing. Once our one-time
+ // trigger capture has made it into the pipeline, we'll start checking
+ // for the completion of that convergence, capturing when that happens.
+ Log.i(TAG, "Forcing pre-capture autoexposure convergence");
CameraCaptureSession.CaptureListener deferredCallbackSetter =
new CameraCaptureSession.CaptureListener() {
+ private boolean mAlreadyDispatched = false;
+
+ @Override
+ public void onCaptureProgressed(CameraCaptureSession session,
+ CaptureRequest request,
+ CaptureResult result) {
+ checkAeState(result);
+ }
+
@Override
public void onCaptureCompleted(CameraCaptureSession session,
CaptureRequest request,
TotalCaptureResult result) {
- mOneshotCaptureCallback = listener;
+ checkAeState(result);
+ }
+
+ private void checkAeState(CaptureResult result) {
+ if (result.get(CaptureResult.CONTROL_AE_STATE) != null &&
+ !mAlreadyDispatched) {
+ // Now our mCameraResultStateListener will invoke the
+ // callback once the autoexposure routine has converged.
+ mAlreadyDispatched = true;
+ mOneshotCaptureCallback = listener;
+ // This is an optimization: check the AE state of this frame
+ // instead of simply waiting for the next.
+ mCameraResultStateListener.monitorControlStates(result);
+ }
}
@Override
@@ -599,13 +659,13 @@ class AndroidCamera2AgentImpl extends CameraAgent {
mSession.setRepeatingRequest(
mPersistentSettings.createRequest(mCamera,
CameraDevice.TEMPLATE_PREVIEW, mPreviewSurface),
- /*listener*/mCameraFocusStateListener, /*handler*/this);
+ /*listener*/mCameraResultStateListener, /*handler*/this);
} catch (CameraAccessException ex) {
Log.e(TAG, "Failed to apply updated request settings", ex);
}
} else if (mCameraState.getState() < AndroidCamera2StateHolder.CAMERA_PREVIEW_READY) {
// If we're already ready to preview, this doesn't regress our state
- mCameraState.setState(AndroidCamera2StateHolder.CAMERA_CONFIGURED);
+ changeState(AndroidCamera2StateHolder.CAMERA_CONFIGURED);
}
}
@@ -659,7 +719,17 @@ class AndroidCamera2AgentImpl extends CameraAgent {
} catch (CameraAccessException ex) {
Log.e(TAG, "Failed to close existing camera capture session", ex);
}
- mCameraState.setState(AndroidCamera2StateHolder.CAMERA_CONFIGURED);
+ changeState(AndroidCamera2StateHolder.CAMERA_CONFIGURED);
+ }
+
+ private void changeState(int newState) {
+ if (mCameraState.getState() != newState) {
+ mCameraState.setState(newState);
+ if (newState < AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) {
+ mCurrentAeState = CaptureResult.CONTROL_AE_STATE_INACTIVE;
+ mCameraResultStateListener.resetState();
+ }
+ }
}
// This listener monitors our connection to and disconnection from camera devices.
@@ -680,7 +750,7 @@ class AndroidCamera2AgentImpl extends CameraAgent {
mLegacyDevice =
props.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) ==
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
- mCameraState.setState(AndroidCamera2StateHolder.CAMERA_UNCONFIGURED);
+ changeState(AndroidCamera2StateHolder.CAMERA_UNCONFIGURED);
mOpenCallback.onCameraOpened(mCameraProxy);
} catch (CameraAccessException ex) {
mOpenCallback.onDeviceOpenFailure(mCameraIndex,
@@ -710,7 +780,7 @@ class AndroidCamera2AgentImpl extends CameraAgent {
@Override
public void onConfigured(CameraCaptureSession session) {
mSession = session;
- mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
+ changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
}
@Override
@@ -728,49 +798,73 @@ class AndroidCamera2AgentImpl extends CameraAgent {
}
}};
+ private abstract class CameraResultStateListener
+ extends CameraCaptureSession.CaptureListener {
+ public abstract void monitorControlStates(CaptureResult result);
+
+ public abstract void resetState();
+ }
+
// This listener monitors requested captures and notifies any relevant callbacks.
- private CameraCaptureSession.CaptureListener mCameraFocusStateListener =
- new CameraCaptureSession.CaptureListener() {
+ private CameraResultStateListener mCameraResultStateListener =
+ new CameraResultStateListener() {
private int mLastAfState = -1;
+ private long mLastAfFrameNumber = -1;
+ private long mLastAeFrameNumber = -1;
+
+ @Override
+ public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
+ CaptureResult result) {
+ monitorControlStates(result);
+ }
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
TotalCaptureResult result) {
+ monitorControlStates(result);
+ }
+
+ @Override
+ public void monitorControlStates(CaptureResult result) {
Integer afStateMaybe = result.get(CaptureResult.CONTROL_AF_STATE);
if (afStateMaybe != null) {
int afState = afStateMaybe;
- boolean afStateChanged = false;
- if (afState != mLastAfState) {
+ // Since we handle both partial and total results for multiple frames here, we
+ // might get the final callbacks for an earlier frame after receiving one or
+ // more that correspond to the next one. To prevent our data from oscillating,
+ // we never consider AF states that are older than the last one we've seen.
+ if (result.getFrameNumber() > mLastAfFrameNumber) {
+ boolean afStateChanged = afState != mLastAfState;
mLastAfState = afState;
- afStateChanged = true;
- }
-
- switch (afState) {
- case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
- case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
- case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: {
- if (afStateChanged && mPassiveAfCallback != null) {
- // A CameraAFMoveCallback is attached. If we just started to scan,
- // the motor is moving; otherwise, it has settled.
- mPassiveAfCallback.onAutoFocusMoving(
- afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN,
- mCameraProxy);
+ mLastAfFrameNumber = result.getFrameNumber();
+
+ switch (afState) {
+ case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
+ case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
+ case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: {
+ if (afStateChanged && mPassiveAfCallback != null) {
+ // A CameraAFMoveCallback is attached. If we just started to
+ // scan, the motor is moving; otherwise, it has settled.
+ mPassiveAfCallback.onAutoFocusMoving(
+ afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN,
+ mCameraProxy);
+ }
+ break;
}
- break;
- }
- case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
- case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: {
- if (mOneshotAfCallback != null) {
- // A call to autoFocus() was just made to request a focus lock.
- // Notify the caller that the lens is now indefinitely fixed, and
- // report whether the image we're now stuck with is in focus.
- mOneshotAfCallback.onAutoFocus(
- afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED,
- mCameraProxy);
- mOneshotAfCallback = null;
+ case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
+ case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: {
+ if (mOneshotAfCallback != null) {
+ // A call to autoFocus() was just made to request a focus lock.
+ // Notify the caller that the lens is now indefinitely fixed,
+ // and report whether the image we're stuck with is in focus.
+ mOneshotAfCallback.onAutoFocus(
+ afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED,
+ mCameraProxy);
+ mOneshotAfCallback = null;
+ }
+ break;
}
- break;
}
}
}
@@ -778,36 +872,53 @@ class AndroidCamera2AgentImpl extends CameraAgent {
Integer aeStateMaybe = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeStateMaybe != null) {
int aeState = aeStateMaybe;
-
- switch (aeState) {
- case CaptureResult.CONTROL_AE_STATE_CONVERGED:
- case CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED:
- case CaptureResult.CONTROL_AE_STATE_LOCKED: {
- if (mOneshotCaptureCallback != null) {
- // A call to takePicture() was just made, and autoexposure converged
- // so it's time to initiate the capture!
- mCaptureReader.setOnImageAvailableListener(mOneshotCaptureCallback,
- /*handler*/Camera2Handler.this);
- try {
- mSession.capture(
- mPersistentSettings.createRequest(mCamera,
- CameraDevice.TEMPLATE_STILL_CAPTURE,
- mCaptureReader.getSurface()),
+ // Since we handle both partial and total results for multiple frames here, we
+ // might get the final callbacks for an earlier frame after receiving one or
+ // more that correspond to the next one. To prevent our data from oscillating,
+ // we never consider AE states that are older than the last one we've seen.
+ if (aeState != mCurrentAeState &&
+ result.getFrameNumber() > mLastAeFrameNumber) {
+ mCurrentAeState = aeStateMaybe;
+ mLastAeFrameNumber = result.getFrameNumber();
+
+ switch (aeState) {
+ case CaptureResult.CONTROL_AE_STATE_CONVERGED:
+ case CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED:
+ case CaptureResult.CONTROL_AE_STATE_LOCKED: {
+ if (mOneshotCaptureCallback != null) {
+ // A call to takePicture() was just made, and autoexposure
+ // converged so it's time to initiate the capture!
+ mCaptureReader.setOnImageAvailableListener(
/*listener*/mOneshotCaptureCallback,
/*handler*/Camera2Handler.this);
- } catch (CameraAccessException ex) {
- Log.e(TAG, "Unable to initiate capture", ex);
- } finally {
- mOneshotCaptureCallback = null;
+ try {
+ mSession.capture(
+ mPersistentSettings.createRequest(mCamera,
+ CameraDevice.TEMPLATE_STILL_CAPTURE,
+ mCaptureReader.getSurface()),
+ /*listener*/mOneshotCaptureCallback,
+ /*handler*/Camera2Handler.this);
+ } catch (CameraAccessException ex) {
+ Log.e(TAG, "Unable to initiate capture", ex);
+ } finally {
+ mOneshotCaptureCallback = null;
+ }
}
+ break;
}
- break;
}
}
}
}
@Override
+ public void resetState() {
+ mLastAfState = -1;
+ mLastAfFrameNumber = -1;
+ mLastAeFrameNumber = -1;
+ }
+
+ @Override
public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
CaptureFailure failure) {
Log.e(TAG, "Capture attempt failed with reason " + failure.getReason());
diff --git a/camera2/utils/src/com/android/ex/camera2/utils/Camera2RequestSettingsSet.java b/camera2/utils/src/com/android/ex/camera2/utils/Camera2RequestSettingsSet.java
index fac8f1a..6e1d825 100644
--- a/camera2/utils/src/com/android/ex/camera2/utils/Camera2RequestSettingsSet.java
+++ b/camera2/utils/src/com/android/ex/camera2/utils/Camera2RequestSettingsSet.java
@@ -146,7 +146,7 @@ public class Camera2RequestSettingsSet {
* to its default value or simply unset. While {@link #get} will return
* {@code null} in both these cases, this method will return {@code true}
* and {@code false}, respectively.</p>
-
+ *
* @param key Which setting to look for.
* @return Whether that setting has a value that will propagate with unions.
*
@@ -160,8 +160,23 @@ public class Camera2RequestSettingsSet {
}
/**
+ * Check whether the value of the specified setting matches the given one.
+ *
+ * <p>This method uses the {@code T} type's {@code equals} method, but is
+ * {@code null}-tolerant.</p>
+ *
+ * @param key Which of this class's settings to check.
+ * @param value Value to test for equality against.
+ * @return Whether they are the same.
+ */
+ public <T> boolean matches(Key<T> key, T value) {
+ return Objects.equals(get(key), value);
+ }
+
+ /**
* Get this set of settings's revision identifier, which can be compared
* against cached past values to determine whether it has been modified.
+ *
* <p>Distinct revisions across the same object do not necessarily indicate
* that the object's key/value pairs have changed at all, but the same
* revision on the same object does imply that they've stayed the same.</p>
diff --git a/camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2UtilsTest.java b/camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2UtilsTest.java
index 01eda8f..7847526 100644
--- a/camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2UtilsTest.java
+++ b/camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2UtilsTest.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import android.graphics.Rect;
import android.hardware.camera2.CameraCaptureSession.CaptureListener;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureRequest;
@@ -234,6 +235,45 @@ public class Camera2UtilsTest extends Camera2DeviceTester {
setUp.get(null);
}
+ @Test
+ public void requestSettingsSetMatchesPrimitives() {
+ Camera2RequestSettingsSet setUp = new Camera2RequestSettingsSet();
+ assertTrue(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, null));
+ assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, false));
+ assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, true));
+
+ setUp.set(CaptureRequest.CONTROL_AE_LOCK, null);
+ assertTrue(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, null));
+ assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, false));
+ assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, true));
+
+ setUp.set(CaptureRequest.CONTROL_AE_LOCK, false);
+ assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, null));
+ assertTrue(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, false));
+ assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, true));
+
+ setUp.set(CaptureRequest.CONTROL_AE_LOCK, true);
+ assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, null));
+ assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, false));
+ assertTrue(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, true));
+ }
+
+ @Test
+ public void requestSettingsSetMatchesReferences() {
+ Camera2RequestSettingsSet setUp = new Camera2RequestSettingsSet();
+ assertTrue(setUp.matches(CaptureRequest.SCALER_CROP_REGION, null));
+ assertFalse(setUp.matches(CaptureRequest.SCALER_CROP_REGION, new Rect(0, 0, 0, 0)));
+
+ setUp.set(CaptureRequest.SCALER_CROP_REGION, null);
+ assertTrue(setUp.matches(CaptureRequest.SCALER_CROP_REGION, null));
+ assertFalse(setUp.matches(CaptureRequest.SCALER_CROP_REGION, new Rect(0, 0, 0, 0)));
+
+ setUp.set(CaptureRequest.SCALER_CROP_REGION, new Rect(0, 0, 0, 0));
+ assertFalse(setUp.matches(CaptureRequest.SCALER_CROP_REGION, null));
+ assertTrue(setUp.matches(CaptureRequest.SCALER_CROP_REGION, new Rect(0, 0, 0, 0)));
+ assertFalse(setUp.matches(CaptureRequest.SCALER_CROP_REGION, new Rect(0, 0, 1, 1)));
+ }
+
@Test(expected=NullPointerException.class)
public void requestSettingsSetNullArgToCreateRequest0() throws Exception {
Camera2RequestSettingsSet setUp = new Camera2RequestSettingsSet();