blob: fa7e9653ec967468505a5609b2d8a1c943c62ac7 [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 Kong88289042014-04-22 16:39:42 -070030import com.android.camera.cameradevice.CameraCapabilities;
31import com.android.camera.cameradevice.CameraCapabilitiesFactory;
Angus Kong5596b4c2014-03-11 16:27:30 -070032import com.android.camera.debug.Log;
Erin Dahlgren357b7672013-11-20 17:38:14 -080033import com.android.camera.settings.SettingsManager;
Doris Liu482de022013-12-18 19:18:16 -080034import com.android.camera.ui.PreviewStatusListener;
Angus Kongb50b5cb2013-08-09 14:55:20 -070035import com.android.camera.util.CameraUtil;
Michael Kolb8872c232013-01-29 10:33:22 -080036
Sascha Haeberling638e6f02013-09-18 14:28:51 -070037import java.util.ArrayList;
38import java.util.List;
39
Michael Kolb8872c232013-01-29 10:33:22 -080040/* A class that handles everything about focus in still picture mode.
41 * This also handles the metering area because it is the same as focus area.
42 *
43 * The test cases:
44 * (1) The camera has continuous autofocus. Move the camera. Take a picture when
45 * CAF is not in progress.
46 * (2) The camera has continuous autofocus. Move the camera. Take a picture when
47 * CAF is in progress.
48 * (3) The camera has face detection. Point the camera at some faces. Hold the
49 * shutter. Release to take a picture.
50 * (4) The camera has face detection. Point the camera at some faces. Single tap
51 * the shutter to take a picture.
52 * (5) The camera has autofocus. Single tap the shutter to take a picture.
53 * (6) The camera has autofocus. Hold the shutter. Release to take a picture.
54 * (7) The camera has no autofocus. Single tap the shutter and take a picture.
55 * (8) The camera has autofocus and supports focus area. Touch the screen to
56 * trigger autofocus. Take a picture.
57 * (9) The camera has autofocus and supports focus area. Touch the screen to
58 * trigger autofocus. Wait until it times out.
59 * (10) The camera has no autofocus and supports metering area. Touch the screen
60 * to change metering area.
61 */
Angus Kong2bacca72014-03-06 12:57:29 -080062public class FocusOverlayManager implements PreviewStatusListener.PreviewAreaChangedListener {
Angus Kong5596b4c2014-03-11 16:27:30 -070063 private static final Log.Tag TAG = new Log.Tag("FocusOverlayMgr");
Michael Kolb8872c232013-01-29 10:33:22 -080064
65 private static final int RESET_TOUCH_FOCUS = 0;
Kevin Gabayand4a68ca2014-03-24 14:13:12 -070066 private static final int RESET_TOUCH_FOCUS_DELAY = 4000;
Michael Kolb8872c232013-01-29 10:33:22 -080067
68 private int mState = STATE_IDLE;
69 private static final int STATE_IDLE = 0; // Focus is not active.
70 private static final int STATE_FOCUSING = 1; // Focus is in progress.
71 // Focus is in progress and the camera should take a picture after focus finishes.
72 private static final int STATE_FOCUSING_SNAP_ON_FINISH = 2;
73 private static final int STATE_SUCCESS = 3; // Focus finishes and succeeds.
74 private static final int STATE_FAIL = 4; // Focus finishes and fails.
75
76 private boolean mInitialized;
77 private boolean mFocusAreaSupported;
78 private boolean mMeteringAreaSupported;
79 private boolean mLockAeAwbNeeded;
80 private boolean mAeAwbLock;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080081 private final Matrix mMatrix;
Michael Kolb8872c232013-01-29 10:33:22 -080082
Michael Kolb8872c232013-01-29 10:33:22 -080083 private boolean mMirror; // true if the camera is front-facing.
84 private int mDisplayOrientation;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080085 private List<Area> mFocusArea; // focus area in driver format
86 private List<Area> mMeteringArea; // metering area in driver format
Michael Kolb8872c232013-01-29 10:33:22 -080087 private String mFocusMode;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080088 private final String[] mDefaultFocusModes;
Michael Kolb8872c232013-01-29 10:33:22 -080089 private String mOverrideFocusMode;
90 private Parameters mParameters;
Angus Kong88289042014-04-22 16:39:42 -070091 private CameraCapabilities mCapabilities;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080092 private final SettingsManager mSettingsManager;
93 private final Handler mHandler;
Michael Kolb8872c232013-01-29 10:33:22 -080094 Listener mListener;
Michael Kolbe3de7222013-02-18 15:16:44 -080095 private boolean mPreviousMoving;
Michael Kolb8872c232013-01-29 10:33:22 -080096
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080097 private final FocusUI mUI;
Doris Liu36ebcb12013-10-28 14:44:24 -070098 private final Rect mPreviewRect = new Rect(0, 0, 0, 0);
Michael Kolbd6954f32013-03-08 20:43:01 -080099
100 public interface FocusUI {
101 public boolean hasFaces();
102 public void clearFocus();
Doris Liu10a035c2014-02-13 14:26:09 -0800103 public void setFocusPosition(int x, int y, boolean isAutoFocus);
Michael Kolbd6954f32013-03-08 20:43:01 -0800104 public void onFocusStarted();
Sascha Haeberlinge2914fd2014-01-17 19:03:52 -0800105 public void onFocusSucceeded();
106 public void onFocusFailed();
Michael Kolbd6954f32013-03-08 20:43:01 -0800107 public void pauseFaceDetection();
108 public void resumeFaceDetection();
109 }
110
Michael Kolb8872c232013-01-29 10:33:22 -0800111 public interface Listener {
112 public void autoFocus();
113 public void cancelAutoFocus();
114 public boolean capture();
115 public void startFaceDetection();
116 public void stopFaceDetection();
117 public void setFocusParameters();
118 }
119
120 private class MainHandler extends Handler {
121 public MainHandler(Looper looper) {
122 super(looper);
123 }
124
125 @Override
126 public void handleMessage(Message msg) {
127 switch (msg.what) {
128 case RESET_TOUCH_FOCUS: {
129 cancelAutoFocus();
130 mListener.startFaceDetection();
131 break;
132 }
133 }
134 }
135 }
136
Erin Dahlgren357b7672013-11-20 17:38:14 -0800137 public FocusOverlayManager(SettingsManager settingsManager,
138 String[] defaultFocusModes,
Michael Kolb8872c232013-01-29 10:33:22 -0800139 Parameters parameters, Listener listener,
Michael Kolbd6954f32013-03-08 20:43:01 -0800140 boolean mirror, Looper looper, FocusUI ui) {
Erin Dahlgren357b7672013-11-20 17:38:14 -0800141 mSettingsManager = settingsManager;
Michael Kolb8872c232013-01-29 10:33:22 -0800142 mHandler = new MainHandler(looper);
143 mMatrix = new Matrix();
Michael Kolb8872c232013-01-29 10:33:22 -0800144 mDefaultFocusModes = defaultFocusModes;
Angus Kong88289042014-04-22 16:39:42 -0700145 // TODO: Pass in the capabilities directly.
146 setParameters(parameters, CameraCapabilitiesFactory.createFrom(parameters));
Michael Kolb8872c232013-01-29 10:33:22 -0800147 mListener = listener;
148 setMirror(mirror);
Michael Kolbd6954f32013-03-08 20:43:01 -0800149 mUI = ui;
Michael Kolb8872c232013-01-29 10:33:22 -0800150 }
151
Angus Kong88289042014-04-22 16:39:42 -0700152 public void setParameters(Parameters parameters, CameraCapabilities capabilities) {
Michael Kolb8872c232013-01-29 10:33:22 -0800153 // parameters can only be null when onConfigurationChanged is called
154 // before camera is open. We will just return in this case, because
155 // parameters will be set again later with the right parameters after
156 // camera is open.
157 if (parameters == null) return;
158 mParameters = parameters;
Angus Kong88289042014-04-22 16:39:42 -0700159 mCapabilities = capabilities;
160 mFocusAreaSupported = mCapabilities.supports(CameraCapabilities.Feature.FOCUS_AREA);
161 mMeteringAreaSupported = mCapabilities.supports(CameraCapabilities.Feature.METERING_AREA);
162 mLockAeAwbNeeded = (mCapabilities.supports(CameraCapabilities.Feature.AUTO_EXPOSURE_LOCK)
163 || mCapabilities.supports(CameraCapabilities.Feature.AUTO_WHITE_BALANCE_LOCK));
Michael Kolb8872c232013-01-29 10:33:22 -0800164 }
165
Doris Liu36ebcb12013-10-28 14:44:24 -0700166 /** This setter should be the only way to mutate mPreviewRect. */
167 public void setPreviewRect(Rect previewRect) {
168 if (!mPreviewRect.equals(previewRect)) {
169 mPreviewRect.set(previewRect);
Michael Kolb8872c232013-01-29 10:33:22 -0800170 setMatrix();
171 }
172 }
173
Doris Liu482de022013-12-18 19:18:16 -0800174 @Override
Angus Kong2bacca72014-03-06 12:57:29 -0800175 public void onPreviewAreaChanged(RectF previewArea) {
Doris Liua1ec04a2014-01-13 17:29:40 -0800176 setPreviewRect(CameraUtil.rectFToRect(previewArea));
Doris Liu482de022013-12-18 19:18:16 -0800177 }
178
Doris Liu36ebcb12013-10-28 14:44:24 -0700179 /** Returns a copy of mPreviewRect so that outside class cannot modify preview
180 * rect except deliberately doing so through the setter. */
181 public Rect getPreviewRect() {
182 return new Rect(mPreviewRect);
183 }
184
Michael Kolb8872c232013-01-29 10:33:22 -0800185 public void setMirror(boolean mirror) {
186 mMirror = mirror;
187 setMatrix();
188 }
189
190 public void setDisplayOrientation(int displayOrientation) {
191 mDisplayOrientation = displayOrientation;
192 setMatrix();
193 }
194
Michael Kolb8872c232013-01-29 10:33:22 -0800195 private void setMatrix() {
Doris Liu36ebcb12013-10-28 14:44:24 -0700196 if (mPreviewRect.width() != 0 && mPreviewRect.height() != 0) {
Michael Kolb8872c232013-01-29 10:33:22 -0800197 Matrix matrix = new Matrix();
Doris Liu36ebcb12013-10-28 14:44:24 -0700198 CameraUtil.prepareMatrix(matrix, mMirror, mDisplayOrientation, getPreviewRect());
Michael Kolb8872c232013-01-29 10:33:22 -0800199 // In face detection, the matrix converts the driver coordinates to UI
200 // coordinates. In tap focus, the inverted matrix converts the UI
201 // coordinates to driver coordinates.
202 matrix.invert(mMatrix);
Michael Kolbd6954f32013-03-08 20:43:01 -0800203 mInitialized = true;
Michael Kolb8872c232013-01-29 10:33:22 -0800204 }
205 }
206
207 private void lockAeAwbIfNeeded() {
208 if (mLockAeAwbNeeded && !mAeAwbLock) {
209 mAeAwbLock = true;
210 mListener.setFocusParameters();
211 }
212 }
213
214 private void unlockAeAwbIfNeeded() {
215 if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) {
216 mAeAwbLock = false;
217 mListener.setFocusParameters();
218 }
219 }
220
Michael Kolb8872c232013-01-29 10:33:22 -0800221 public void onShutterUp() {
222 if (!mInitialized) return;
223
224 if (needAutoFocusCall()) {
225 // User releases half-pressed focus key.
226 if (mState == STATE_FOCUSING || mState == STATE_SUCCESS
227 || mState == STATE_FAIL) {
228 cancelAutoFocus();
229 }
230 }
231
232 // Unlock AE and AWB after cancelAutoFocus. Camera API does not
233 // guarantee setParameters can be called during autofocus.
234 unlockAeAwbIfNeeded();
235 }
236
Angus Kongeaaf56d2014-02-20 11:59:10 -0800237 public void focusAndCapture() {
Michael Kolb8872c232013-01-29 10:33:22 -0800238 if (!mInitialized) return;
239
Angus Kongeaaf56d2014-02-20 11:59:10 -0800240 if (!needAutoFocusCall()) {
241 // Focus is not needed.
242 capture();
243 } else if (mState == STATE_SUCCESS || mState == STATE_FAIL) {
244 // Focus is done already.
Michael Kolb8872c232013-01-29 10:33:22 -0800245 capture();
246 } else if (mState == STATE_FOCUSING) {
Angus Kongeaaf56d2014-02-20 11:59:10 -0800247 // Still focusing and will not trigger snap upon finish.
Michael Kolb8872c232013-01-29 10:33:22 -0800248 mState = STATE_FOCUSING_SNAP_ON_FINISH;
249 } else if (mState == STATE_IDLE) {
Angus Kongeaaf56d2014-02-20 11:59:10 -0800250 autoFocusAndCapture();
Michael Kolb8872c232013-01-29 10:33:22 -0800251 }
252 }
253
254 public void onAutoFocus(boolean focused, boolean shutterButtonPressed) {
255 if (mState == STATE_FOCUSING_SNAP_ON_FINISH) {
256 // Take the picture no matter focus succeeds or fails. No need
257 // to play the AF sound if we're about to play the shutter
258 // sound.
259 if (focused) {
260 mState = STATE_SUCCESS;
261 } else {
262 mState = STATE_FAIL;
263 }
264 updateFocusUI();
265 capture();
266 } else if (mState == STATE_FOCUSING) {
267 // This happens when (1) user is half-pressing the focus key or
268 // (2) touch focus is triggered. Play the focus tone. Do not
269 // take the picture now.
270 if (focused) {
271 mState = STATE_SUCCESS;
272 } else {
273 mState = STATE_FAIL;
274 }
275 updateFocusUI();
276 // If this is triggered by touch focus, cancel focus after a
277 // while.
Michael Kolbb0579432013-07-11 13:48:15 -0700278 if (mFocusArea != null) {
Michael Kolb8872c232013-01-29 10:33:22 -0800279 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
280 }
281 if (shutterButtonPressed) {
282 // Lock AE & AWB so users can half-press shutter and recompose.
283 lockAeAwbIfNeeded();
284 }
285 } else if (mState == STATE_IDLE) {
286 // User has released the focus key before focus completes.
287 // Do nothing.
288 }
289 }
290
291 public void onAutoFocusMoving(boolean moving) {
292 if (!mInitialized) return;
Michael Kolbd6954f32013-03-08 20:43:01 -0800293
294
Michael Kolb8872c232013-01-29 10:33:22 -0800295 // Ignore if the camera has detected some faces.
Michael Kolbd6954f32013-03-08 20:43:01 -0800296 if (mUI.hasFaces()) {
297 mUI.clearFocus();
Michael Kolb8872c232013-01-29 10:33:22 -0800298 return;
299 }
300
301 // Ignore if we have requested autofocus. This method only handles
302 // continuous autofocus.
303 if (mState != STATE_IDLE) return;
304
Michael Kolbe3de7222013-02-18 15:16:44 -0800305 // animate on false->true trasition only b/8219520
306 if (moving && !mPreviousMoving) {
Doris Liuca4a5662014-01-02 17:40:12 -0800307 // Auto focus at the center of the preview.
Doris Liu10a035c2014-02-13 14:26:09 -0800308 mUI.setFocusPosition(mPreviewRect.centerX(), mPreviewRect.centerY(), true);
Michael Kolbd6954f32013-03-08 20:43:01 -0800309 mUI.onFocusStarted();
Michael Kolbe3de7222013-02-18 15:16:44 -0800310 } else if (!moving) {
Sascha Haeberlinge2914fd2014-01-17 19:03:52 -0800311 mUI.onFocusSucceeded();
Michael Kolb8872c232013-01-29 10:33:22 -0800312 }
Michael Kolbe3de7222013-02-18 15:16:44 -0800313 mPreviousMoving = moving;
Michael Kolb8872c232013-01-29 10:33:22 -0800314 }
315
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700316 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
Michael Kolb0718d482013-02-16 13:13:47 -0800317 private void initializeFocusAreas(int x, int y) {
Michael Kolb8872c232013-01-29 10:33:22 -0800318 if (mFocusArea == null) {
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800319 mFocusArea = new ArrayList<Area>();
Michael Kolb8872c232013-01-29 10:33:22 -0800320 mFocusArea.add(new Area(new Rect(), 1));
321 }
322
323 // Convert the coordinates to driver format.
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800324 calculateTapArea(x, y, 1f, mFocusArea.get(0).rect);
Michael Kolb8872c232013-01-29 10:33:22 -0800325 }
326
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700327 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
Michael Kolb0718d482013-02-16 13:13:47 -0800328 private void initializeMeteringAreas(int x, int y) {
Michael Kolb8872c232013-01-29 10:33:22 -0800329 if (mMeteringArea == null) {
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800330 mMeteringArea = new ArrayList<Area>();
Michael Kolb8872c232013-01-29 10:33:22 -0800331 mMeteringArea.add(new Area(new Rect(), 1));
332 }
333
334 // Convert the coordinates to driver format.
335 // AE area is bigger because exposure is sensitive and
336 // easy to over- or underexposure if area is too small.
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800337 calculateTapArea(x, y, 1.5f, mMeteringArea.get(0).rect);
Michael Kolb8872c232013-01-29 10:33:22 -0800338 }
339
340 public void onSingleTapUp(int x, int y) {
341 if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) return;
342
343 // Let users be able to cancel previous touch focus.
Michael Kolbb0579432013-07-11 13:48:15 -0700344 if ((mFocusArea != null) && (mState == STATE_FOCUSING ||
Michael Kolb8872c232013-01-29 10:33:22 -0800345 mState == STATE_SUCCESS || mState == STATE_FAIL)) {
346 cancelAutoFocus();
347 }
Doris Liu36ebcb12013-10-28 14:44:24 -0700348 if (mPreviewRect.width() == 0 || mPreviewRect.height() == 0) return;
Michael Kolbb0579432013-07-11 13:48:15 -0700349 // Initialize variables.
Michael Kolb8872c232013-01-29 10:33:22 -0800350 // Initialize mFocusArea.
351 if (mFocusAreaSupported) {
Michael Kolb0718d482013-02-16 13:13:47 -0800352 initializeFocusAreas(x, y);
Michael Kolb8872c232013-01-29 10:33:22 -0800353 }
354 // Initialize mMeteringArea.
355 if (mMeteringAreaSupported) {
Michael Kolb0718d482013-02-16 13:13:47 -0800356 initializeMeteringAreas(x, y);
Michael Kolb8872c232013-01-29 10:33:22 -0800357 }
358
359 // Use margin to set the focus indicator to the touched area.
Doris Liu10a035c2014-02-13 14:26:09 -0800360 mUI.setFocusPosition(x, y, false);
Michael Kolb8872c232013-01-29 10:33:22 -0800361
362 // Stop face detection because we want to specify focus and metering area.
363 mListener.stopFaceDetection();
364
365 // Set the focus area and metering area.
366 mListener.setFocusParameters();
367 if (mFocusAreaSupported) {
368 autoFocus();
369 } else { // Just show the indicator in all other cases.
370 updateFocusUI();
Kevin Gabayand4a68ca2014-03-24 14:13:12 -0700371 // Reset the metering area in 4 seconds.
Michael Kolb8872c232013-01-29 10:33:22 -0800372 mHandler.removeMessages(RESET_TOUCH_FOCUS);
373 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
374 }
375 }
376
377 public void onPreviewStarted() {
378 mState = STATE_IDLE;
379 }
380
381 public void onPreviewStopped() {
382 // If auto focus was in progress, it would have been stopped.
383 mState = STATE_IDLE;
384 resetTouchFocus();
385 updateFocusUI();
386 }
387
388 public void onCameraReleased() {
389 onPreviewStopped();
390 }
391
Angus Kongeaaf56d2014-02-20 11:59:10 -0800392 /**
393 * Triggers the autofocus and sets the specified state.
394 *
395 * @param focusingState The state to use when focus is in progress.
396 */
397 private void autoFocus(int focusingState) {
Michael Kolb8872c232013-01-29 10:33:22 -0800398 Log.v(TAG, "Start autofocus.");
399 mListener.autoFocus();
Angus Kongeaaf56d2014-02-20 11:59:10 -0800400 mState = focusingState;
Michael Kolb8872c232013-01-29 10:33:22 -0800401 // Pause the face view because the driver will keep sending face
402 // callbacks after the focus completes.
Michael Kolbd6954f32013-03-08 20:43:01 -0800403 mUI.pauseFaceDetection();
Michael Kolb8872c232013-01-29 10:33:22 -0800404 updateFocusUI();
405 mHandler.removeMessages(RESET_TOUCH_FOCUS);
406 }
407
Angus Kongeaaf56d2014-02-20 11:59:10 -0800408 /**
409 * Triggers the autofocus and set the state to indicate the focus is in
410 * progress.
411 */
412 private void autoFocus() {
413 autoFocus(STATE_FOCUSING);
414 }
415
416 /**
417 * Triggers the autofocus and set the state to which a capture will happen
418 * in the following autofocus callback.
419 */
420 private void autoFocusAndCapture() {
421 autoFocus(STATE_FOCUSING_SNAP_ON_FINISH);
422 }
423
Michael Kolb8872c232013-01-29 10:33:22 -0800424 private void cancelAutoFocus() {
425 Log.v(TAG, "Cancel autofocus.");
Michael Kolb8872c232013-01-29 10:33:22 -0800426 // Reset the tap area before calling mListener.cancelAutofocus.
427 // Otherwise, focus mode stays at auto and the tap area passed to the
428 // driver is not reset.
429 resetTouchFocus();
430 mListener.cancelAutoFocus();
Michael Kolbd6954f32013-03-08 20:43:01 -0800431 mUI.resumeFaceDetection();
Michael Kolb8872c232013-01-29 10:33:22 -0800432 mState = STATE_IDLE;
433 updateFocusUI();
434 mHandler.removeMessages(RESET_TOUCH_FOCUS);
435 }
436
437 private void capture() {
438 if (mListener.capture()) {
439 mState = STATE_IDLE;
440 mHandler.removeMessages(RESET_TOUCH_FOCUS);
441 }
442 }
443
444 public String getFocusMode() {
445 if (mOverrideFocusMode != null) return mOverrideFocusMode;
Michael Kolb4a40e122013-02-14 08:30:59 -0800446 if (mParameters == null) return Parameters.FOCUS_MODE_AUTO;
Michael Kolb8872c232013-01-29 10:33:22 -0800447 List<String> supportedFocusModes = mParameters.getSupportedFocusModes();
448
Michael Kolbb0579432013-07-11 13:48:15 -0700449 if (mFocusAreaSupported && mFocusArea != null) {
Michael Kolb8872c232013-01-29 10:33:22 -0800450 // Always use autofocus in tap-to-focus.
451 mFocusMode = Parameters.FOCUS_MODE_AUTO;
452 } else {
453 // The default is continuous autofocus.
Erin Dahlgren635a4b82013-11-25 15:21:18 -0800454 mFocusMode = mSettingsManager.get(SettingsManager.SETTING_FOCUS_MODE);
Michael Kolb8872c232013-01-29 10:33:22 -0800455 // Try to find a supported focus mode from the default list.
456 if (mFocusMode == null) {
457 for (int i = 0; i < mDefaultFocusModes.length; i++) {
458 String mode = mDefaultFocusModes[i];
Angus Kongb50b5cb2013-08-09 14:55:20 -0700459 if (CameraUtil.isSupported(mode, supportedFocusModes)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800460 mFocusMode = mode;
461 break;
462 }
463 }
464 }
465 }
Angus Kongb50b5cb2013-08-09 14:55:20 -0700466 if (!CameraUtil.isSupported(mFocusMode, supportedFocusModes)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800467 // For some reasons, the driver does not support the current
468 // focus mode. Fall back to auto.
Angus Kongb50b5cb2013-08-09 14:55:20 -0700469 if (CameraUtil.isSupported(Parameters.FOCUS_MODE_AUTO,
Michael Kolb8872c232013-01-29 10:33:22 -0800470 mParameters.getSupportedFocusModes())) {
471 mFocusMode = Parameters.FOCUS_MODE_AUTO;
472 } else {
473 mFocusMode = mParameters.getFocusMode();
474 }
475 }
476 return mFocusMode;
477 }
478
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800479 public List<Area> getFocusAreas() {
Michael Kolb8872c232013-01-29 10:33:22 -0800480 return mFocusArea;
481 }
482
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800483 public List<Area> getMeteringAreas() {
Michael Kolb8872c232013-01-29 10:33:22 -0800484 return mMeteringArea;
485 }
486
487 public void updateFocusUI() {
488 if (!mInitialized) return;
489 // Show only focus indicator or face indicator.
Michael Kolb8872c232013-01-29 10:33:22 -0800490
491 if (mState == STATE_IDLE) {
Michael Kolbb0579432013-07-11 13:48:15 -0700492 if (mFocusArea == null) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800493 mUI.clearFocus();
Michael Kolb8872c232013-01-29 10:33:22 -0800494 } else {
495 // Users touch on the preview and the indicator represents the
496 // metering area. Either focus area is not supported or
497 // autoFocus call is not required.
Michael Kolbd6954f32013-03-08 20:43:01 -0800498 mUI.onFocusStarted();
Michael Kolb8872c232013-01-29 10:33:22 -0800499 }
500 } else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800501 mUI.onFocusStarted();
Michael Kolb8872c232013-01-29 10:33:22 -0800502 } else {
Angus Kongb50b5cb2013-08-09 14:55:20 -0700503 if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800504 // TODO: check HAL behavior and decide if this can be removed.
Sascha Haeberlinge2914fd2014-01-17 19:03:52 -0800505 mUI.onFocusSucceeded();
Michael Kolb8872c232013-01-29 10:33:22 -0800506 } else if (mState == STATE_SUCCESS) {
Sascha Haeberlinge2914fd2014-01-17 19:03:52 -0800507 mUI.onFocusSucceeded();
Michael Kolb8872c232013-01-29 10:33:22 -0800508 } else if (mState == STATE_FAIL) {
Sascha Haeberlinge2914fd2014-01-17 19:03:52 -0800509 mUI.onFocusFailed();
Michael Kolb8872c232013-01-29 10:33:22 -0800510 }
511 }
512 }
513
514 public void resetTouchFocus() {
515 if (!mInitialized) return;
516
517 // Put focus indicator to the center. clear reset position
Michael Kolbd6954f32013-03-08 20:43:01 -0800518 mUI.clearFocus();
Michael Kolb0718d482013-02-16 13:13:47 -0800519 // Initialize mFocusArea.
Michael Kolbb0579432013-07-11 13:48:15 -0700520 mFocusArea = null;
521 mMeteringArea = null;
Michael Kolb8872c232013-01-29 10:33:22 -0800522 }
523
Michael Kolb0718d482013-02-16 13:13:47 -0800524 private void calculateTapArea(int x, int y, float areaMultiple, Rect rect) {
Doris Liub3749f22013-09-25 12:22:08 -0700525 int areaSize = (int) (getAreaSize() * areaMultiple);
Doris Liu36ebcb12013-10-28 14:44:24 -0700526 int left = CameraUtil.clamp(x - areaSize / 2, mPreviewRect.left,
527 mPreviewRect.right - areaSize);
528 int top = CameraUtil.clamp(y - areaSize / 2, mPreviewRect.top,
529 mPreviewRect.bottom - areaSize);
Michael Kolb8872c232013-01-29 10:33:22 -0800530
Doris Liub3749f22013-09-25 12:22:08 -0700531 RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
Michael Kolb8872c232013-01-29 10:33:22 -0800532 mMatrix.mapRect(rectF);
Angus Kongb50b5cb2013-08-09 14:55:20 -0700533 CameraUtil.rectFToRect(rectF, rect);
Michael Kolb8872c232013-01-29 10:33:22 -0800534 }
535
Doris Liub3749f22013-09-25 12:22:08 -0700536 private int getAreaSize() {
537 // Recommended focus area size from the manufacture is 1/8 of the image
Doris Liu2ba03262013-09-26 12:32:38 -0700538 // width (i.e. longer edge of the image)
Doris Liu36ebcb12013-10-28 14:44:24 -0700539 return Math.max(mPreviewRect.width(), mPreviewRect.height()) / 8;
Doris Liub3749f22013-09-25 12:22:08 -0700540 }
541
Michael Kolb8872c232013-01-29 10:33:22 -0800542 /* package */ int getFocusState() {
543 return mState;
544 }
545
546 public boolean isFocusCompleted() {
547 return mState == STATE_SUCCESS || mState == STATE_FAIL;
548 }
549
550 public boolean isFocusingSnapOnFinish() {
551 return mState == STATE_FOCUSING_SNAP_ON_FINISH;
552 }
553
554 public void removeMessages() {
555 mHandler.removeMessages(RESET_TOUCH_FOCUS);
556 }
557
558 public void overrideFocusMode(String focusMode) {
559 mOverrideFocusMode = focusMode;
560 }
561
562 public void setAeAwbLock(boolean lock) {
563 mAeAwbLock = lock;
564 }
565
566 public boolean getAeAwbLock() {
567 return mAeAwbLock;
568 }
569
570 private boolean needAutoFocusCall() {
571 String focusMode = getFocusMode();
572 return !(focusMode.equals(Parameters.FOCUS_MODE_INFINITY)
573 || focusMode.equals(Parameters.FOCUS_MODE_FIXED)
574 || focusMode.equals(Parameters.FOCUS_MODE_EDOF));
575 }
576}