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.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 {
    115         public boolean hasFaces();
    116         public void clearFocus();
    117         public void setFocusPosition(int x, int y, boolean isPassiveScan, int aFsize, int aEsize);
    118         public void setFocusPosition(int x, int y, boolean isPassiveScan);
    119         public void onFocusStarted();
    120         public void onFocusSucceeded();
    121         public void onFocusFailed();
    122         public void setPassiveFocusSuccess(boolean success);
    123         public void showDebugMessage(String message);
    124         public void pauseFaceDetection();
    125         public void resumeFaceDetection();
    126     }
    127 
    128     public interface Listener {
    129         public void autoFocus();
    130         public void cancelAutoFocus();
    131         public boolean capture();
    132         public void startFaceDetection();
    133         public void stopFaceDetection();
    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;
    148         public MainHandler(FocusOverlayManager manager, Looper looper) {
    149             super(looper);
    150             mManager = new WeakReference<FocusOverlayManager>(manager);
    151         }
    152 
    153         @Override
    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 
    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 
    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. */
    201     public void setPreviewRect(Rect previewRect) {
    202         if (!mPreviewRect.equals(previewRect)) {
    203             mPreviewRect.set(previewRect);
    204             setMatrix();
    205         }
    206     }
    207 
    208     @Override
    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. */
    215     public Rect getPreviewRect() {
    216         return new Rect(mPreviewRect);
    217     }
    218 
    219     public void setMirror(boolean mirror) {
    220         mMirror = mirror;
    221         setMatrix();
    222     }
    223 
    224     public void setDisplayOrientation(int displayOrientation) {
    225         mDisplayOrientation = displayOrientation;
    226         setMatrix();
    227     }
    228 
    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 
    241     private void lockAeAwbIfNeeded() {
    242         if (mLockAeAwbNeeded && !mAeAwbLock) {
    243             mAeAwbLock = true;
    244             mListener.setFocusParameters();
    245         }
    246     }
    247 
    248     private void unlockAeAwbIfNeeded() {
    249         if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) {
    250             mAeAwbLock = false;
    251             mListener.setFocusParameters();
    252         }
    253     }
    254 
    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 
    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 
    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 
    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. */
    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. */
    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)
    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)
    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 
    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 
    436     public void onPreviewStarted() {
    437         mState = STATE_IDLE;
    438         resetTouchFocus();
    439     }
    440 
    441     public void onPreviewStopped() {
    442         // If auto focus was in progress, it would have been stopped.
    443         mState = STATE_IDLE;
    444         updateFocusUI();
    445     }
    446 
    447     public void onCameraReleased() {
    448         onPreviewStopped();
    449     }
    450 
    451     @Override
    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      */
    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      */
    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      */
    486     private void autoFocusAndCapture() {
    487         autoFocus(STATE_FOCUSING_SNAP_ON_FINISH);
    488     }
    489 
    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 
    504     private void capture() {
    505         if (mListener.capture()) {
    506             mState = STATE_IDLE;
    507             mHandler.removeMessages(RESET_TOUCH_FOCUS);
    508         }
    509     }
    510 
    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 
    558     public List<Area> getFocusAreas() {
    559         return mFocusArea;
    560     }
    561 
    562     public List<Area> getMeteringAreas() {
    563         return mMeteringArea;
    564     }
    565 
    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 
    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 
    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 
    626     /* package */ int getFocusState() {
    627         return mState;
    628     }
    629 
    630     public boolean isFocusCompleted() {
    631         return mState == STATE_SUCCESS || mState == STATE_FAIL;
    632     }
    633 
    634     public boolean isFocusingSnapOnFinish() {
    635         return mState == STATE_FOCUSING_SNAP_ON_FINISH;
    636     }
    637 
    638     public void removeMessages() {
    639         mHandler.removeMessages(RESET_TOUCH_FOCUS);
    640     }
    641 
    642     public void overrideFocusMode(CameraCapabilities.FocusMode focusMode) {
    643         mOverrideFocusMode = focusMode;
    644     }
    645 
    646     public void setAeAwbLock(boolean lock) {
    647         mAeAwbLock = lock;
    648     }
    649 
    650     public boolean getAeAwbLock() {
    651         return mAeAwbLock;
    652     }
    653 
    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