blob: c223aea6bb568333c7691d00b2f6d986dab07add [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 int mPreviewWidth; // The width of the preview frame layout.
80 private int mPreviewHeight; // The height of the preview frame layout.
81 private boolean mMirror; // true if the camera is front-facing.
82 private int mDisplayOrientation;
Michael Kolb8872c232013-01-29 10:33:22 -080083 private List<Object> mFocusArea; // focus area in driver format
84 private List<Object> mMeteringArea; // metering area in driver format
85 private String mFocusMode;
86 private String[] mDefaultFocusModes;
87 private String mOverrideFocusMode;
88 private Parameters mParameters;
89 private ComboPreferences mPreferences;
90 private Handler mHandler;
91 Listener mListener;
Michael Kolbe3de7222013-02-18 15:16:44 -080092 private boolean mPreviousMoving;
Michael Kolb0718d482013-02-16 13:13:47 -080093 private boolean mFocusDefault;
Michael Kolb8872c232013-01-29 10:33:22 -080094
Michael Kolbd6954f32013-03-08 20:43:01 -080095 private FocusUI mUI;
96
97 public interface FocusUI {
98 public boolean hasFaces();
99 public void clearFocus();
100 public void setFocusPosition(int x, int y);
101 public void onFocusStarted();
102 public void onFocusSucceeded(boolean timeOut);
103 public void onFocusFailed(boolean timeOut);
104 public void pauseFaceDetection();
105 public void resumeFaceDetection();
106 }
107
Michael Kolb8872c232013-01-29 10:33:22 -0800108 public interface Listener {
109 public void autoFocus();
110 public void cancelAutoFocus();
111 public boolean capture();
112 public void startFaceDetection();
113 public void stopFaceDetection();
114 public void setFocusParameters();
115 }
116
117 private class MainHandler extends Handler {
118 public MainHandler(Looper looper) {
119 super(looper);
120 }
121
122 @Override
123 public void handleMessage(Message msg) {
124 switch (msg.what) {
125 case RESET_TOUCH_FOCUS: {
126 cancelAutoFocus();
127 mListener.startFaceDetection();
128 break;
129 }
130 }
131 }
132 }
133
134 public FocusOverlayManager(ComboPreferences preferences, String[] defaultFocusModes,
135 Parameters parameters, Listener listener,
Michael Kolbd6954f32013-03-08 20:43:01 -0800136 boolean mirror, Looper looper, FocusUI ui) {
Michael Kolb8872c232013-01-29 10:33:22 -0800137 mHandler = new MainHandler(looper);
138 mMatrix = new Matrix();
139 mPreferences = preferences;
140 mDefaultFocusModes = defaultFocusModes;
141 setParameters(parameters);
142 mListener = listener;
143 setMirror(mirror);
Michael Kolb0718d482013-02-16 13:13:47 -0800144 mFocusDefault = true;
Michael Kolbd6954f32013-03-08 20:43:01 -0800145 mUI = ui;
Michael Kolb8872c232013-01-29 10:33:22 -0800146 }
147
148 public void setParameters(Parameters parameters) {
149 // parameters can only be null when onConfigurationChanged is called
150 // before camera is open. We will just return in this case, because
151 // parameters will be set again later with the right parameters after
152 // camera is open.
153 if (parameters == null) return;
154 mParameters = parameters;
Angus Kongb50b5cb2013-08-09 14:55:20 -0700155 mFocusAreaSupported = CameraUtil.isFocusAreaSupported(parameters);
156 mMeteringAreaSupported = CameraUtil.isMeteringAreaSupported(parameters);
157 mLockAeAwbNeeded = (CameraUtil.isAutoExposureLockSupported(mParameters) ||
158 CameraUtil.isAutoWhiteBalanceLockSupported(mParameters));
Michael Kolb8872c232013-01-29 10:33:22 -0800159 }
160
161 public void setPreviewSize(int previewWidth, int previewHeight) {
162 if (mPreviewWidth != previewWidth || mPreviewHeight != previewHeight) {
163 mPreviewWidth = previewWidth;
164 mPreviewHeight = previewHeight;
165 setMatrix();
166 }
167 }
168
169 public void setMirror(boolean mirror) {
170 mMirror = mirror;
171 setMatrix();
172 }
173
174 public void setDisplayOrientation(int displayOrientation) {
175 mDisplayOrientation = displayOrientation;
176 setMatrix();
177 }
178
Michael Kolb8872c232013-01-29 10:33:22 -0800179 private void setMatrix() {
180 if (mPreviewWidth != 0 && mPreviewHeight != 0) {
181 Matrix matrix = new Matrix();
Angus Kongb50b5cb2013-08-09 14:55:20 -0700182 CameraUtil.prepareMatrix(matrix, mMirror, mDisplayOrientation,
Michael Kolb8872c232013-01-29 10:33:22 -0800183 mPreviewWidth, mPreviewHeight);
184 // In face detection, the matrix converts the driver coordinates to UI
185 // coordinates. In tap focus, the inverted matrix converts the UI
186 // coordinates to driver coordinates.
187 matrix.invert(mMatrix);
Michael Kolbd6954f32013-03-08 20:43:01 -0800188 mInitialized = true;
Michael Kolb8872c232013-01-29 10:33:22 -0800189 }
190 }
191
192 private void lockAeAwbIfNeeded() {
193 if (mLockAeAwbNeeded && !mAeAwbLock) {
194 mAeAwbLock = true;
195 mListener.setFocusParameters();
196 }
197 }
198
199 private void unlockAeAwbIfNeeded() {
200 if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) {
201 mAeAwbLock = false;
202 mListener.setFocusParameters();
203 }
204 }
205
206 public void onShutterDown() {
207 if (!mInitialized) return;
208
209 boolean autoFocusCalled = false;
210 if (needAutoFocusCall()) {
211 // Do not focus if touch focus has been triggered.
212 if (mState != STATE_SUCCESS && mState != STATE_FAIL) {
213 autoFocus();
214 autoFocusCalled = true;
215 }
216 }
217
218 if (!autoFocusCalled) lockAeAwbIfNeeded();
219 }
220
221 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
237 public void doSnap() {
238 if (!mInitialized) return;
239
240 // If the user has half-pressed the shutter and focus is completed, we
241 // can take the photo right away. If the focus mode is infinity, we can
242 // also take the photo.
243 if (!needAutoFocusCall() || (mState == STATE_SUCCESS || mState == STATE_FAIL)) {
244 capture();
245 } else if (mState == STATE_FOCUSING) {
246 // Half pressing the shutter (i.e. the focus button event) will
247 // already have requested AF for us, so just request capture on
248 // focus here.
249 mState = STATE_FOCUSING_SNAP_ON_FINISH;
250 } else if (mState == STATE_IDLE) {
251 // We didn't do focus. This can happen if the user press focus key
252 // while the snapshot is still in progress. The user probably wants
253 // the next snapshot as soon as possible, so we just do a snapshot
254 // without focusing again.
255 capture();
256 }
257 }
258
259 public void onAutoFocus(boolean focused, boolean shutterButtonPressed) {
260 if (mState == STATE_FOCUSING_SNAP_ON_FINISH) {
261 // Take the picture no matter focus succeeds or fails. No need
262 // to play the AF sound if we're about to play the shutter
263 // sound.
264 if (focused) {
265 mState = STATE_SUCCESS;
266 } else {
267 mState = STATE_FAIL;
268 }
269 updateFocusUI();
270 capture();
271 } else if (mState == STATE_FOCUSING) {
272 // This happens when (1) user is half-pressing the focus key or
273 // (2) touch focus is triggered. Play the focus tone. Do not
274 // take the picture now.
275 if (focused) {
276 mState = STATE_SUCCESS;
277 } else {
278 mState = STATE_FAIL;
279 }
280 updateFocusUI();
281 // If this is triggered by touch focus, cancel focus after a
282 // while.
Michael Kolb0718d482013-02-16 13:13:47 -0800283 if (!mFocusDefault) {
Michael Kolb8872c232013-01-29 10:33:22 -0800284 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
285 }
286 if (shutterButtonPressed) {
287 // Lock AE & AWB so users can half-press shutter and recompose.
288 lockAeAwbIfNeeded();
289 }
290 } else if (mState == STATE_IDLE) {
291 // User has released the focus key before focus completes.
292 // Do nothing.
293 }
294 }
295
296 public void onAutoFocusMoving(boolean moving) {
297 if (!mInitialized) return;
Michael Kolbd6954f32013-03-08 20:43:01 -0800298
299
Michael Kolb8872c232013-01-29 10:33:22 -0800300 // Ignore if the camera has detected some faces.
Michael Kolbd6954f32013-03-08 20:43:01 -0800301 if (mUI.hasFaces()) {
302 mUI.clearFocus();
Michael Kolb8872c232013-01-29 10:33:22 -0800303 return;
304 }
305
306 // Ignore if we have requested autofocus. This method only handles
307 // continuous autofocus.
308 if (mState != STATE_IDLE) return;
309
Michael Kolbe3de7222013-02-18 15:16:44 -0800310 // animate on false->true trasition only b/8219520
311 if (moving && !mPreviousMoving) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800312 mUI.onFocusStarted();
Michael Kolbe3de7222013-02-18 15:16:44 -0800313 } else if (!moving) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800314 mUI.onFocusSucceeded(true);
Michael Kolb8872c232013-01-29 10:33:22 -0800315 }
Michael Kolbe3de7222013-02-18 15:16:44 -0800316 mPreviousMoving = moving;
Michael Kolb8872c232013-01-29 10:33:22 -0800317 }
318
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700319 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
Michael Kolb0718d482013-02-16 13:13:47 -0800320 private void initializeFocusAreas(int x, int y) {
Michael Kolb8872c232013-01-29 10:33:22 -0800321 if (mFocusArea == null) {
322 mFocusArea = new ArrayList<Object>();
323 mFocusArea.add(new Area(new Rect(), 1));
324 }
325
326 // Convert the coordinates to driver format.
Michael Kolb0718d482013-02-16 13:13:47 -0800327 calculateTapArea(x, y, 1f, ((Area) mFocusArea.get(0)).rect);
Michael Kolb8872c232013-01-29 10:33:22 -0800328 }
329
Sascha Haeberling638e6f02013-09-18 14:28:51 -0700330 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
Michael Kolb0718d482013-02-16 13:13:47 -0800331 private void initializeMeteringAreas(int x, int y) {
Michael Kolb8872c232013-01-29 10:33:22 -0800332 if (mMeteringArea == null) {
333 mMeteringArea = new ArrayList<Object>();
334 mMeteringArea.add(new Area(new Rect(), 1));
335 }
336
337 // Convert the coordinates to driver format.
338 // AE area is bigger because exposure is sensitive and
339 // easy to over- or underexposure if area is too small.
Michael Kolb0718d482013-02-16 13:13:47 -0800340 calculateTapArea(x, y, 1.5f, ((Area) mMeteringArea.get(0)).rect);
Michael Kolb8872c232013-01-29 10:33:22 -0800341 }
342
Doris Liucbdd3732013-10-03 11:00:59 -0700343 private void resetMeteringAreas() {
344 mMeteringArea = null;
345 }
346
Michael Kolb8872c232013-01-29 10:33:22 -0800347 public void onSingleTapUp(int x, int y) {
348 if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) return;
349
350 // Let users be able to cancel previous touch focus.
Michael Kolb0718d482013-02-16 13:13:47 -0800351 if ((!mFocusDefault) && (mState == STATE_FOCUSING ||
Michael Kolb8872c232013-01-29 10:33:22 -0800352 mState == STATE_SUCCESS || mState == STATE_FAIL)) {
353 cancelAutoFocus();
354 }
Michael Kolb0718d482013-02-16 13:13:47 -0800355 if (mPreviewWidth == 0 || mPreviewHeight == 0) return;
356 mFocusDefault = false;
Michael Kolb8872c232013-01-29 10:33:22 -0800357 // Initialize mFocusArea.
358 if (mFocusAreaSupported) {
Michael Kolb0718d482013-02-16 13:13:47 -0800359 initializeFocusAreas(x, y);
Michael Kolb8872c232013-01-29 10:33:22 -0800360 }
361 // Initialize mMeteringArea.
362 if (mMeteringAreaSupported) {
Michael Kolb0718d482013-02-16 13:13:47 -0800363 initializeMeteringAreas(x, y);
Michael Kolb8872c232013-01-29 10:33:22 -0800364 }
365
366 // Use margin to set the focus indicator to the touched area.
Michael Kolbd6954f32013-03-08 20:43:01 -0800367 mUI.setFocusPosition(x, y);
Michael Kolb8872c232013-01-29 10:33:22 -0800368
369 // Stop face detection because we want to specify focus and metering area.
370 mListener.stopFaceDetection();
371
372 // Set the focus area and metering area.
373 mListener.setFocusParameters();
374 if (mFocusAreaSupported) {
375 autoFocus();
376 } else { // Just show the indicator in all other cases.
377 updateFocusUI();
378 // Reset the metering area in 3 seconds.
379 mHandler.removeMessages(RESET_TOUCH_FOCUS);
380 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
381 }
382 }
383
384 public void onPreviewStarted() {
385 mState = STATE_IDLE;
386 }
387
388 public void onPreviewStopped() {
389 // If auto focus was in progress, it would have been stopped.
390 mState = STATE_IDLE;
391 resetTouchFocus();
392 updateFocusUI();
393 }
394
395 public void onCameraReleased() {
396 onPreviewStopped();
397 }
398
399 private void autoFocus() {
400 Log.v(TAG, "Start autofocus.");
401 mListener.autoFocus();
402 mState = STATE_FOCUSING;
403 // Pause the face view because the driver will keep sending face
404 // callbacks after the focus completes.
Michael Kolbd6954f32013-03-08 20:43:01 -0800405 mUI.pauseFaceDetection();
Michael Kolb8872c232013-01-29 10:33:22 -0800406 updateFocusUI();
407 mHandler.removeMessages(RESET_TOUCH_FOCUS);
408 }
409
410 private void cancelAutoFocus() {
411 Log.v(TAG, "Cancel autofocus.");
412
413 // Reset the tap area before calling mListener.cancelAutofocus.
414 // Otherwise, focus mode stays at auto and the tap area passed to the
415 // driver is not reset.
416 resetTouchFocus();
417 mListener.cancelAutoFocus();
Michael Kolbd6954f32013-03-08 20:43:01 -0800418 mUI.resumeFaceDetection();
Michael Kolb8872c232013-01-29 10:33:22 -0800419 mState = STATE_IDLE;
420 updateFocusUI();
421 mHandler.removeMessages(RESET_TOUCH_FOCUS);
422 }
423
424 private void capture() {
425 if (mListener.capture()) {
426 mState = STATE_IDLE;
427 mHandler.removeMessages(RESET_TOUCH_FOCUS);
428 }
429 }
430
431 public String getFocusMode() {
432 if (mOverrideFocusMode != null) return mOverrideFocusMode;
Michael Kolb4a40e122013-02-14 08:30:59 -0800433 if (mParameters == null) return Parameters.FOCUS_MODE_AUTO;
Michael Kolb8872c232013-01-29 10:33:22 -0800434 List<String> supportedFocusModes = mParameters.getSupportedFocusModes();
435
Michael Kolb0718d482013-02-16 13:13:47 -0800436 if (mFocusAreaSupported && !mFocusDefault) {
Michael Kolb8872c232013-01-29 10:33:22 -0800437 // Always use autofocus in tap-to-focus.
438 mFocusMode = Parameters.FOCUS_MODE_AUTO;
439 } else {
440 // The default is continuous autofocus.
441 mFocusMode = mPreferences.getString(
442 CameraSettings.KEY_FOCUS_MODE, null);
443
444 // Try to find a supported focus mode from the default list.
445 if (mFocusMode == null) {
446 for (int i = 0; i < mDefaultFocusModes.length; i++) {
447 String mode = mDefaultFocusModes[i];
Angus Kongb50b5cb2013-08-09 14:55:20 -0700448 if (CameraUtil.isSupported(mode, supportedFocusModes)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800449 mFocusMode = mode;
450 break;
451 }
452 }
453 }
454 }
Angus Kongb50b5cb2013-08-09 14:55:20 -0700455 if (!CameraUtil.isSupported(mFocusMode, supportedFocusModes)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800456 // For some reasons, the driver does not support the current
457 // focus mode. Fall back to auto.
Angus Kongb50b5cb2013-08-09 14:55:20 -0700458 if (CameraUtil.isSupported(Parameters.FOCUS_MODE_AUTO,
Michael Kolb8872c232013-01-29 10:33:22 -0800459 mParameters.getSupportedFocusModes())) {
460 mFocusMode = Parameters.FOCUS_MODE_AUTO;
461 } else {
462 mFocusMode = mParameters.getFocusMode();
463 }
464 }
465 return mFocusMode;
466 }
467
468 public List getFocusAreas() {
469 return mFocusArea;
470 }
471
472 public List getMeteringAreas() {
473 return mMeteringArea;
474 }
475
476 public void updateFocusUI() {
477 if (!mInitialized) return;
478 // Show only focus indicator or face indicator.
Michael Kolb8872c232013-01-29 10:33:22 -0800479
480 if (mState == STATE_IDLE) {
Michael Kolb0718d482013-02-16 13:13:47 -0800481 if (mFocusDefault) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800482 mUI.clearFocus();
Michael Kolb8872c232013-01-29 10:33:22 -0800483 } else {
484 // Users touch on the preview and the indicator represents the
485 // metering area. Either focus area is not supported or
486 // autoFocus call is not required.
Michael Kolbd6954f32013-03-08 20:43:01 -0800487 mUI.onFocusStarted();
Michael Kolb8872c232013-01-29 10:33:22 -0800488 }
489 } else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800490 mUI.onFocusStarted();
Michael Kolb8872c232013-01-29 10:33:22 -0800491 } else {
Angus Kongb50b5cb2013-08-09 14:55:20 -0700492 if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800493 // TODO: check HAL behavior and decide if this can be removed.
Michael Kolbd6954f32013-03-08 20:43:01 -0800494 mUI.onFocusSucceeded(false);
Michael Kolb8872c232013-01-29 10:33:22 -0800495 } else if (mState == STATE_SUCCESS) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800496 mUI.onFocusSucceeded(false);
Michael Kolb8872c232013-01-29 10:33:22 -0800497 } else if (mState == STATE_FAIL) {
Michael Kolbd6954f32013-03-08 20:43:01 -0800498 mUI.onFocusFailed(false);
Michael Kolb8872c232013-01-29 10:33:22 -0800499 }
500 }
501 }
502
503 public void resetTouchFocus() {
504 if (!mInitialized) return;
505
506 // Put focus indicator to the center. clear reset position
Michael Kolbd6954f32013-03-08 20:43:01 -0800507 mUI.clearFocus();
Michael Kolb0718d482013-02-16 13:13:47 -0800508 // Initialize mFocusArea.
509 if (mFocusAreaSupported) {
510 initializeFocusAreas(mPreviewWidth / 2, mPreviewHeight / 2);
511 }
Doris Liucbdd3732013-10-03 11:00:59 -0700512 // Reset metering area when no specific region is selected.
Michael Kolb0718d482013-02-16 13:13:47 -0800513 if (mMeteringAreaSupported) {
Doris Liucbdd3732013-10-03 11:00:59 -0700514 resetMeteringAreas();
Michael Kolb0718d482013-02-16 13:13:47 -0800515 }
516 mFocusDefault = true;
Michael Kolb8872c232013-01-29 10:33:22 -0800517 }
518
Michael Kolb0718d482013-02-16 13:13:47 -0800519 private void calculateTapArea(int x, int y, float areaMultiple, Rect rect) {
Doris Liub3749f22013-09-25 12:22:08 -0700520 int areaSize = (int) (getAreaSize() * areaMultiple);
521 int left = CameraUtil.clamp(x - areaSize / 2, 0, mPreviewWidth - areaSize);
522 int top = CameraUtil.clamp(y - areaSize / 2, 0, mPreviewHeight - areaSize);
Michael Kolb8872c232013-01-29 10:33:22 -0800523
Doris Liub3749f22013-09-25 12:22:08 -0700524 RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
Michael Kolb8872c232013-01-29 10:33:22 -0800525 mMatrix.mapRect(rectF);
Angus Kongb50b5cb2013-08-09 14:55:20 -0700526 CameraUtil.rectFToRect(rectF, rect);
Michael Kolb8872c232013-01-29 10:33:22 -0800527 }
528
Doris Liub3749f22013-09-25 12:22:08 -0700529 private int getAreaSize() {
530 // Recommended focus area size from the manufacture is 1/8 of the image
Doris Liu2ba03262013-09-26 12:32:38 -0700531 // width (i.e. longer edge of the image)
532 return Math.max(mPreviewWidth, mPreviewHeight) / 8;
Doris Liub3749f22013-09-25 12:22:08 -0700533 }
534
Michael Kolb8872c232013-01-29 10:33:22 -0800535 /* package */ int getFocusState() {
536 return mState;
537 }
538
539 public boolean isFocusCompleted() {
540 return mState == STATE_SUCCESS || mState == STATE_FAIL;
541 }
542
543 public boolean isFocusingSnapOnFinish() {
544 return mState == STATE_FOCUSING_SNAP_ON_FINISH;
545 }
546
547 public void removeMessages() {
548 mHandler.removeMessages(RESET_TOUCH_FOCUS);
549 }
550
551 public void overrideFocusMode(String focusMode) {
552 mOverrideFocusMode = focusMode;
553 }
554
555 public void setAeAwbLock(boolean lock) {
556 mAeAwbLock = lock;
557 }
558
559 public boolean getAeAwbLock() {
560 return mAeAwbLock;
561 }
562
563 private boolean needAutoFocusCall() {
564 String focusMode = getFocusMode();
565 return !(focusMode.equals(Parameters.FOCUS_MODE_INFINITY)
566 || focusMode.equals(Parameters.FOCUS_MODE_FIXED)
567 || focusMode.equals(Parameters.FOCUS_MODE_EDOF));
568 }
569}