1 /*
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 
17 package com.android.camera;
18 
19 import android.annotation.TargetApi;
20 import android.graphics.Matrix;
21 import android.graphics.Rect;
22 import android.graphics.RectF;
23 import android.hardware.Camera.Area;
24 import android.os.Build;
25 import android.os.Handler;
26 import android.os.Looper;
27 import android.os.Message;
28 
29 import com.android.camera.app.AppController;
30 import com.android.camera.app.MotionManager;
31 import com.android.camera.debug.Log;
32 import com.android.camera.one.Settings3A;
33 import com.android.camera.settings.Keys;
34 import com.android.camera.settings.SettingsManager;
35 import com.android.camera.ui.PreviewStatusListener;
36 import com.android.camera.ui.TouchCoordinate;
37 import com.android.camera.util.CameraUtil;
38 import com.android.camera.util.UsageStatistics;
39 import com.android.ex.camera2.portability.CameraCapabilities;
40 
41 import java.lang.ref.WeakReference;
42 import java.util.ArrayList;
43 import java.util.List;
44 
45 /* A class that handles everything about focus in still picture mode.
46  * This also handles the metering area because it is the same as focus area.
47  *
48  * The test cases:
49  * (1) The camera has continuous autofocus. Move the camera. Take a picture when
50  *     CAF is not in progress.
51  * (2) The camera has continuous autofocus. Move the camera. Take a picture when
52  *     CAF is in progress.
53  * (3) The camera has face detection. Point the camera at some faces. Hold the
54  *     shutter. Release to take a picture.
55  * (4) The camera has face detection. Point the camera at some faces. Single tap
56  *     the shutter to take a picture.
57  * (5) The camera has autofocus. Single tap the shutter to take a picture.
58  * (6) The camera has autofocus. Hold the shutter. Release to take a picture.
59  * (7) The camera has no autofocus. Single tap the shutter and take a picture.
60  * (8) The camera has autofocus and supports focus area. Touch the screen to
61  *     trigger autofocus. Take a picture.
62  * (9) The camera has autofocus and supports focus area. Touch the screen to
63  *     trigger autofocus. Wait until it times out.
64  * (10) The camera has no autofocus and supports metering area. Touch the screen
65  *     to change metering area.
66  */
67 public class FocusOverlayManager implements PreviewStatusListener.PreviewAreaChangedListener,
68         MotionManager.MotionListener {
69     private static final Log.Tag TAG = new Log.Tag("FocusOverlayMgr");
70 
71     private static final int RESET_TOUCH_FOCUS = 0;
72 
73     private static final int RESET_TOUCH_FOCUS_DELAY_MILLIS = Settings3A.getFocusHoldMillis();
74 
75     public static final float AF_REGION_BOX = Settings3A.getAutoFocusRegionWidth();
76     public static final float AE_REGION_BOX = Settings3A.getMeteringRegionWidth();
77 
78     private int mState = STATE_IDLE;
79     private static final int STATE_IDLE = 0; // Focus is not active.
80     private static final int STATE_FOCUSING = 1; // Focus is in progress.
81     // Focus is in progress and the camera should take a picture after focus finishes.
82     private static final int STATE_FOCUSING_SNAP_ON_FINISH = 2;
83     private static final int STATE_SUCCESS = 3; // Focus finishes and succeeds.
84     private static final int STATE_FAIL = 4; // Focus finishes and fails.
85 
86     private boolean mInitialized;
87     private boolean mFocusAreaSupported;
88     private boolean mMeteringAreaSupported;
89     private boolean mLockAeAwbNeeded;
90     private boolean mAeAwbLock;
91     private final Matrix mMatrix;
92 
93     private boolean mMirror; // true if the camera is front-facing.
94     private int mDisplayOrientation;
95     private List<Area> mFocusArea; // focus area in driver format
96     private List<Area> mMeteringArea; // metering area in driver format
97     private CameraCapabilities.FocusMode mFocusMode;
98     private final List<CameraCapabilities.FocusMode> mDefaultFocusModes;
99     private CameraCapabilities.FocusMode mOverrideFocusMode;
100     private CameraCapabilities mCapabilities;
101     private final AppController mAppController;
102     private final SettingsManager mSettingsManager;
103     private final Handler mHandler;
104     Listener mListener;
105     private boolean mPreviousMoving;
106     private final FocusUI mUI;
107     private final Rect mPreviewRect = new Rect(0, 0, 0, 0);
108     private boolean mFocusLocked;
109 
110     /** Manual tap to focus parameters */
111     private TouchCoordinate mTouchCoordinate;
112     private long mTouchTime;
113 
114     public  interface FocusUI {
hasFaces()115         public boolean hasFaces();
clearFocus()116         public void clearFocus();
setFocusPosition(int x, int y, boolean isPassiveScan, int aFsize, int aEsize)117         public void setFocusPosition(int x, int y, boolean isPassiveScan, int aFsize, int aEsize);
setFocusPosition(int x, int y, boolean isPassiveScan)118         public void setFocusPosition(int x, int y, boolean isPassiveScan);
onFocusStarted()119         public void onFocusStarted();
onFocusSucceeded()120         public void onFocusSucceeded();
onFocusFailed()121         public void onFocusFailed();
setPassiveFocusSuccess(boolean success)122         public void setPassiveFocusSuccess(boolean success);
showDebugMessage(String message)123         public void showDebugMessage(String message);
pauseFaceDetection()124         public void pauseFaceDetection();
resumeFaceDetection()125         public void resumeFaceDetection();
126     }
127 
128     public interface Listener {
autoFocus()129         public void autoFocus();
cancelAutoFocus()130         public void cancelAutoFocus();
capture()131         public boolean capture();
startFaceDetection()132         public void startFaceDetection();
stopFaceDetection()133         public void stopFaceDetection();
setFocusParameters()134         public void setFocusParameters();
135     }
136 
137     /**
138      * TODO: Refactor this so that we either don't need a handler or make
139      * mListener not be the activity.
140      */
141     private static class MainHandler extends Handler {
142         /**
143          * The outer mListener at the moment is actually the CameraActivity,
144          * which we would leak if we didn't break the GC path here using a
145          * WeakReference.
146          */
147         final WeakReference<FocusOverlayManager> mManager;
MainHandler(FocusOverlayManager manager, Looper looper)148         public MainHandler(FocusOverlayManager manager, Looper looper) {
149             super(looper);
150             mManager = new WeakReference<FocusOverlayManager>(manager);
151         }
152 
153         @Override
handleMessage(Message msg)154         public void handleMessage(Message msg) {
155             FocusOverlayManager manager = mManager.get();
156             if (manager == null) {
157                 return;
158             }
159 
160             switch (msg.what) {
161                 case RESET_TOUCH_FOCUS: {
162                     manager.cancelAutoFocus();
163                     manager.mListener.startFaceDetection();
164                     break;
165                 }
166             }
167         }
168     }
169 
FocusOverlayManager(AppController appController, List<CameraCapabilities.FocusMode> defaultFocusModes, CameraCapabilities capabilities, Listener listener, boolean mirror, Looper looper, FocusUI ui)170     public FocusOverlayManager(AppController appController,
171             List<CameraCapabilities.FocusMode> defaultFocusModes, CameraCapabilities capabilities,
172             Listener listener, boolean mirror, Looper looper, FocusUI ui) {
173         mAppController = appController;
174         mSettingsManager = appController.getSettingsManager();
175         mHandler = new MainHandler(this, looper);
176         mMatrix = new Matrix();
177         mDefaultFocusModes = new ArrayList<CameraCapabilities.FocusMode>(defaultFocusModes);
178         updateCapabilities(capabilities);
179         mListener = listener;
180         setMirror(mirror);
181         mUI = ui;
182         mFocusLocked = false;
183     }
184 
updateCapabilities(CameraCapabilities capabilities)185     public void updateCapabilities(CameraCapabilities capabilities) {
186         // capabilities can only be null when onConfigurationChanged is called
187         // before camera is open. We will just return in this case, because
188         // capabilities will be set again later with the right capabilities after
189         // camera is open.
190         if (capabilities == null) {
191             return;
192         }
193         mCapabilities = capabilities;
194         mFocusAreaSupported = mCapabilities.supports(CameraCapabilities.Feature.FOCUS_AREA);
195         mMeteringAreaSupported = mCapabilities.supports(CameraCapabilities.Feature.METERING_AREA);
196         mLockAeAwbNeeded = (mCapabilities.supports(CameraCapabilities.Feature.AUTO_EXPOSURE_LOCK)
197                 || mCapabilities.supports(CameraCapabilities.Feature.AUTO_WHITE_BALANCE_LOCK));
198     }
199 
200     /** This setter should be the only way to mutate mPreviewRect. */
setPreviewRect(Rect previewRect)201     public void setPreviewRect(Rect previewRect) {
202         if (!mPreviewRect.equals(previewRect)) {
203             mPreviewRect.set(previewRect);
204             setMatrix();
205         }
206     }
207 
208     @Override
onPreviewAreaChanged(RectF previewArea)209     public void onPreviewAreaChanged(RectF previewArea) {
210         setPreviewRect(CameraUtil.rectFToRect(previewArea));
211     }
212 
213     /** Returns a copy of mPreviewRect so that outside class cannot modify preview
214      *  rect except deliberately doing so through the setter. */
getPreviewRect()215     public Rect getPreviewRect() {
216         return new Rect(mPreviewRect);
217     }
218 
setMirror(boolean mirror)219     public void setMirror(boolean mirror) {
220         mMirror = mirror;
221         setMatrix();
222     }
223 
setDisplayOrientation(int displayOrientation)224     public void setDisplayOrientation(int displayOrientation) {
225         mDisplayOrientation = displayOrientation;
226         setMatrix();
227     }
228 
setMatrix()229     private void setMatrix() {
230         if (mPreviewRect.width() != 0 && mPreviewRect.height() != 0) {
231             Matrix matrix = new Matrix();
232             CameraUtil.prepareMatrix(matrix, mMirror, mDisplayOrientation, getPreviewRect());
233             // In face detection, the matrix converts the driver coordinates to UI
234             // coordinates. In tap focus, the inverted matrix converts the UI
235             // coordinates to driver coordinates.
236             matrix.invert(mMatrix);
237             mInitialized = true;
238         }
239     }
240 
lockAeAwbIfNeeded()241     private void lockAeAwbIfNeeded() {
242         if (mLockAeAwbNeeded && !mAeAwbLock) {
243             mAeAwbLock = true;
244             mListener.setFocusParameters();
245         }
246     }
247 
unlockAeAwbIfNeeded()248     private void unlockAeAwbIfNeeded() {
249         if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) {
250             mAeAwbLock = false;
251             mListener.setFocusParameters();
252         }
253     }
254 
onShutterUp(CameraCapabilities.FocusMode currentFocusMode)255     public void onShutterUp(CameraCapabilities.FocusMode currentFocusMode) {
256         if (!mInitialized) {
257             return;
258         }
259 
260         if (needAutoFocusCall(currentFocusMode)) {
261             // User releases half-pressed focus key.
262             if (mState == STATE_FOCUSING || mState == STATE_SUCCESS
263                     || mState == STATE_FAIL) {
264                 cancelAutoFocus();
265             }
266         }
267 
268         // Unlock AE and AWB after cancelAutoFocus. Camera API does not
269         // guarantee setParameters can be called during autofocus.
270         unlockAeAwbIfNeeded();
271     }
272 
focusAndCapture(CameraCapabilities.FocusMode currentFocusMode)273     public void focusAndCapture(CameraCapabilities.FocusMode currentFocusMode) {
274         if (!mInitialized) {
275             return;
276         }
277 
278         if (!needAutoFocusCall(currentFocusMode)) {
279             // Focus is not needed.
280             capture();
281         } else if (mState == STATE_SUCCESS || mState == STATE_FAIL) {
282             // Focus is done already.
283             capture();
284         } else if (mState == STATE_FOCUSING) {
285             // Still focusing and will not trigger snap upon finish.
286             mState = STATE_FOCUSING_SNAP_ON_FINISH;
287         } else if (mState == STATE_IDLE) {
288             autoFocusAndCapture();
289         }
290     }
291 
onAutoFocus(boolean focused, boolean shutterButtonPressed)292     public void onAutoFocus(boolean focused, boolean shutterButtonPressed) {
293         if (mState == STATE_FOCUSING_SNAP_ON_FINISH) {
294             // Take the picture no matter focus succeeds or fails. No need
295             // to play the AF sound if we're about to play the shutter
296             // sound.
297             if (focused) {
298                 mState = STATE_SUCCESS;
299             } else {
300                 mState = STATE_FAIL;
301             }
302             updateFocusUI();
303             capture();
304         } else if (mState == STATE_FOCUSING) {
305             // This happens when (1) user is half-pressing the focus key or
306             // (2) touch focus is triggered. Play the focus tone. Do not
307             // take the picture now.
308             if (focused) {
309                 mState = STATE_SUCCESS;
310             } else {
311                 mState = STATE_FAIL;
312             }
313             updateFocusUI();
314             // If this is triggered by touch focus, cancel focus after a
315             // while.
316             if (mFocusArea != null) {
317                 mFocusLocked = true;
318                 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY_MILLIS);
319             }
320             if (shutterButtonPressed) {
321                 // Lock AE & AWB so users can half-press shutter and recompose.
322                 lockAeAwbIfNeeded();
323             }
324         } else if (mState == STATE_IDLE) {
325             // User has released the focus key before focus completes.
326             // Do nothing.
327         }
328     }
329 
onAutoFocusMoving(boolean moving)330     public void onAutoFocusMoving(boolean moving) {
331         if (!mInitialized) {
332             return;
333         }
334 
335 
336         // Ignore if the camera has detected some faces.
337         if (mUI.hasFaces()) {
338             mUI.clearFocus();
339             return;
340         }
341 
342         // Ignore if we have requested autofocus. This method only handles
343         // continuous autofocus.
344         if (mState != STATE_IDLE) {
345             return;
346         }
347 
348         // animate on false->true trasition only b/8219520
349         if (moving && !mPreviousMoving) {
350             // Auto focus at the center of the preview.
351             mUI.setFocusPosition(mPreviewRect.centerX(), mPreviewRect.centerY(), true,
352                     getAFRegionEdge(), getAERegionEdge());
353             mUI.onFocusStarted();
354         } else if (!moving) {
355             mUI.onFocusSucceeded();
356         }
357         mPreviousMoving = moving;
358     }
359 
360     /** Returns width of auto focus region in pixels. */
getAFRegionEdge()361     private int getAFRegionEdge() {
362         return (int) (Math.min(mPreviewRect.width(), mPreviewRect.height()) * AF_REGION_BOX);
363     }
364 
365     /** Returns width of metering region in pixels. */
getAERegionEdge()366     private int getAERegionEdge() {
367         return (int) (Math.min(mPreviewRect.width(), mPreviewRect.height()) * AE_REGION_BOX);
368     }
369 
370     @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
initializeFocusAreas(int x, int y)371     private void initializeFocusAreas(int x, int y) {
372         if (mFocusArea == null) {
373             mFocusArea = new ArrayList<Area>();
374             mFocusArea.add(new Area(new Rect(), 1));
375         }
376 
377         // Convert the coordinates to driver format.
378         calculateTapArea(x, y, getAFRegionEdge(), mFocusArea.get(0).rect);
379     }
380 
381     @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
initializeMeteringAreas(int x, int y)382     private void initializeMeteringAreas(int x, int y) {
383         if (mMeteringArea == null) {
384             mMeteringArea = new ArrayList<Area>();
385             mMeteringArea.add(new Area(new Rect(), 1));
386         }
387 
388         // Convert the coordinates to driver format.
389         calculateTapArea(x, y, getAERegionEdge(), mMeteringArea.get(0).rect);
390     }
391 
onSingleTapUp(int x, int y)392     public void onSingleTapUp(int x, int y) {
393         if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
394             return;
395         }
396 
397         // Let users be able to cancel previous touch focus.
398         if ((mFocusArea != null) && (mState == STATE_FOCUSING ||
399                     mState == STATE_SUCCESS || mState == STATE_FAIL)) {
400             cancelAutoFocus();
401         }
402         if (mPreviewRect.width() == 0 || mPreviewRect.height() == 0) {
403             return;
404         }
405         // Initialize variables.
406         // Initialize mFocusArea.
407         if (mFocusAreaSupported) {
408             initializeFocusAreas(x, y);
409         }
410         // Initialize mMeteringArea.
411         if (mMeteringAreaSupported) {
412             initializeMeteringAreas(x, y);
413         }
414 
415         // Use margin to set the focus indicator to the touched area.
416         mUI.setFocusPosition(x, y, false, getAFRegionEdge(), getAERegionEdge());
417         // Log manual tap to focus.
418         mTouchCoordinate = new TouchCoordinate(x, y, mPreviewRect.width(), mPreviewRect.height());
419         mTouchTime = System.currentTimeMillis();
420 
421         // Stop face detection because we want to specify focus and metering area.
422         mListener.stopFaceDetection();
423 
424         // Set the focus area and metering area.
425         mListener.setFocusParameters();
426         if (mFocusAreaSupported) {
427             autoFocus();
428         } else {  // Just show the indicator in all other cases.
429             updateFocusUI();
430             // Reset the metering area in 4 seconds.
431             mHandler.removeMessages(RESET_TOUCH_FOCUS);
432             mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY_MILLIS);
433         }
434     }
435 
onPreviewStarted()436     public void onPreviewStarted() {
437         mState = STATE_IDLE;
438         resetTouchFocus();
439     }
440 
onPreviewStopped()441     public void onPreviewStopped() {
442         // If auto focus was in progress, it would have been stopped.
443         mState = STATE_IDLE;
444         updateFocusUI();
445     }
446 
onCameraReleased()447     public void onCameraReleased() {
448         onPreviewStopped();
449     }
450 
451     @Override
onMoving()452     public void onMoving() {
453         if (mFocusLocked) {
454             Log.d(TAG, "onMoving: Early focus unlock.");
455             cancelAutoFocus();
456         }
457     }
458 
459     /**
460      * Triggers the autofocus and sets the specified state.
461      *
462      * @param focusingState The state to use when focus is in progress.
463      */
autoFocus(int focusingState)464     private void autoFocus(int focusingState) {
465         mListener.autoFocus();
466         mState = focusingState;
467         // Pause the face view because the driver will keep sending face
468         // callbacks after the focus completes.
469         mUI.pauseFaceDetection();
470         updateFocusUI();
471         mHandler.removeMessages(RESET_TOUCH_FOCUS);
472     }
473 
474     /**
475      * Triggers the autofocus and set the state to indicate the focus is in
476      * progress.
477      */
autoFocus()478     private void autoFocus() {
479         autoFocus(STATE_FOCUSING);
480     }
481 
482     /**
483      * Triggers the autofocus and set the state to which a capture will happen
484      * in the following autofocus callback.
485      */
autoFocusAndCapture()486     private void autoFocusAndCapture() {
487         autoFocus(STATE_FOCUSING_SNAP_ON_FINISH);
488     }
489 
cancelAutoFocus()490     private void cancelAutoFocus() {
491         Log.v(TAG, "Cancel autofocus.");
492         // Reset the tap area before calling mListener.cancelAutofocus.
493         // Otherwise, focus mode stays at auto and the tap area passed to the
494         // driver is not reset.
495         resetTouchFocus();
496         mListener.cancelAutoFocus();
497         mUI.resumeFaceDetection();
498         mState = STATE_IDLE;
499         mFocusLocked = false;
500         updateFocusUI();
501         mHandler.removeMessages(RESET_TOUCH_FOCUS);
502     }
503 
capture()504     private void capture() {
505         if (mListener.capture()) {
506             mState = STATE_IDLE;
507             mHandler.removeMessages(RESET_TOUCH_FOCUS);
508         }
509     }
510 
getFocusMode( final CameraCapabilities.FocusMode currentFocusMode)511     public CameraCapabilities.FocusMode getFocusMode(
512             final CameraCapabilities.FocusMode currentFocusMode) {
513         if (mOverrideFocusMode != null) {
514             Log.v(TAG, "returning override focus: " + mOverrideFocusMode);
515             return mOverrideFocusMode;
516         }
517         if (mCapabilities == null) {
518             Log.v(TAG, "no capabilities, returning default AUTO focus mode");
519             return CameraCapabilities.FocusMode.AUTO;
520         }
521 
522         if (mFocusAreaSupported && mFocusArea != null) {
523             Log.v(TAG, "in tap to focus, returning AUTO focus mode");
524             // Always use autofocus in tap-to-focus.
525             mFocusMode = CameraCapabilities.FocusMode.AUTO;
526         } else {
527             String focusSetting = mSettingsManager.getString(mAppController.getCameraScope(),
528                     Keys.KEY_FOCUS_MODE);
529             Log.v(TAG, "stored focus setting for camera: " + focusSetting);
530             // The default is continuous autofocus.
531             mFocusMode = mCapabilities.getStringifier().focusModeFromString(focusSetting);
532             Log.v(TAG, "focus mode resolved from setting: " + mFocusMode);
533             // Try to find a supported focus mode from the default list.
534             if (mFocusMode == null) {
535                 for (CameraCapabilities.FocusMode mode : mDefaultFocusModes) {
536                     if (mCapabilities.supports(mode)) {
537                         mFocusMode = mode;
538                         Log.v(TAG, "selected supported focus mode from default list" + mode);
539                         break;
540                     }
541                 }
542             }
543         }
544         if (!mCapabilities.supports(mFocusMode)) {
545             // For some reasons, the driver does not support the current
546             // focus mode. Fall back to auto.
547             if (mCapabilities.supports(CameraCapabilities.FocusMode.AUTO)) {
548                 Log.v(TAG, "no supported focus mode, falling back to AUTO");
549                 mFocusMode = CameraCapabilities.FocusMode.AUTO;
550             } else {
551                 Log.v(TAG, "no supported focus mode, falling back to current: " + currentFocusMode);
552                 mFocusMode = currentFocusMode;
553             }
554         }
555         return mFocusMode;
556     }
557 
getFocusAreas()558     public List<Area> getFocusAreas() {
559         return mFocusArea;
560     }
561 
getMeteringAreas()562     public List<Area> getMeteringAreas() {
563         return mMeteringArea;
564     }
565 
updateFocusUI()566     public void updateFocusUI() {
567         if (!mInitialized) {
568             // Show only focus indicator or face indicator.
569             return;
570         }
571         if (mState == STATE_IDLE) {
572             if (mFocusArea == null) {
573                 mUI.clearFocus();
574             } else {
575                 // Users touch on the preview and the indicator represents the
576                 // metering area. Either focus area is not supported or
577                 // autoFocus call is not required.
578                 mUI.onFocusStarted();
579             }
580         } else if (mState == STATE_FOCUSING) {
581             mUI.onFocusStarted();
582         } else {
583             if (mFocusMode == CameraCapabilities.FocusMode.CONTINUOUS_PICTURE) {
584                 // TODO: check HAL behavior and decide if this can be removed.
585                 mUI.onFocusSucceeded();
586             } else if (mState == STATE_SUCCESS) {
587                 mUI.onFocusSucceeded();
588             } else if (mState == STATE_FAIL) {
589                 mUI.onFocusFailed();
590             }
591         }
592     }
593 
resetTouchFocus()594     public void resetTouchFocus() {
595         if (!mInitialized) {
596             return;
597         }
598 
599         // Put focus indicator to the center. clear reset position
600         mUI.clearFocus();
601         // Initialize mFocusArea.
602         mFocusArea = null;
603         mMeteringArea = null;
604         // This will cause current module to call getFocusAreas() and
605         // getMeteringAreas() and send updated regions to camera.
606         mListener.setFocusParameters();
607 
608         if (mTouchCoordinate != null) {
609             UsageStatistics.instance().tapToFocus(mTouchCoordinate,
610                     0.001f * (System.currentTimeMillis() - mTouchTime));
611             mTouchCoordinate = null;
612         }
613     }
614 
calculateTapArea(int x, int y, int size, Rect rect)615     private void calculateTapArea(int x, int y, int size, Rect rect) {
616         int left = CameraUtil.clamp(x - size / 2, mPreviewRect.left,
617                 mPreviewRect.right - size);
618         int top = CameraUtil.clamp(y - size / 2, mPreviewRect.top,
619                 mPreviewRect.bottom - size);
620 
621         RectF rectF = new RectF(left, top, left + size, top + size);
622         mMatrix.mapRect(rectF);
623         CameraUtil.rectFToRect(rectF, rect);
624     }
625 
getFocusState()626     /* package */ int getFocusState() {
627         return mState;
628     }
629 
isFocusCompleted()630     public boolean isFocusCompleted() {
631         return mState == STATE_SUCCESS || mState == STATE_FAIL;
632     }
633 
isFocusingSnapOnFinish()634     public boolean isFocusingSnapOnFinish() {
635         return mState == STATE_FOCUSING_SNAP_ON_FINISH;
636     }
637 
removeMessages()638     public void removeMessages() {
639         mHandler.removeMessages(RESET_TOUCH_FOCUS);
640     }
641 
overrideFocusMode(CameraCapabilities.FocusMode focusMode)642     public void overrideFocusMode(CameraCapabilities.FocusMode focusMode) {
643         mOverrideFocusMode = focusMode;
644     }
645 
setAeAwbLock(boolean lock)646     public void setAeAwbLock(boolean lock) {
647         mAeAwbLock = lock;
648     }
649 
getAeAwbLock()650     public boolean getAeAwbLock() {
651         return mAeAwbLock;
652     }
653 
needAutoFocusCall(CameraCapabilities.FocusMode focusMode)654     private boolean needAutoFocusCall(CameraCapabilities.FocusMode focusMode) {
655         return !(focusMode == CameraCapabilities.FocusMode.INFINITY
656                 || focusMode == CameraCapabilities.FocusMode.FIXED
657                 || focusMode == CameraCapabilities.FocusMode.EXTENDED_DOF);
658     }
659 }
660