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