blob: 0f41da393c83c6e74970bbb124ebebaf53d91291 [file] [log] [blame]
Michael Kolb8872c232013-01-29 10:33:22 -08001/*
2 * Copyright (C) 2012 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 */
16
17package com.android.camera;
18
19import android.annotation.TargetApi;
20import android.graphics.Matrix;
21import android.graphics.Rect;
22import android.graphics.RectF;
23import android.hardware.Camera.Area;
24import android.hardware.Camera.Parameters;
Sascha Haeberling638e6f02013-09-18 14:28:51 -070025import android.os.Build;
Michael Kolb8872c232013-01-29 10:33:22 -080026import android.os.Handler;
27import android.os.Looper;
28import android.os.Message;
Michael Kolb8872c232013-01-29 10:33:22 -080029
Angus Kong2bca2102014-03-11 16:27:30 -070030import com.android.camera.debug.Log;
Erin Dahlgren357b7672013-11-20 17:38:14 -080031import com.android.camera.settings.SettingsManager;
Doris Liu482de022013-12-18 19:18:16 -080032import com.android.camera.ui.PreviewStatusListener;
Angus Kongb50b5cb2013-08-09 14:55:20 -070033import com.android.camera.util.CameraUtil;
Seth Raphaelcbd82672013-11-05 10:12:36 -080034import com.android.camera.util.UsageStatistics;
Michael Kolb8872c232013-01-29 10:33:22 -080035
Sascha Haeberling638e6f02013-09-18 14:28:51 -070036import java.util.ArrayList;
37import java.util.List;
38
Michael Kolb8872c232013-01-29 10:33:22 -080039/* A class that handles everything about focus in still picture mode.
40 * This also handles the metering area because it is the same as focus area.
41 *
42 * The test cases:
43 * (1) The camera has continuous autofocus. Move the camera. Take a picture when
44 * CAF is not in progress.
45 * (2) The camera has continuous autofocus. Move the camera. Take a picture when
46 * CAF is in progress.
47 * (3) The camera has face detection. Point the camera at some faces. Hold the
48 * shutter. Release to take a picture.
49 * (4) The camera has face detection. Point the camera at some faces. Single tap
50 * the shutter to take a picture.
51 * (5) The camera has autofocus. Single tap the shutter to take a picture.
52 * (6) The camera has autofocus. Hold the shutter. Release to take a picture.
53 * (7) The camera has no autofocus. Single tap the shutter and take a picture.
54 * (8) The camera has autofocus and supports focus area. Touch the screen to
55 * trigger autofocus. Take a picture.
56 * (9) The camera has autofocus and supports focus area. Touch the screen to
57 * trigger autofocus. Wait until it times out.
58 * (10) The camera has no autofocus and supports metering area. Touch the screen
59 * to change metering area.
60 */
Angus Kong2bacca72014-03-06 12:57:29 -080061public class FocusOverlayManager implements PreviewStatusListener.PreviewAreaChangedListener {
Angus Kong2bca2102014-03-11 16:27:30 -070062 private static final Log.Tag TAG = new Log.Tag("FocusOverlayMgr");
Michael Kolb8872c232013-01-29 10:33:22 -080063
64 private static final int RESET_TOUCH_FOCUS = 0;
Kevin Gabayand4a68ca2014-03-24 14:13:12 -070065 private static final int RESET_TOUCH_FOCUS_DELAY = 4000;
Michael Kolb8872c232013-01-29 10:33:22 -080066
67 private int mState = STATE_IDLE;
68 private static final int STATE_IDLE = 0; // Focus is not active.
69 private static final int STATE_FOCUSING = 1; // Focus is in progress.
70 // Focus is in progress and the camera should take a picture after focus finishes.
71 private static final int STATE_FOCUSING_SNAP_ON_FINISH = 2;
72 private static final int STATE_SUCCESS = 3; // Focus finishes and succeeds.
73 private static final int STATE_FAIL = 4; // Focus finishes and fails.
74
75 private boolean mInitialized;
76 private boolean mFocusAreaSupported;
77 private boolean mMeteringAreaSupported;
78 private boolean mLockAeAwbNeeded;
79 private boolean mAeAwbLock;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080080 private final Matrix mMatrix;
Michael Kolb8872c232013-01-29 10:33:22 -080081
Michael Kolb8872c232013-01-29 10:33:22 -080082 private boolean mMirror; // true if the camera is front-facing.
83 private int mDisplayOrientation;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080084 private List<Area> mFocusArea; // focus area in driver format
85 private List<Area> mMeteringArea; // metering area in driver format
Michael Kolb8872c232013-01-29 10:33:22 -080086 private String mFocusMode;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080087 private final String[] mDefaultFocusModes;
Michael Kolb8872c232013-01-29 10:33:22 -080088 private String mOverrideFocusMode;
89 private Parameters mParameters;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080090 private final SettingsManager mSettingsManager;
91 private final Handler mHandler;
Michael Kolb8872c232013-01-29 10:33:22 -080092 Listener mListener;
Michael Kolbe3de7222013-02-18 15:16:44 -080093 private boolean mPreviousMoving;
Michael Kolb8872c232013-01-29 10:33:22 -080094
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080095 private final FocusUI mUI;
Doris Liu36ebcb12013-10-28 14:44:24 -070096 private final Rect mPreviewRect = new Rect(0, 0, 0, 0);
Michael Kolbd6954f32013-03-08 20:43:01 -080097
98 public interface FocusUI {
99 public boolean hasFaces();
100 public void clearFocus();
Doris Liu10a035c2014-02-13 14:26:09 -0800101 public void setFocusPosition(int x, int y, boolean isAutoFocus);
Michael Kolbd6954f32013-03-08 20:43:01 -0800102 public void onFocusStarted();
Sascha Haeberlinge2914fd2014-01-17 19:03:52 -0800103 public void onFocusSucceeded();
104 public void onFocusFailed();
Michael Kolbd6954f32013-03-08 20:43:01 -0800105 public void pauseFaceDetection();
106 public void resumeFaceDetection();
107 }
108
Michael Kolb8872c232013-01-29 10:33:22 -0800109 public interface Listener {
110 public void autoFocus();
111 public void cancelAutoFocus();
112 public boolean capture();
113 public void startFaceDetection();
114 public void stopFaceDetection();
115 public void setFocusParameters();
116 }
117
118 private class MainHandler extends Handler {
119 public MainHandler(Looper looper) {
120 super(looper);
121 }
122
123 @Override
124 public void handleMessage(Message msg) {
125 switch (msg.what) {
126 case RESET_TOUCH_FOCUS: {
127 cancelAutoFocus();
128 mListener.startFaceDetection();
129 break;
130 }
131 }
132 }
133 }
134
Erin Dahlgren357b7672013-11-20 17:38:14 -0800135 public FocusOverlayManager(SettingsManager settingsManager,
136 String[] defaultFocusModes,
Michael Kolb8872c232013-01-29 10:33:22 -0800137 Parameters parameters, Listener listener,
Michael Kolbd6954f32013-03-08 20:43:01 -0800138 boolean mirror, Looper looper, FocusUI ui) {
Erin Dahlgren357b7672013-11-20 17:38:14 -0800139 mSettingsManager = settingsManager;
Michael Kolb8872c232013-01-29 10:33:22 -0800140 mHandler = new MainHandler(looper);
141 mMatrix = new Matrix();
Michael Kolb8872c232013-01-29 10:33:22 -0800142 mDefaultFocusModes = defaultFocusModes;
143 setParameters(parameters);
144 mListener = listener;
145 setMirror(mirror);
Michael Kolbd6954f32013-03-08 20:43:01 -0800146 mUI = ui;
Michael Kolb8872c232013-01-29 10:33:22 -0800147 }
148
149 public void setParameters(Parameters parameters) {
150 // parameters can only be null when onConfigurationChanged is called
151 // before camera is open. We will just return in this case, because
152 // parameters will be set again later with the right parameters after
153 // camera is open.
154 if (parameters == null) return;
155 mParameters = parameters;
Angus Kongb50b5cb2013-08-09 14:55:20 -0700156 mFocusAreaSupported = CameraUtil.isFocusAreaSupported(parameters);
157 mMeteringAreaSupported = CameraUtil.isMeteringAreaSupported(parameters);
158 mLockAeAwbNeeded = (CameraUtil.isAutoExposureLockSupported(mParameters) ||
159 CameraUtil.isAutoWhiteBalanceLockSupported(mParameters));
Michael Kolb8872c232013-01-29 10:33:22 -0800160 }
161
Doris Liu36ebcb12013-10-28 14:44:24 -0700162 /** This setter should be the only way to mutate mPreviewRect. */
163 public void setPreviewRect(Rect previewRect) {
164 if (!mPreviewRect.equals(previewRect)) {
165 mPreviewRect.set(previewRect);
Michael Kolb8872c232013-01-29 10:33:22 -0800166 setMatrix();
167 }
168 }
169
Doris Liu482de022013-12-18 19:18:16 -0800170 @Override
Angus Kong2bacca72014-03-06 12:57:29 -0800171 public void onPreviewAreaChanged(RectF previewArea) {
Doris Liua1ec04a2014-01-13 17:29:40 -0800172 setPreviewRect(CameraUtil.rectFToRect(previewArea));
Doris Liu482de022013-12-18 19:18:16 -0800173 }
174
Doris Liu36ebcb12013-10-28 14:44:24 -0700175 /** Returns a copy of mPreviewRect so that outside class cannot modify preview
176 * rect except deliberately doing so through the setter. */
177 public Rect getPreviewRect() {
178 return new Rect(mPreviewRect);
179 }
180
Michael Kolb8872c232013-01-29 10:33:22 -0800181 public void setMirror(boolean mirror) {
182 mMirror = mirror;
183 setMatrix();
184 }
185
186 public void setDisplayOrientation(int displayOrientation) {
187 mDisplayOrientation = displayOrientation;
188 setMatrix();
189 }
190
Michael Kolb8872c232013-01-29 10:33:22 -0800191 private void setMatrix() {
Doris Liu36ebcb12013-10-28 14:44:24 -0700192 if (mPreviewRect.width() != 0 && mPreviewRect.height() != 0) {
Michael Kolb8872c232013-01-29 10:33:22 -0800193 Matrix matrix = new Matrix();
Doris Liu36ebcb12013-10-28 14:44:24 -0700194 CameraUtil.prepareMatrix(matrix, mMirror, mDisplayOrientation, getPreviewRect());
Michael Kolb8872c232013-01-29 10:33:22 -0800195 // In face detection, the matrix converts the driver coordinates to UI
196 // coordinates. In tap focus, the inverted matrix converts the UI
197 // coordinates to driver coordinates.
198 matrix.invert(mMatrix);
Michael Kolbd6954f32013-03-08 20:43:01 -0800199 mInitialized = true;
Michael Kolb8872c232013-01-29 10:33:22 -0800200 }
201 }
202
203 private void lockAeAwbIfNeeded() {
204 if (mLockAeAwbNeeded && !mAeAwbLock) {
205 mAeAwbLock = true;
206 mListener.setFocusParameters();
207 }
208 }
209
210 private void unlockAeAwbIfNeeded() {
211 if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) {
212 mAeAwbLock = false;
213 mListener.setFocusParameters();
214 }
215 }
216
Michael Kolb8872c232013-01-29 10:33:22 -0800217 public void onShutterUp() {
218 if (!mInitialized) return;
219
220 if (needAutoFocusCall()) {
221 // User releases half-pressed focus key.
222 if (mState == STATE_FOCUSING || mState == STATE_SUCCESS
223 || mState == STATE_FAIL) {
224 cancelAutoFocus();
225 }
226 }
227
228 // Unlock AE and AWB after cancelAutoFocus. Camera API does not
229 // guarantee setParameters can be called during autofocus.
230 unlockAeAwbIfNeeded();
231 }
232
Angus Kongeaaf56d2014-02-20 11:59:10 -0800233 public void focusAndCapture() {
Michael Kolb8872c232013-01-29 10:33:22 -0800234 if (!mInitialized) return;
235
Angus Kongeaaf56d2014-02-20 11:59:10 -0800236 if (!needAutoFocusCall()) {
237 // Focus is not needed.
238 capture();
239 } else if (mState == STATE_SUCCESS || mState == STATE_FAIL) {
240 // Focus is done already.
Michael Kolb8872c232013-01-29 10:33:22 -0800241 capture();
242 } else if (mState == STATE_FOCUSING) {
Angus Kongeaaf56d2014-02-20 11:59:10 -0800243 // Still focusing and will not trigger snap upon finish.
Michael Kolb8872c232013-01-29 10:33:22 -0800244 mState = STATE_FOCUSING_SNAP_ON_FINISH;
245 } else if (mState == STATE_IDLE) {
Angus Kongeaaf56d2014-02-20 11:59:10 -0800246 autoFocusAndCapture();
Michael Kolb8872c232013-01-29 10:33:22 -0800247 }
248 }
249
250 public void onAutoFocus(boolean focused, boolean shutterButtonPressed) {
251 if (mState == STATE_FOCUSING_SNAP_ON_FINISH) {
252 // Take the picture no matter focus succeeds or fails. No need
253 // to play the AF sound if we're about to play the shutter
254 // sound.
255 if (focused) {
256 mState = STATE_SUCCESS;
257 } else {
258 mState = STATE_FAIL;
259 }
260 updateFocusUI();
261 capture();
262 } else if (mState == STATE_FOCUSING) {
263 // This happens when (1) user is half-pressing the focus key or
264 // (2) touch focus is triggered. Play the focus tone. Do not
265 // take the picture now.
266 if (focused) {
267 mState = STATE_SUCCESS;
268 } else {
269 mState = STATE_FAIL;
270 }
271 updateFocusUI();
272 // If this is triggered by touch focus, cancel focus after a
273 // while.
Michael Kolbb0579432013-07-11 13:48:15 -0700274 if (mFocusArea != null) {
Michael Kolb8872c232013-01-29 10:33:22 -0800275 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
276 }
277 if (shutterButtonPressed) {
278 // Lock AE & AWB so users can half-press shutter and recompose.
279 lockAeAwbIfNeeded();
280 }
281 } else if (mState == STATE_IDLE) {
282 // User has released the focus key before focus completes.
283 // Do nothing.
284 }
285 }
286
287 public void onAutoFocusMoving(boolean moving) {
288 if (!mInitialized) return;
Michael Kolbd6954f32013-03-08 20:43:01 -0800289
290
Michael Kolb8872c232013-01-29 10:33:22 -0800291 // Ignore if the camera has detected some faces.
Michael Kolbd6954f32013-03-08 20:43:01 -0800292 if (mUI.hasFaces()) {
293 mUI.clearFocus();
Michael Kolb8872c232013-01-29 10:33:22 -0800294 return;
295 }
296
297 // Ignore if we have requested autofocus. This method only handles
298 // continuous autofocus.
299 if (mState != STATE_IDLE) return;
300
Michael Kolbe3de7222013-02-18 15:16:44 -0800301 // animate on false->true trasition only b/8219520
302 if (moving && !mPreviousMoving) {
Doris Liuca4a5662014-01-02 17:40:12 -0800303 // Auto focus at the center of the preview.
Doris Liu10a035c2014-02-13 14:26:09 -0800304 mUI.setFocusPosition(mPreviewRect.centerX(), mPreviewRect.centerY(), true);
Michael Kolbd6954f32013-03-08 20:43:01 -0800305 mUI.onFocusStarted();
Michael Kolbe3de7222013-02-18 15:16:44 -0800306 } else if (!moving) {
Sascha Haeberlinge2914fd2014-01-17 19:03:52 -0800307 mUI.onFocusSucceeded();
Michael Kolb8872c232013-01-29 10:33:22 -0800308 }
Michael Kolbe3de7222013-02-18 15:16:44 -0800309 mPreviousMoving = moving;
Michael Kolb8872c232013-01-29 10:33:22 -0800310 }
311
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700312 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
Michael Kolb0718d482013-02-16 13:13:47 -0800313 private void initializeFocusAreas(int x, int y) {
Michael Kolb8872c232013-01-29 10:33:22 -0800314 if (mFocusArea == null) {
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800315 mFocusArea = new ArrayList<Area>();
Michael Kolb8872c232013-01-29 10:33:22 -0800316 mFocusArea.add(new Area(new Rect(), 1));
317 }
318
319 // Convert the coordinates to driver format.
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800320 calculateTapArea(x, y, 1f, mFocusArea.get(0).rect);
Michael Kolb8872c232013-01-29 10:33:22 -0800321 }
322
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700323 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
Michael Kolb0718d482013-02-16 13:13:47 -0800324 private void initializeMeteringAreas(int x, int y) {
Michael Kolb8872c232013-01-29 10:33:22 -0800325 if (mMeteringArea == null) {
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800326 mMeteringArea = new ArrayList<Area>();
Michael Kolb8872c232013-01-29 10:33:22 -0800327 mMeteringArea.add(new Area(new Rect(), 1));
328 }
329
330 // Convert the coordinates to driver format.
331 // AE area is bigger because exposure is sensitive and
332 // easy to over- or underexposure if area is too small.
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800333 calculateTapArea(x, y, 1.5f, mMeteringArea.get(0).rect);
Michael Kolb8872c232013-01-29 10:33:22 -0800334 }
335
336 public void onSingleTapUp(int x, int y) {
337 if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) return;
338
Seth Raphael5e09d012013-12-18 13:45:03 -0800339 UsageStatistics.tapToFocus();
Seth Raphaelcbd82672013-11-05 10:12:36 -0800340
Michael Kolb8872c232013-01-29 10:33:22 -0800341 // Let users be able to cancel previous touch focus.
Michael Kolbb0579432013-07-11 13:48:15 -0700342 if ((mFocusArea != null) && (mState == STATE_FOCUSING ||
Michael Kolb8872c232013-01-29 10:33:22 -0800343 mState == STATE_SUCCESS || mState == STATE_FAIL)) {
344 cancelAutoFocus();
345 }
Doris Liu36ebcb12013-10-28 14:44:24 -0700346 if (mPreviewRect.width() == 0 || mPreviewRect.height() == 0) return;
Michael Kolbb0579432013-07-11 13:48:15 -0700347 // Initialize variables.
Michael Kolb8872c232013-01-29 10:33:22 -0800348 // Initialize mFocusArea.
349 if (mFocusAreaSupported) {
Michael Kolb0718d482013-02-16 13:13:47 -0800350 initializeFocusAreas(x, y);
Michael Kolb8872c232013-01-29 10:33:22 -0800351 }
352 // Initialize mMeteringArea.
353 if (mMeteringAreaSupported) {
Michael Kolb0718d482013-02-16 13:13:47 -0800354 initializeMeteringAreas(x, y);
Michael Kolb8872c232013-01-29 10:33:22 -0800355 }
356
357 // Use margin to set the focus indicator to the touched area.
Doris Liu10a035c2014-02-13 14:26:09 -0800358 mUI.setFocusPosition(x, y, false);
Michael Kolb8872c232013-01-29 10:33:22 -0800359
360 // Stop face detection because we want to specify focus and metering area.
361 mListener.stopFaceDetection();
362
363 // Set the focus area and metering area.
364 mListener.setFocusParameters();
365 if (mFocusAreaSupported) {
366 autoFocus();
367 } else { // Just show the indicator in all other cases.
368 updateFocusUI();
Kevin Gabayand4a68ca2014-03-24 14:13:12 -0700369 // Reset the metering area in 4 seconds.
Michael Kolb8872c232013-01-29 10:33:22 -0800370 mHandler.removeMessages(RESET_TOUCH_FOCUS);
371 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
372 }
373 }
374
375 public void onPreviewStarted() {
376 mState = STATE_IDLE;
377 }
378
379 public void onPreviewStopped() {
380 // If auto focus was in progress, it would have been stopped.
381 mState = STATE_IDLE;
382 resetTouchFocus();
383 updateFocusUI();
384 }
385
386 public void onCameraReleased() {
387 onPreviewStopped();
388 }
389
Angus Kongeaaf56d2014-02-20 11:59:10 -0800390 /**
391 * Triggers the autofocus and sets the specified state.
392 *
393 * @param focusingState The state to use when focus is in progress.
394 */
395 private void autoFocus(int focusingState) {
Michael Kolb8872c232013-01-29 10:33:22 -0800396 Log.v(TAG, "Start autofocus.");
397 mListener.autoFocus();
Angus Kongeaaf56d2014-02-20 11:59:10 -0800398 mState = focusingState;
Michael Kolb8872c232013-01-29 10:33:22 -0800399 // Pause the face view because the driver will keep sending face
400 // callbacks after the focus completes.
Michael Kolbd6954f32013-03-08 20:43:01 -0800401 mUI.pauseFaceDetection();
Michael Kolb8872c232013-01-29 10:33:22 -0800402 updateFocusUI();
403 mHandler.removeMessages(RESET_TOUCH_FOCUS);
404 }
405
Angus Kongeaaf56d2014-02-20 11:59:10 -0800406 /**
407 * Triggers the autofocus and set the state to indicate the focus is in
408 * progress.
409 */
410 private void autoFocus() {
411 autoFocus(STATE_FOCUSING);
412 }
413
414 /**
415 * Triggers the autofocus and set the state to which a capture will happen
416 * in the following autofocus callback.
417 */
418 private void autoFocusAndCapture() {
419 autoFocus(STATE_FOCUSING_SNAP_ON_FINISH);
420 }
421
Michael Kolb8872c232013-01-29 10:33:22 -0800422 private void cancelAutoFocus() {
423 Log.v(TAG, "Cancel autofocus.");
Michael Kolb8872c232013-01-29 10:33:22 -0800424 // Reset the tap area before calling mListener.cancelAutofocus.
425 // Otherwise, focus mode stays at auto and the tap area passed to the
426 // driver is not reset.
427 resetTouchFocus();
428 mListener.cancelAutoFocus();
Michael Kolbd6954f32013-03-08 20:43:01 -0800429 mUI.resumeFaceDetection();
Michael Kolb8872c232013-01-29 10:33:22 -0800430 mState = STATE_IDLE;
431 updateFocusUI();
432 mHandler.removeMessages(RESET_TOUCH_FOCUS);
433 }
434
435 private void capture() {
436 if (mListener.capture()) {
437 mState = STATE_IDLE;
438 mHandler.removeMessages(RESET_TOUCH_FOCUS);
439 }
440 }
441
442 public String getFocusMode() {
443 if (mOverrideFocusMode != null) return mOverrideFocusMode;
Michael Kolb4a40e122013-02-14 08:30:59 -0800444 if (mParameters == null) return Parameters.FOCUS_MODE_AUTO;
Michael Kolb8872c232013-01-29 10:33:22 -0800445 List<String> supportedFocusModes = mParameters.getSupportedFocusModes();
446
Michael Kolbb0579432013-07-11 13:48:15 -0700447 if (mFocusAreaSupported && mFocusArea != null) {
Michael Kolb8872c232013-01-29 10:33:22 -0800448 // Always use autofocus in tap-to-focus.
449 mFocusMode = Parameters.FOCUS_MODE_AUTO;
450 } else {
451 // The default is continuous autofocus.
Erin Dahlgren635a4b82013-11-25 15:21:18 -0800452 mFocusMode = mSettingsManager.get(SettingsManager.SETTING_FOCUS_MODE);
Michael Kolb8872c232013-01-29 10:33:22 -0800453 // Try to find a supported focus mode from the default list.
454 if (mFocusMode == null) {
455 for (int i = 0; i < mDefaultFocusModes.length; i++) {
456 String mode = mDefaultFocusModes[i];
Angus Kongb50b5cb2013-08-09 14:55:20 -0700457 if (CameraUtil.isSupported(mode, supportedFocusModes)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800458 mFocusMode = mode;
459 break;
460 }
461 }
462 }
463 }
Angus Kongb50b5cb2013-08-09 14:55:20 -0700464 if (!CameraUtil.isSupported(mFocusMode, supportedFocusModes)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800465 // For some reasons, the driver does not support the current
466 // focus mode. Fall back to auto.
Angus Kongb50b5cb2013-08-09 14:55:20 -0700467 if (CameraUtil.isSupported(Parameters.FOCUS_MODE_AUTO,
Michael Kolb8872c232013-01-29 10:33:22 -0800468 mParameters.getSupportedFocusModes())) {
469 mFocusMode = Parameters.FOCUS_MODE_AUTO;
470 } else {
471 mFocusMode = mParameters.getFocusMode();
472 }
473 }
474 return mFocusMode;
475 }
476
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800477 public List<Area> getFocusAreas() {
Michael Kolb8872c232013-01-29 10:33:22 -0800478 return mFocusArea;
479 }
480
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800481 public List<Area> getMeteringAreas() {
Michael Kolb8872c232013-01-29 10:33:22 -0800482 return mMeteringArea;
483 }
484
485 public void updateFocusUI() {
486 if (!mInitialized) return;
487 // Show only focus indicator or face indicator.
Michael Kolb8872c232013-01-29 10:33:22 -0800488
489 if (mState == STATE_IDLE) {
Michael Kolbb0579432013-07-11 13:48:15 -0700490 if (mFocusArea == null) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800491 mUI.clearFocus();
Michael Kolb8872c232013-01-29 10:33:22 -0800492 } else {
493 // Users touch on the preview and the indicator represents the
494 // metering area. Either focus area is not supported or
495 // autoFocus call is not required.
Michael Kolbd6954f32013-03-08 20:43:01 -0800496 mUI.onFocusStarted();
Michael Kolb8872c232013-01-29 10:33:22 -0800497 }
498 } else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800499 mUI.onFocusStarted();
Michael Kolb8872c232013-01-29 10:33:22 -0800500 } else {
Angus Kongb50b5cb2013-08-09 14:55:20 -0700501 if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800502 // TODO: check HAL behavior and decide if this can be removed.
Sascha Haeberlinge2914fd2014-01-17 19:03:52 -0800503 mUI.onFocusSucceeded();
Michael Kolb8872c232013-01-29 10:33:22 -0800504 } else if (mState == STATE_SUCCESS) {
Sascha Haeberlinge2914fd2014-01-17 19:03:52 -0800505 mUI.onFocusSucceeded();
Michael Kolb8872c232013-01-29 10:33:22 -0800506 } else if (mState == STATE_FAIL) {
Sascha Haeberlinge2914fd2014-01-17 19:03:52 -0800507 mUI.onFocusFailed();
Michael Kolb8872c232013-01-29 10:33:22 -0800508 }
509 }
510 }
511
512 public void resetTouchFocus() {
513 if (!mInitialized) return;
514
515 // Put focus indicator to the center. clear reset position
Michael Kolbd6954f32013-03-08 20:43:01 -0800516 mUI.clearFocus();
Michael Kolb0718d482013-02-16 13:13:47 -0800517 // Initialize mFocusArea.
Michael Kolbb0579432013-07-11 13:48:15 -0700518 mFocusArea = null;
519 mMeteringArea = null;
Michael Kolb8872c232013-01-29 10:33:22 -0800520 }
521
Michael Kolb0718d482013-02-16 13:13:47 -0800522 private void calculateTapArea(int x, int y, float areaMultiple, Rect rect) {
Doris Liub3749f22013-09-25 12:22:08 -0700523 int areaSize = (int) (getAreaSize() * areaMultiple);
Doris Liu36ebcb12013-10-28 14:44:24 -0700524 int left = CameraUtil.clamp(x - areaSize / 2, mPreviewRect.left,
525 mPreviewRect.right - areaSize);
526 int top = CameraUtil.clamp(y - areaSize / 2, mPreviewRect.top,
527 mPreviewRect.bottom - areaSize);
Michael Kolb8872c232013-01-29 10:33:22 -0800528
Doris Liub3749f22013-09-25 12:22:08 -0700529 RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
Michael Kolb8872c232013-01-29 10:33:22 -0800530 mMatrix.mapRect(rectF);
Angus Kongb50b5cb2013-08-09 14:55:20 -0700531 CameraUtil.rectFToRect(rectF, rect);
Michael Kolb8872c232013-01-29 10:33:22 -0800532 }
533
Doris Liub3749f22013-09-25 12:22:08 -0700534 private int getAreaSize() {
535 // Recommended focus area size from the manufacture is 1/8 of the image
Doris Liu2ba03262013-09-26 12:32:38 -0700536 // width (i.e. longer edge of the image)
Doris Liu36ebcb12013-10-28 14:44:24 -0700537 return Math.max(mPreviewRect.width(), mPreviewRect.height()) / 8;
Doris Liub3749f22013-09-25 12:22:08 -0700538 }
539
Michael Kolb8872c232013-01-29 10:33:22 -0800540 /* package */ int getFocusState() {
541 return mState;
542 }
543
544 public boolean isFocusCompleted() {
545 return mState == STATE_SUCCESS || mState == STATE_FAIL;
546 }
547
548 public boolean isFocusingSnapOnFinish() {
549 return mState == STATE_FOCUSING_SNAP_ON_FINISH;
550 }
551
552 public void removeMessages() {
553 mHandler.removeMessages(RESET_TOUCH_FOCUS);
554 }
555
556 public void overrideFocusMode(String focusMode) {
557 mOverrideFocusMode = focusMode;
558 }
559
560 public void setAeAwbLock(boolean lock) {
561 mAeAwbLock = lock;
562 }
563
564 public boolean getAeAwbLock() {
565 return mAeAwbLock;
566 }
567
568 private boolean needAutoFocusCall() {
569 String focusMode = getFocusMode();
570 return !(focusMode.equals(Parameters.FOCUS_MODE_INFINITY)
571 || focusMode.equals(Parameters.FOCUS_MODE_FIXED)
572 || focusMode.equals(Parameters.FOCUS_MODE_EDOF));
573 }
574}