blob: edc2db7b7c94fd7722213b9693051896132c60b0 [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;
29import android.util.Log;
30
Angus Kongb50b5cb2013-08-09 14:55:20 -070031import com.android.camera.util.CameraUtil;
Michael Kolb8872c232013-01-29 10:33:22 -080032
Sascha Haeberling638e6f02013-09-18 14:28:51 -070033import java.util.ArrayList;
34import java.util.List;
35
Michael Kolb8872c232013-01-29 10:33:22 -080036/* A class that handles everything about focus in still picture mode.
37 * This also handles the metering area because it is the same as focus area.
38 *
39 * The test cases:
40 * (1) The camera has continuous autofocus. Move the camera. Take a picture when
41 * CAF is not in progress.
42 * (2) The camera has continuous autofocus. Move the camera. Take a picture when
43 * CAF is in progress.
44 * (3) The camera has face detection. Point the camera at some faces. Hold the
45 * shutter. Release to take a picture.
46 * (4) The camera has face detection. Point the camera at some faces. Single tap
47 * the shutter to take a picture.
48 * (5) The camera has autofocus. Single tap the shutter to take a picture.
49 * (6) The camera has autofocus. Hold the shutter. Release to take a picture.
50 * (7) The camera has no autofocus. Single tap the shutter and take a picture.
51 * (8) The camera has autofocus and supports focus area. Touch the screen to
52 * trigger autofocus. Take a picture.
53 * (9) The camera has autofocus and supports focus area. Touch the screen to
54 * trigger autofocus. Wait until it times out.
55 * (10) The camera has no autofocus and supports metering area. Touch the screen
56 * to change metering area.
57 */
58public class FocusOverlayManager {
59 private static final String TAG = "CAM_FocusManager";
60
61 private static final int RESET_TOUCH_FOCUS = 0;
62 private static final int RESET_TOUCH_FOCUS_DELAY = 3000;
63
64 private int mState = STATE_IDLE;
65 private static final int STATE_IDLE = 0; // Focus is not active.
66 private static final int STATE_FOCUSING = 1; // Focus is in progress.
67 // Focus is in progress and the camera should take a picture after focus finishes.
68 private static final int STATE_FOCUSING_SNAP_ON_FINISH = 2;
69 private static final int STATE_SUCCESS = 3; // Focus finishes and succeeds.
70 private static final int STATE_FAIL = 4; // Focus finishes and fails.
71
72 private boolean mInitialized;
73 private boolean mFocusAreaSupported;
74 private boolean mMeteringAreaSupported;
75 private boolean mLockAeAwbNeeded;
76 private boolean mAeAwbLock;
77 private Matrix mMatrix;
78
Michael Kolb8872c232013-01-29 10:33:22 -080079 private boolean mMirror; // true if the camera is front-facing.
80 private int mDisplayOrientation;
Michael Kolb8872c232013-01-29 10:33:22 -080081 private List<Object> mFocusArea; // focus area in driver format
82 private List<Object> mMeteringArea; // metering area in driver format
83 private String mFocusMode;
84 private String[] mDefaultFocusModes;
85 private String mOverrideFocusMode;
86 private Parameters mParameters;
87 private ComboPreferences mPreferences;
88 private Handler mHandler;
89 Listener mListener;
Michael Kolbe3de7222013-02-18 15:16:44 -080090 private boolean mPreviousMoving;
Michael Kolb0718d482013-02-16 13:13:47 -080091 private boolean mFocusDefault;
Michael Kolb8872c232013-01-29 10:33:22 -080092
Michael Kolbd6954f32013-03-08 20:43:01 -080093 private FocusUI mUI;
Doris Liu36ebcb12013-10-28 14:44:24 -070094 private final Rect mPreviewRect = new Rect(0, 0, 0, 0);
Michael Kolbd6954f32013-03-08 20:43:01 -080095
96 public interface FocusUI {
97 public boolean hasFaces();
98 public void clearFocus();
99 public void setFocusPosition(int x, int y);
100 public void onFocusStarted();
101 public void onFocusSucceeded(boolean timeOut);
102 public void onFocusFailed(boolean timeOut);
103 public void pauseFaceDetection();
104 public void resumeFaceDetection();
105 }
106
Michael Kolb8872c232013-01-29 10:33:22 -0800107 public interface Listener {
108 public void autoFocus();
109 public void cancelAutoFocus();
110 public boolean capture();
111 public void startFaceDetection();
112 public void stopFaceDetection();
113 public void setFocusParameters();
114 }
115
116 private class MainHandler extends Handler {
117 public MainHandler(Looper looper) {
118 super(looper);
119 }
120
121 @Override
122 public void handleMessage(Message msg) {
123 switch (msg.what) {
124 case RESET_TOUCH_FOCUS: {
125 cancelAutoFocus();
126 mListener.startFaceDetection();
127 break;
128 }
129 }
130 }
131 }
132
133 public FocusOverlayManager(ComboPreferences preferences, String[] defaultFocusModes,
134 Parameters parameters, Listener listener,
Michael Kolbd6954f32013-03-08 20:43:01 -0800135 boolean mirror, Looper looper, FocusUI ui) {
Michael Kolb8872c232013-01-29 10:33:22 -0800136 mHandler = new MainHandler(looper);
137 mMatrix = new Matrix();
138 mPreferences = preferences;
139 mDefaultFocusModes = defaultFocusModes;
140 setParameters(parameters);
141 mListener = listener;
142 setMirror(mirror);
Michael Kolb0718d482013-02-16 13:13:47 -0800143 mFocusDefault = true;
Michael Kolbd6954f32013-03-08 20:43:01 -0800144 mUI = ui;
Michael Kolb8872c232013-01-29 10:33:22 -0800145 }
146
147 public void setParameters(Parameters parameters) {
148 // parameters can only be null when onConfigurationChanged is called
149 // before camera is open. We will just return in this case, because
150 // parameters will be set again later with the right parameters after
151 // camera is open.
152 if (parameters == null) return;
153 mParameters = parameters;
Angus Kongb50b5cb2013-08-09 14:55:20 -0700154 mFocusAreaSupported = CameraUtil.isFocusAreaSupported(parameters);
155 mMeteringAreaSupported = CameraUtil.isMeteringAreaSupported(parameters);
156 mLockAeAwbNeeded = (CameraUtil.isAutoExposureLockSupported(mParameters) ||
157 CameraUtil.isAutoWhiteBalanceLockSupported(mParameters));
Michael Kolb8872c232013-01-29 10:33:22 -0800158 }
159
160 public void setPreviewSize(int previewWidth, int previewHeight) {
Doris Liu36ebcb12013-10-28 14:44:24 -0700161 if (mPreviewRect.width() != previewWidth || mPreviewRect.height() != previewHeight) {
162 setPreviewRect(new Rect(0, 0, previewWidth, previewHeight));
163 }
164 }
165
166 /** 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 Liu36ebcb12013-10-28 14:44:24 -0700174 /** Returns a copy of mPreviewRect so that outside class cannot modify preview
175 * rect except deliberately doing so through the setter. */
176 public Rect getPreviewRect() {
177 return new Rect(mPreviewRect);
178 }
179
Michael Kolb8872c232013-01-29 10:33:22 -0800180 public void setMirror(boolean mirror) {
181 mMirror = mirror;
182 setMatrix();
183 }
184
185 public void setDisplayOrientation(int displayOrientation) {
186 mDisplayOrientation = displayOrientation;
187 setMatrix();
188 }
189
Michael Kolb8872c232013-01-29 10:33:22 -0800190 private void setMatrix() {
Doris Liu36ebcb12013-10-28 14:44:24 -0700191 if (mPreviewRect.width() != 0 && mPreviewRect.height() != 0) {
Michael Kolb8872c232013-01-29 10:33:22 -0800192 Matrix matrix = new Matrix();
Doris Liu36ebcb12013-10-28 14:44:24 -0700193 CameraUtil.prepareMatrix(matrix, mMirror, mDisplayOrientation, getPreviewRect());
Michael Kolb8872c232013-01-29 10:33:22 -0800194 // In face detection, the matrix converts the driver coordinates to UI
195 // coordinates. In tap focus, the inverted matrix converts the UI
196 // coordinates to driver coordinates.
197 matrix.invert(mMatrix);
Michael Kolbd6954f32013-03-08 20:43:01 -0800198 mInitialized = true;
Michael Kolb8872c232013-01-29 10:33:22 -0800199 }
200 }
201
202 private void lockAeAwbIfNeeded() {
203 if (mLockAeAwbNeeded && !mAeAwbLock) {
204 mAeAwbLock = true;
205 mListener.setFocusParameters();
206 }
207 }
208
209 private void unlockAeAwbIfNeeded() {
210 if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) {
211 mAeAwbLock = false;
212 mListener.setFocusParameters();
213 }
214 }
215
216 public void onShutterDown() {
217 if (!mInitialized) return;
218
219 boolean autoFocusCalled = false;
220 if (needAutoFocusCall()) {
221 // Do not focus if touch focus has been triggered.
222 if (mState != STATE_SUCCESS && mState != STATE_FAIL) {
223 autoFocus();
224 autoFocusCalled = true;
225 }
226 }
227
228 if (!autoFocusCalled) lockAeAwbIfNeeded();
229 }
230
231 public void onShutterUp() {
232 if (!mInitialized) return;
233
234 if (needAutoFocusCall()) {
235 // User releases half-pressed focus key.
236 if (mState == STATE_FOCUSING || mState == STATE_SUCCESS
237 || mState == STATE_FAIL) {
238 cancelAutoFocus();
239 }
240 }
241
242 // Unlock AE and AWB after cancelAutoFocus. Camera API does not
243 // guarantee setParameters can be called during autofocus.
244 unlockAeAwbIfNeeded();
245 }
246
247 public void doSnap() {
248 if (!mInitialized) return;
249
250 // If the user has half-pressed the shutter and focus is completed, we
251 // can take the photo right away. If the focus mode is infinity, we can
252 // also take the photo.
253 if (!needAutoFocusCall() || (mState == STATE_SUCCESS || mState == STATE_FAIL)) {
254 capture();
255 } else if (mState == STATE_FOCUSING) {
256 // Half pressing the shutter (i.e. the focus button event) will
257 // already have requested AF for us, so just request capture on
258 // focus here.
259 mState = STATE_FOCUSING_SNAP_ON_FINISH;
260 } else if (mState == STATE_IDLE) {
261 // We didn't do focus. This can happen if the user press focus key
262 // while the snapshot is still in progress. The user probably wants
263 // the next snapshot as soon as possible, so we just do a snapshot
264 // without focusing again.
265 capture();
266 }
267 }
268
269 public void onAutoFocus(boolean focused, boolean shutterButtonPressed) {
270 if (mState == STATE_FOCUSING_SNAP_ON_FINISH) {
271 // Take the picture no matter focus succeeds or fails. No need
272 // to play the AF sound if we're about to play the shutter
273 // sound.
274 if (focused) {
275 mState = STATE_SUCCESS;
276 } else {
277 mState = STATE_FAIL;
278 }
279 updateFocusUI();
280 capture();
281 } else if (mState == STATE_FOCUSING) {
282 // This happens when (1) user is half-pressing the focus key or
283 // (2) touch focus is triggered. Play the focus tone. Do not
284 // take the picture now.
285 if (focused) {
286 mState = STATE_SUCCESS;
287 } else {
288 mState = STATE_FAIL;
289 }
290 updateFocusUI();
291 // If this is triggered by touch focus, cancel focus after a
292 // while.
Michael Kolb0718d482013-02-16 13:13:47 -0800293 if (!mFocusDefault) {
Michael Kolb8872c232013-01-29 10:33:22 -0800294 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
295 }
296 if (shutterButtonPressed) {
297 // Lock AE & AWB so users can half-press shutter and recompose.
298 lockAeAwbIfNeeded();
299 }
300 } else if (mState == STATE_IDLE) {
301 // User has released the focus key before focus completes.
302 // Do nothing.
303 }
304 }
305
306 public void onAutoFocusMoving(boolean moving) {
307 if (!mInitialized) return;
Michael Kolbd6954f32013-03-08 20:43:01 -0800308
309
Michael Kolb8872c232013-01-29 10:33:22 -0800310 // Ignore if the camera has detected some faces.
Michael Kolbd6954f32013-03-08 20:43:01 -0800311 if (mUI.hasFaces()) {
312 mUI.clearFocus();
Michael Kolb8872c232013-01-29 10:33:22 -0800313 return;
314 }
315
316 // Ignore if we have requested autofocus. This method only handles
317 // continuous autofocus.
318 if (mState != STATE_IDLE) return;
319
Michael Kolbe3de7222013-02-18 15:16:44 -0800320 // animate on false->true trasition only b/8219520
321 if (moving && !mPreviousMoving) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800322 mUI.onFocusStarted();
Michael Kolbe3de7222013-02-18 15:16:44 -0800323 } else if (!moving) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800324 mUI.onFocusSucceeded(true);
Michael Kolb8872c232013-01-29 10:33:22 -0800325 }
Michael Kolbe3de7222013-02-18 15:16:44 -0800326 mPreviousMoving = moving;
Michael Kolb8872c232013-01-29 10:33:22 -0800327 }
328
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700329 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
Michael Kolb0718d482013-02-16 13:13:47 -0800330 private void initializeFocusAreas(int x, int y) {
Michael Kolb8872c232013-01-29 10:33:22 -0800331 if (mFocusArea == null) {
332 mFocusArea = new ArrayList<Object>();
333 mFocusArea.add(new Area(new Rect(), 1));
334 }
335
336 // Convert the coordinates to driver format.
Michael Kolb0718d482013-02-16 13:13:47 -0800337 calculateTapArea(x, y, 1f, ((Area) mFocusArea.get(0)).rect);
Michael Kolb8872c232013-01-29 10:33:22 -0800338 }
339
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700340 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
Michael Kolb0718d482013-02-16 13:13:47 -0800341 private void initializeMeteringAreas(int x, int y) {
Michael Kolb8872c232013-01-29 10:33:22 -0800342 if (mMeteringArea == null) {
343 mMeteringArea = new ArrayList<Object>();
344 mMeteringArea.add(new Area(new Rect(), 1));
345 }
346
347 // Convert the coordinates to driver format.
348 // AE area is bigger because exposure is sensitive and
349 // easy to over- or underexposure if area is too small.
Michael Kolb0718d482013-02-16 13:13:47 -0800350 calculateTapArea(x, y, 1.5f, ((Area) mMeteringArea.get(0)).rect);
Michael Kolb8872c232013-01-29 10:33:22 -0800351 }
352
Doris Liucbdd3732013-10-03 11:00:59 -0700353 private void resetMeteringAreas() {
354 mMeteringArea = null;
355 }
356
Michael Kolb8872c232013-01-29 10:33:22 -0800357 public void onSingleTapUp(int x, int y) {
358 if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) return;
359
360 // Let users be able to cancel previous touch focus.
Michael Kolb0718d482013-02-16 13:13:47 -0800361 if ((!mFocusDefault) && (mState == STATE_FOCUSING ||
Michael Kolb8872c232013-01-29 10:33:22 -0800362 mState == STATE_SUCCESS || mState == STATE_FAIL)) {
363 cancelAutoFocus();
364 }
Doris Liu36ebcb12013-10-28 14:44:24 -0700365 if (mPreviewRect.width() == 0 || mPreviewRect.height() == 0) return;
Michael Kolb0718d482013-02-16 13:13:47 -0800366 mFocusDefault = false;
Michael Kolb8872c232013-01-29 10:33:22 -0800367 // Initialize mFocusArea.
368 if (mFocusAreaSupported) {
Michael Kolb0718d482013-02-16 13:13:47 -0800369 initializeFocusAreas(x, y);
Michael Kolb8872c232013-01-29 10:33:22 -0800370 }
371 // Initialize mMeteringArea.
372 if (mMeteringAreaSupported) {
Michael Kolb0718d482013-02-16 13:13:47 -0800373 initializeMeteringAreas(x, y);
Michael Kolb8872c232013-01-29 10:33:22 -0800374 }
375
376 // Use margin to set the focus indicator to the touched area.
Michael Kolbd6954f32013-03-08 20:43:01 -0800377 mUI.setFocusPosition(x, y);
Michael Kolb8872c232013-01-29 10:33:22 -0800378
379 // Stop face detection because we want to specify focus and metering area.
380 mListener.stopFaceDetection();
381
382 // Set the focus area and metering area.
383 mListener.setFocusParameters();
384 if (mFocusAreaSupported) {
385 autoFocus();
386 } else { // Just show the indicator in all other cases.
387 updateFocusUI();
388 // Reset the metering area in 3 seconds.
389 mHandler.removeMessages(RESET_TOUCH_FOCUS);
390 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
391 }
392 }
393
394 public void onPreviewStarted() {
395 mState = STATE_IDLE;
396 }
397
398 public void onPreviewStopped() {
399 // If auto focus was in progress, it would have been stopped.
400 mState = STATE_IDLE;
401 resetTouchFocus();
402 updateFocusUI();
403 }
404
405 public void onCameraReleased() {
406 onPreviewStopped();
407 }
408
409 private void autoFocus() {
410 Log.v(TAG, "Start autofocus.");
411 mListener.autoFocus();
412 mState = STATE_FOCUSING;
413 // Pause the face view because the driver will keep sending face
414 // callbacks after the focus completes.
Michael Kolbd6954f32013-03-08 20:43:01 -0800415 mUI.pauseFaceDetection();
Michael Kolb8872c232013-01-29 10:33:22 -0800416 updateFocusUI();
417 mHandler.removeMessages(RESET_TOUCH_FOCUS);
418 }
419
420 private void cancelAutoFocus() {
421 Log.v(TAG, "Cancel autofocus.");
422
423 // Reset the tap area before calling mListener.cancelAutofocus.
424 // Otherwise, focus mode stays at auto and the tap area passed to the
425 // driver is not reset.
426 resetTouchFocus();
427 mListener.cancelAutoFocus();
Michael Kolbd6954f32013-03-08 20:43:01 -0800428 mUI.resumeFaceDetection();
Michael Kolb8872c232013-01-29 10:33:22 -0800429 mState = STATE_IDLE;
430 updateFocusUI();
431 mHandler.removeMessages(RESET_TOUCH_FOCUS);
432 }
433
434 private void capture() {
435 if (mListener.capture()) {
436 mState = STATE_IDLE;
437 mHandler.removeMessages(RESET_TOUCH_FOCUS);
438 }
439 }
440
441 public String getFocusMode() {
442 if (mOverrideFocusMode != null) return mOverrideFocusMode;
Michael Kolb4a40e122013-02-14 08:30:59 -0800443 if (mParameters == null) return Parameters.FOCUS_MODE_AUTO;
Michael Kolb8872c232013-01-29 10:33:22 -0800444 List<String> supportedFocusModes = mParameters.getSupportedFocusModes();
445
Michael Kolb0718d482013-02-16 13:13:47 -0800446 if (mFocusAreaSupported && !mFocusDefault) {
Michael Kolb8872c232013-01-29 10:33:22 -0800447 // Always use autofocus in tap-to-focus.
448 mFocusMode = Parameters.FOCUS_MODE_AUTO;
449 } else {
450 // The default is continuous autofocus.
451 mFocusMode = mPreferences.getString(
452 CameraSettings.KEY_FOCUS_MODE, null);
453
454 // Try to find a supported focus mode from the default list.
455 if (mFocusMode == null) {
456 for (int i = 0; i < mDefaultFocusModes.length; i++) {
457 String mode = mDefaultFocusModes[i];
Angus Kongb50b5cb2013-08-09 14:55:20 -0700458 if (CameraUtil.isSupported(mode, supportedFocusModes)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800459 mFocusMode = mode;
460 break;
461 }
462 }
463 }
464 }
Angus Kongb50b5cb2013-08-09 14:55:20 -0700465 if (!CameraUtil.isSupported(mFocusMode, supportedFocusModes)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800466 // For some reasons, the driver does not support the current
467 // focus mode. Fall back to auto.
Angus Kongb50b5cb2013-08-09 14:55:20 -0700468 if (CameraUtil.isSupported(Parameters.FOCUS_MODE_AUTO,
Michael Kolb8872c232013-01-29 10:33:22 -0800469 mParameters.getSupportedFocusModes())) {
470 mFocusMode = Parameters.FOCUS_MODE_AUTO;
471 } else {
472 mFocusMode = mParameters.getFocusMode();
473 }
474 }
475 return mFocusMode;
476 }
477
478 public List getFocusAreas() {
479 return mFocusArea;
480 }
481
482 public List getMeteringAreas() {
483 return mMeteringArea;
484 }
485
486 public void updateFocusUI() {
487 if (!mInitialized) return;
488 // Show only focus indicator or face indicator.
Michael Kolb8872c232013-01-29 10:33:22 -0800489
490 if (mState == STATE_IDLE) {
Michael Kolb0718d482013-02-16 13:13:47 -0800491 if (mFocusDefault) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800492 mUI.clearFocus();
Michael Kolb8872c232013-01-29 10:33:22 -0800493 } else {
494 // Users touch on the preview and the indicator represents the
495 // metering area. Either focus area is not supported or
496 // autoFocus call is not required.
Michael Kolbd6954f32013-03-08 20:43:01 -0800497 mUI.onFocusStarted();
Michael Kolb8872c232013-01-29 10:33:22 -0800498 }
499 } else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800500 mUI.onFocusStarted();
Michael Kolb8872c232013-01-29 10:33:22 -0800501 } else {
Angus Kongb50b5cb2013-08-09 14:55:20 -0700502 if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800503 // TODO: check HAL behavior and decide if this can be removed.
Michael Kolbd6954f32013-03-08 20:43:01 -0800504 mUI.onFocusSucceeded(false);
Michael Kolb8872c232013-01-29 10:33:22 -0800505 } else if (mState == STATE_SUCCESS) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800506 mUI.onFocusSucceeded(false);
Michael Kolb8872c232013-01-29 10:33:22 -0800507 } else if (mState == STATE_FAIL) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800508 mUI.onFocusFailed(false);
Michael Kolb8872c232013-01-29 10:33:22 -0800509 }
510 }
511 }
512
513 public void resetTouchFocus() {
514 if (!mInitialized) return;
515
516 // Put focus indicator to the center. clear reset position
Michael Kolbd6954f32013-03-08 20:43:01 -0800517 mUI.clearFocus();
Michael Kolb0718d482013-02-16 13:13:47 -0800518 // Initialize mFocusArea.
519 if (mFocusAreaSupported) {
Doris Liu36ebcb12013-10-28 14:44:24 -0700520 initializeFocusAreas(mPreviewRect.centerX(), mPreviewRect.centerY());
Michael Kolb0718d482013-02-16 13:13:47 -0800521 }
Doris Liucbdd3732013-10-03 11:00:59 -0700522 // Reset metering area when no specific region is selected.
Michael Kolb0718d482013-02-16 13:13:47 -0800523 if (mMeteringAreaSupported) {
Doris Liucbdd3732013-10-03 11:00:59 -0700524 resetMeteringAreas();
Michael Kolb0718d482013-02-16 13:13:47 -0800525 }
526 mFocusDefault = true;
Michael Kolb8872c232013-01-29 10:33:22 -0800527 }
528
Michael Kolb0718d482013-02-16 13:13:47 -0800529 private void calculateTapArea(int x, int y, float areaMultiple, Rect rect) {
Doris Liub3749f22013-09-25 12:22:08 -0700530 int areaSize = (int) (getAreaSize() * areaMultiple);
Doris Liu36ebcb12013-10-28 14:44:24 -0700531 int left = CameraUtil.clamp(x - areaSize / 2, mPreviewRect.left,
532 mPreviewRect.right - areaSize);
533 int top = CameraUtil.clamp(y - areaSize / 2, mPreviewRect.top,
534 mPreviewRect.bottom - areaSize);
Michael Kolb8872c232013-01-29 10:33:22 -0800535
Doris Liub3749f22013-09-25 12:22:08 -0700536 RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
Michael Kolb8872c232013-01-29 10:33:22 -0800537 mMatrix.mapRect(rectF);
Angus Kongb50b5cb2013-08-09 14:55:20 -0700538 CameraUtil.rectFToRect(rectF, rect);
Michael Kolb8872c232013-01-29 10:33:22 -0800539 }
540
Doris Liub3749f22013-09-25 12:22:08 -0700541 private int getAreaSize() {
542 // Recommended focus area size from the manufacture is 1/8 of the image
Doris Liu2ba03262013-09-26 12:32:38 -0700543 // width (i.e. longer edge of the image)
Doris Liu36ebcb12013-10-28 14:44:24 -0700544 return Math.max(mPreviewRect.width(), mPreviewRect.height()) / 8;
Doris Liub3749f22013-09-25 12:22:08 -0700545 }
546
Michael Kolb8872c232013-01-29 10:33:22 -0800547 /* package */ int getFocusState() {
548 return mState;
549 }
550
551 public boolean isFocusCompleted() {
552 return mState == STATE_SUCCESS || mState == STATE_FAIL;
553 }
554
555 public boolean isFocusingSnapOnFinish() {
556 return mState == STATE_FOCUSING_SNAP_ON_FINISH;
557 }
558
559 public void removeMessages() {
560 mHandler.removeMessages(RESET_TOUCH_FOCUS);
561 }
562
563 public void overrideFocusMode(String focusMode) {
564 mOverrideFocusMode = focusMode;
565 }
566
567 public void setAeAwbLock(boolean lock) {
568 mAeAwbLock = lock;
569 }
570
571 public boolean getAeAwbLock() {
572 return mAeAwbLock;
573 }
574
575 private boolean needAutoFocusCall() {
576 String focusMode = getFocusMode();
577 return !(focusMode.equals(Parameters.FOCUS_MODE_INFINITY)
578 || focusMode.equals(Parameters.FOCUS_MODE_FIXED)
579 || focusMode.equals(Parameters.FOCUS_MODE_EDOF));
580 }
581}