AutoFocusStateMachine.java revision a47d6986cb4aa66e277c61df79a3947bbecd5de8
1/* 2 * Copyright 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.android.ex.camera2.pos; 17 18import android.hardware.camera2.CameraDevice; 19import android.hardware.camera2.CaptureRequest; 20import android.hardware.camera2.CaptureResult; 21import android.util.Log; 22 23/** 24 * Manage the auto focus state machine for CameraDevice. 25 * 26 * <p>Requests are created only when the AF needs to be manipulated from the user, 27 * but automatic camera-caused AF state changes are broadcasted from any new result.</p> 28 */ 29public class AutoFocusStateMachine { 30 31 public interface AutoFocusStateListener { 32 /** 33 * The camera is currently focused (either active or passive). 34 * 35 * @param locked True if the lens has been locked from moving, false otherwise. 36 */ 37 void onAutoFocusSuccess(CaptureResult result, boolean locked); 38 39 /** 40 * The camera is currently not focused (either active or passive). 41 * 42 * @param locked False if the AF is still scanning, true if needs a restart. 43 */ 44 void onAutoFocusFail(CaptureResult result, boolean locked); 45 46 /** 47 * The camera is currently scanning (either active or passive) 48 * and has not yet converged. 49 * 50 * <p>This is not called for results where the AF either succeeds or fails.</p> 51 */ 52 void onAutoFocusScan(CaptureResult result); 53 54 /** 55 * The camera is currently not doing anything with the autofocus. 56 * 57 * <p>Autofocus could be off, or this could be an intermediate state transition as 58 * scanning restarts.</p> 59 */ 60 void onAutoFocusInactive(CaptureResult result); 61 } 62 63 private static final String TAG = "AutoFocusStateMachine"; 64 private static final boolean DEBUG_LOGGING = Log.isLoggable(TAG, Log.DEBUG); 65 private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE); 66 private static final int AF_UNINITIALIZED = -1; 67 68 private final AutoFocusStateListener mListener; 69 private int mLastAfState = AF_UNINITIALIZED; 70 private int mLastAfMode = AF_UNINITIALIZED; 71 private int mCurrentAfMode = AF_UNINITIALIZED; 72 private int mCurrentAfTrigger = AF_UNINITIALIZED; 73 74 public AutoFocusStateMachine(AutoFocusStateListener listener) { 75 if (listener == null) { 76 throw new IllegalArgumentException("listener should not be null"); 77 } 78 mListener = listener; 79 } 80 81 /** 82 * Invoke every time we get a new CaptureResult via 83 * {@link CameraDevice.CaptureListener#onCaptureCompleted}. 84 * 85 * <p>This function is responsible for dispatching updates via the 86 * {@link AutoFocusStateListener} so without calling this on a regular basis, no 87 * AF changes will be observed.</p> 88 * 89 * @param result CaptureResult 90 */ 91 public synchronized void onCaptureCompleted(CaptureResult result) { 92 93 int afState = result.get(CaptureResult.CONTROL_AF_STATE); 94 int afMode = result.get(CaptureResult.CONTROL_AF_MODE); 95 96 if (DEBUG_LOGGING) Log.d(TAG, "onCaptureCompleted - new AF mode = " + afMode + 97 " new AF state = " + afState); 98 99 if (mLastAfState == afState && afMode == mLastAfMode) { 100 // Same AF state as last time, nothing else needs to be done. 101 return; 102 } 103 104 if (VERBOSE_LOGGING) Log.v(TAG, "onCaptureCompleted - new AF mode = " + afMode + 105 " new AF state = " + afState); 106 107 mLastAfState = afState; 108 mLastAfMode = afMode; 109 110 switch (afState) { 111 case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED: 112 mListener.onAutoFocusSuccess(result, /*locked*/true); 113 break; 114 case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: 115 mListener.onAutoFocusFail(result, /*locked*/true); 116 break; 117 case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED: 118 mListener.onAutoFocusSuccess(result, /*locked*/false); 119 break; 120 case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: 121 mListener.onAutoFocusFail(result, /*locked*/false); 122 break; 123 case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN: 124 mListener.onAutoFocusScan(result); 125 break; 126 case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN: 127 mListener.onAutoFocusScan(result); 128 break; 129 case CaptureResult.CONTROL_AF_STATE_INACTIVE: 130 mListener.onAutoFocusInactive(result); 131 break; 132 } 133 } 134 135 /** 136 * Lock the lens from moving. Typically used before taking a picture. 137 * 138 * <p>After calling this function, submit the new requestBuilder as a separate capture. 139 * Do not submit it as a repeating request or the AF lock will be repeated every time.</p> 140 * 141 * <p>Create a new repeating request from repeatingBuilder and set that as the updated 142 * repeating request.</p> 143 * 144 * <p>If the lock succeeds, {@link AutoFocusStateListener#onAutoFocusSuccess} with 145 * {@code locked == true} will be invoked. If the lock fails, 146 * {@link AutoFocusStateListener#onAutoFocusFail} with {@code scanning == false} will be 147 * invoked.</p> 148 * 149 * @param repeatingBuilder Builder for a repeating request. 150 * @param requestBuilder Builder for a non-repeating request. 151 * 152 */ 153 public synchronized void lockAutoFocus(CaptureRequest.Builder repeatingBuilder, 154 CaptureRequest.Builder requestBuilder) { 155 156 if (VERBOSE_LOGGING) Log.v(TAG, "lockAutoFocus"); 157 158 if (mCurrentAfMode == AF_UNINITIALIZED) { 159 throw new IllegalStateException("AF mode was not enabled"); 160 } 161 162 mCurrentAfTrigger = CaptureRequest.CONTROL_AF_TRIGGER_START; 163 164 repeatingBuilder.set(CaptureRequest.CONTROL_AF_MODE, mCurrentAfMode); 165 requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, mCurrentAfMode); 166 167 repeatingBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, 168 CaptureRequest.CONTROL_AF_TRIGGER_IDLE); 169 requestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, 170 CaptureRequest.CONTROL_AF_TRIGGER_START); 171 } 172 173 /** 174 * Unlock the lens, allowing it to move again. Typically used after taking a picture. 175 * 176 * <p>After calling this function, submit the new requestBuilder as a separate capture. 177 * Do not submit it as a repeating request or the AF lock will be repeated every time.</p> 178 * 179 * <p>Create a new repeating request from repeatingBuilder and set that as the updated 180 * repeating request.</p> 181 * 182 * <p>Once the unlock takes effect, {@link AutoFocusStateListener#onAutoFocusInactive} is 183 * invoked, and after that the effects depend on which mode you were in: 184 * <ul> 185 * <li>Passive - Scanning restarts with {@link AutoFocusStateListener#onAutoFocusScan}</li> 186 * <li>Active - The lens goes back to a default position (no callbacks)</li> 187 * </ul> 188 * </p> 189 * 190 * @param repeatingBuilder Builder for a repeating request. 191 * @param requestBuilder Builder for a non-repeating request. 192 * 193 */ 194 public synchronized void unlockAutoFocus(CaptureRequest.Builder repeatingBuilder, 195 CaptureRequest.Builder requestBuilder) { 196 197 if (VERBOSE_LOGGING) Log.v(TAG, "unlockAutoFocus"); 198 199 if (mCurrentAfMode == AF_UNINITIALIZED) { 200 throw new IllegalStateException("AF mode was not enabled"); 201 } 202 203 mCurrentAfTrigger = CaptureRequest.CONTROL_AF_TRIGGER_CANCEL; 204 205 repeatingBuilder.set(CaptureRequest.CONTROL_AF_MODE, mCurrentAfMode); 206 requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, mCurrentAfMode); 207 208 repeatingBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, 209 CaptureRequest.CONTROL_AF_TRIGGER_IDLE); 210 requestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, 211 CaptureRequest.CONTROL_AF_TRIGGER_CANCEL); 212 } 213 214 /** 215 * Enable active auto focus, immediately triggering a converging scan. 216 * 217 * <p>This is typically only used when locking the passive AF has failed.</p> 218 * 219 * <p>Once active AF scanning starts, {@link AutoFocusStateListener#onAutoFocusScan} will be 220 * invoked.</p> 221 * 222 * <p>If the active scan succeeds, {@link AutoFocusStateListener#onAutoFocusSuccess} with 223 * {@code locked == true} will be invoked. If the active scan fails, 224 * {@link AutoFocusStateListener#onAutoFocusFail} with {@code scanning == false} will be 225 * invoked.</p> 226 * 227 * <p>After calling this function, submit the new requestBuilder as a separate capture. 228 * Do not submit it as a repeating request or the AF trigger will be repeated every time.</p> 229 * 230 * <p>Create a new repeating request from repeatingBuilder and set that as the updated 231 * repeating request.</p> 232 * 233 * @param repeatingBuilder Builder for a repeating request. 234 * @param requestBuilder Builder for a non-repeating request. 235 * 236 * @param repeatingBuilder Builder for a repeating request. 237 */ 238 public synchronized void setActiveAutoFocus(CaptureRequest.Builder repeatingBuilder, 239 CaptureRequest.Builder requestBuilder) { 240 if (VERBOSE_LOGGING) Log.v(TAG, "setActiveAutoFocus"); 241 242 mCurrentAfMode = CaptureRequest.CONTROL_AF_MODE_AUTO; 243 244 repeatingBuilder.set(CaptureRequest.CONTROL_AF_MODE, mCurrentAfMode); 245 requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, mCurrentAfMode); 246 247 repeatingBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, 248 CaptureRequest.CONTROL_AF_TRIGGER_IDLE); 249 requestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, 250 CaptureRequest.CONTROL_AF_TRIGGER_START); 251 } 252 253 /** 254 * Enable passive autofocus, immediately triggering a non-converging scan. 255 * 256 * <p>While passive autofocus is enabled, use {@link #lockAutoFocus} to lock 257 * the lens before taking a picture. Once a picture is taken, use {@link #unlockAutoFocus} 258 * to let the lens go back into passive scanning.</p> 259 * 260 * <p>Once passive AF scanning starts, {@link AutoFocusStateListener#onAutoFocusScan} will be 261 * invoked.</p> 262 * 263 * @param repeatingBuilder Builder for a repeating request. 264 * @param picture True for still capture AF, false for video AF. 265 */ 266 public synchronized void setPassiveAutoFocus(boolean picture, 267 CaptureRequest.Builder repeatingBuilder) { 268 if (VERBOSE_LOGGING) Log.v(TAG, "setPassiveAutoFocus - picture " + picture); 269 270 if (picture) { 271 mCurrentAfMode = CaptureResult.CONTROL_AF_MODE_CONTINUOUS_PICTURE; 272 } else { 273 mCurrentAfMode = CaptureResult.CONTROL_AF_MODE_CONTINUOUS_VIDEO; 274 } 275 276 repeatingBuilder.set(CaptureRequest.CONTROL_AF_MODE, mCurrentAfMode); 277 } 278} 279