summaryrefslogtreecommitdiffstats
path: root/camera2/public/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java
diff options
context:
space:
mode:
Diffstat (limited to 'camera2/public/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java')
-rw-r--r--camera2/public/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java76
1 files changed, 76 insertions, 0 deletions
diff --git a/camera2/public/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java b/camera2/public/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java
index 5b11c2b..500fb12 100644
--- a/camera2/public/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java
+++ b/camera2/public/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java
@@ -21,6 +21,8 @@ import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.util.Log;
+import com.android.ex.camera2.utils.SysTrace;
+
/**
* Manage the auto focus state machine for CameraDevice.
*
@@ -29,6 +31,10 @@ import android.util.Log;
*/
public class AutoFocusStateMachine {
+ /**
+ * Observe state AF state transitions triggered by
+ * {@link AutoFocusStateMachine#onCaptureCompleted onCaptureCompleted}.
+ */
public interface AutoFocusStateListener {
/**
* The camera is currently focused (either active or passive).
@@ -72,6 +78,10 @@ public class AutoFocusStateMachine {
private int mCurrentAfMode = AF_UNINITIALIZED;
private int mCurrentAfTrigger = AF_UNINITIALIZED;
+ private int mCurrentAfCookie = AF_UNINITIALIZED;
+ private String mCurrentAfTrace = "";
+ private int mLastAfCookie = 0;
+
public AutoFocusStateMachine(AutoFocusStateListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener should not be null");
@@ -146,9 +156,11 @@ public class AutoFocusStateMachine {
switch (afState) {
case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
mListener.onAutoFocusSuccess(result, /*locked*/true);
+ endTraceAsync();
break;
case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED:
mListener.onAutoFocusFail(result, /*locked*/true);
+ endTraceAsync();
break;
case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
mListener.onAutoFocusSuccess(result, /*locked*/false);
@@ -169,6 +181,22 @@ public class AutoFocusStateMachine {
}
/**
+ * Reset the current AF state.
+ *
+ * <p>
+ * When dropping capture results (by not invoking {@link #onCaptureCompleted} when a new
+ * {@link CaptureResult} is available), call this function to reset the state. Otherwise
+ * the next time a new state is observed this class may incorrectly consider it as the same
+ * state as before, and not issue any callbacks by {@link AutoFocusStateListener}.
+ * </p>
+ */
+ public synchronized void resetState() {
+ if (VERBOSE_LOGGING) Log.v(TAG, "resetState - last state was " + mLastAfState);
+
+ mLastAfState = AF_UNINITIALIZED;
+ }
+
+ /**
* Lock the lens from moving. Typically used before taking a picture.
*
* <p>After calling this function, submit the new requestBuilder as a separate capture.
@@ -195,6 +223,8 @@ public class AutoFocusStateMachine {
throw new IllegalStateException("AF mode was not enabled");
}
+ beginTraceAsync("AFSM_lockAutoFocus");
+
mCurrentAfTrigger = CaptureRequest.CONTROL_AF_TRIGGER_START;
repeatingBuilder.set(CaptureRequest.CONTROL_AF_MODE, mCurrentAfMode);
@@ -275,6 +305,8 @@ public class AutoFocusStateMachine {
CaptureRequest.Builder requestBuilder) {
if (VERBOSE_LOGGING) Log.v(TAG, "setActiveAutoFocus");
+ beginTraceAsync("AFSM_setActiveAutoFocus");
+
mCurrentAfMode = CaptureRequest.CONTROL_AF_MODE_AUTO;
repeatingBuilder.set(CaptureRequest.CONTROL_AF_MODE, mCurrentAfMode);
@@ -311,4 +343,48 @@ public class AutoFocusStateMachine {
repeatingBuilder.set(CaptureRequest.CONTROL_AF_MODE, mCurrentAfMode);
}
+
+ private synchronized void beginTraceAsync(String sectionName) {
+ if (mCurrentAfCookie != AF_UNINITIALIZED) {
+ // Terminate any currently active async sections before beginning another section
+ SysTrace.endSectionAsync(mCurrentAfTrace, mCurrentAfCookie);
+ }
+
+ mLastAfCookie++;
+ mCurrentAfCookie = mLastAfCookie;
+ mCurrentAfTrace = sectionName;
+
+ SysTrace.beginSectionAsync(sectionName, mCurrentAfCookie);
+ }
+
+ private synchronized void endTraceAsync() {
+ if (mCurrentAfCookie == AF_UNINITIALIZED) {
+ Log.w(TAG, "endTraceAsync - no current trace active");
+ return;
+ }
+
+ SysTrace.endSectionAsync(mCurrentAfTrace, mCurrentAfCookie);
+ mCurrentAfCookie = AF_UNINITIALIZED;
+ }
+
+ /**
+ * Update the repeating request with current focus mode.
+ *
+ * <p>This is typically used when a new repeating request is created to update preview with
+ * new metadata (i.e. crop region). The current auto focus mode needs to be carried over for
+ * correct auto focus behavior.<p>
+ *
+ * @param repeatingBuilder Builder for a repeating request.
+ */
+ public synchronized void updateCaptureRequest(CaptureRequest.Builder repeatingBuilder) {
+ if (repeatingBuilder == null) {
+ throw new IllegalArgumentException("repeatingBuilder shouldn't be null");
+ }
+
+ if (mCurrentAfMode == AF_UNINITIALIZED) {
+ throw new IllegalStateException("AF mode was not enabled");
+ }
+
+ repeatingBuilder.set(CaptureRequest.CONTROL_AF_MODE, mCurrentAfMode);
+ }
}