FocusManager.java revision 72eaced345def3746038f1aba3efe2845b274884
1d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li/*
2d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li * Copyright (C) 2011 The Android Open Source Project
3d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li *
4d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li * Licensed under the Apache License, Version 2.0 (the "License");
5d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li * you may not use this file except in compliance with the License.
6d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li * You may obtain a copy of the License at
7d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li *
8d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li *      http://www.apache.org/licenses/LICENSE-2.0
9d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li *
10d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li * Unless required by applicable law or agreed to in writing, software
11d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li * distributed under the License is distributed on an "AS IS" BASIS,
12d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li * See the License for the specific language governing permissions and
14d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li * limitations under the License.
15d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li */
16d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
17d480002ccad05cf992c628c72884091c36cc654cWu-cheng Lipackage com.android.camera;
18d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
19d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport com.android.camera.ui.FaceView;
2020b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Liimport com.android.camera.ui.FocusIndicator;
2120b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Liimport com.android.camera.ui.FocusIndicatorView;
22d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
231acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Liimport android.content.res.AssetFileDescriptor;
24048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huangimport android.graphics.Matrix;
25d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.graphics.Rect;
26048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huangimport android.graphics.RectF;
27d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.hardware.Camera.Area;
28d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.hardware.Camera.Parameters;
29d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.os.Handler;
30d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.os.Message;
31d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.util.Log;
32d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.view.MotionEvent;
33d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.view.View;
34d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.view.ViewGroup;
35d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.widget.RelativeLayout;
36d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
37d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport java.util.ArrayList;
38d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport java.util.List;
39d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
40d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li// A class that handles everything about focus in still picture mode.
41d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li// This also handles the metering area because it is the same as focus area.
42d480002ccad05cf992c628c72884091c36cc654cWu-cheng Lipublic class FocusManager {
4358dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li    private static final String TAG = "FocusManager";
44d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
45d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int RESET_TOUCH_FOCUS = 0;
46d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int FOCUS_BEEP_VOLUME = 100;
47d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int RESET_TOUCH_FOCUS_DELAY = 3000;
48d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
49d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private int mState = STATE_IDLE;
50d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int STATE_IDLE = 0; // Focus is not active.
51d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int STATE_FOCUSING = 1; // Focus is in progress.
52d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    // Focus is in progress and the camera should take a picture after focus finishes.
53d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int STATE_FOCUSING_SNAP_ON_FINISH = 2;
54d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int STATE_SUCCESS = 3; // Focus finishes and succeeds.
55d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int STATE_FAIL = 4; // Focus finishes and fails.
56d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
57d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private boolean mInitialized;
58d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private boolean mFocusAreaSupported;
5953be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    private boolean mLockAeAwbNeeded;
6053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    private boolean mAeAwbLock;
61048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang    private Matrix mMatrix;
621acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li    private SoundPlayer mSoundPlayer;
6320b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li    private View mFocusIndicatorRotateLayout;
6420b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li    private FocusIndicatorView mFocusIndicator;
65d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private View mPreviewFrame;
66d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private FaceView mFaceView;
67bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang    private List<Area> mFocusArea; // focus area in driver format
68bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang    private List<Area> mMeteringArea; // metering area in driver format
69d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private String mFocusMode;
7060dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang    private String[] mDefaultFocusModes;
71d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private String mOverrideFocusMode;
72d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private Parameters mParameters;
73d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private ComboPreferences mPreferences;
74d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private Handler mHandler;
75d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    Listener mListener;
76d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
77d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public interface Listener {
78d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        public void autoFocus();
79d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        public void cancelAutoFocus();
80d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        public boolean capture();
81d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        public void startFaceDetection();
82d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        public void stopFaceDetection();
83d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        public void setFocusParameters();
84d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
85d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
86d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private class MainHandler extends Handler {
87d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        @Override
88d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        public void handleMessage(Message msg) {
89d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            switch (msg.what) {
90d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                case RESET_TOUCH_FOCUS: {
91d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                    cancelAutoFocus();
92d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                    mListener.startFaceDetection();
93d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                    break;
94d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                }
95d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
96d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
97d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
98d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
9960dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang    public FocusManager(ComboPreferences preferences, String[] defaultFocusModes) {
100d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mPreferences = preferences;
10160dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang        mDefaultFocusModes = defaultFocusModes;
10258dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li        mHandler = new MainHandler();
103048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        mMatrix = new Matrix();
10458dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li    }
10558dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li
10658dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li    // This has to be initialized before initialize().
10758dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li    public void initializeParameters(Parameters parameters) {
108d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mParameters = parameters;
109d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mFocusAreaSupported = (mParameters.getMaxNumFocusAreas() > 0
110d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                && isSupported(Parameters.FOCUS_MODE_AUTO,
111d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                        mParameters.getSupportedFocusModes()));
11253be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        mLockAeAwbNeeded = (mParameters.isAutoExposureLockSupported() ||
11353be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li                mParameters.isAutoWhiteBalanceLockSupported());
114d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
115d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
11620b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li    public void initialize(View focusIndicatorRotate, View previewFrame,
117048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang            FaceView faceView, Listener listener, boolean mirror, int displayOrientation) {
11820b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        mFocusIndicatorRotateLayout = focusIndicatorRotate;
11920b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        mFocusIndicator = (FocusIndicatorView) focusIndicatorRotate.findViewById(
12020b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li                R.id.focus_indicator);
121d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mPreviewFrame = previewFrame;
122d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mFaceView = faceView;
123d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mListener = listener;
124048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang
125048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        Matrix matrix = new Matrix();
126048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        Util.prepareMatrix(matrix, mirror, displayOrientation,
127048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang                previewFrame.getWidth(), previewFrame.getHeight());
128048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        // In face detection, the matrix converts the driver coordinates to UI
129048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        // coordinates. In tap focus, the inverted matrix converts the UI
130048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        // coordinates to driver coordinates.
131048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        matrix.invert(mMatrix);
132048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang
13358dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li        if (mParameters != null) {
13458dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li            mInitialized = true;
13558dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li        } else {
13658dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li            Log.e(TAG, "mParameters is not initialized.");
13758dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li        }
138d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
139d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
14053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    public void onShutterDown() {
141d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (!mInitialized) return;
142d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
14353be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        // Lock AE and AWB so users can half-press shutter and recompose.
14453be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        if (mLockAeAwbNeeded && !mAeAwbLock) {
14553be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            mAeAwbLock = true;
14653be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            mListener.setFocusParameters();
14753be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        }
14853be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
14953be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        if (needAutoFocusCall()) {
15053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            // Do not focus if touch focus has been triggered.
15153be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            if (mState != STATE_SUCCESS && mState != STATE_FAIL) {
15253be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li                autoFocus();
153d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
154d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
155d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
156d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
15753be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    public void onShutterUp() {
15853be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        if (!mInitialized) return;
15953be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
16053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        if (needAutoFocusCall()) {
16153be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            // User releases half-pressed focus key.
16253be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            if (mState == STATE_FOCUSING || mState == STATE_SUCCESS
16353be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li                    || mState == STATE_FAIL) {
16453be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li                cancelAutoFocus();
16553be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            }
16653be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        }
16753be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
16853be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        // Unlock AE and AWB after cancelAutoFocus. Camera API does not
16953be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        // guarantee setParameters can be called during autofocus.
17053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) {
17153be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            mAeAwbLock = false;
17253be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            mListener.setFocusParameters();
17353be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        }
17453be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    }
17553be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
176d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void doSnap() {
177d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (!mInitialized) return;
178d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
179d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // If the user has half-pressed the shutter and focus is completed, we
180d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // can take the photo right away. If the focus mode is infinity, we can
181d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // also take the photo.
18253be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        if (!needAutoFocusCall() || (mState == STATE_SUCCESS || mState == STATE_FAIL)) {
183d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            capture();
184d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        } else if (mState == STATE_FOCUSING) {
185d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // Half pressing the shutter (i.e. the focus button event) will
186d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // already have requested AF for us, so just request capture on
187d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // focus here.
188d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mState = STATE_FOCUSING_SNAP_ON_FINISH;
189d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        } else if (mState == STATE_IDLE) {
1909d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang            // We didn't do focus. This can happen if the user press focus key
1919d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang            // while the snapshot is still in progress. The user probably wants
1929d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang            // the next snapshot as soon as possible, so we just do a snapshot
1939d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang            // without focusing again.
1949d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang            capture();
195d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
196d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
197d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
198d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void onShutter() {
199d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        resetTouchFocus();
200d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        updateFocusUI();
201d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
202d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
203d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void onAutoFocus(boolean focused) {
2046bc0f740f5d7fa6eb8aa8a4ba7dd3ab4dca999d4Wu-cheng Li        if (mState == STATE_FOCUSING_SNAP_ON_FINISH) {
205d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // Take the picture no matter focus succeeds or fails. No need
206d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // to play the AF sound if we're about to play the shutter
207d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // sound.
208d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            if (focused) {
209d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mState = STATE_SUCCESS;
210d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            } else {
211d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mState = STATE_FAIL;
212d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
213d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            updateFocusUI();
214d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            capture();
215d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        } else if (mState == STATE_FOCUSING) {
216d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // This happens when (1) user is half-pressing the focus key or
217d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // (2) touch focus is triggered. Play the focus tone. Do not
218d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // take the picture now.
219d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            if (focused) {
220d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mState = STATE_SUCCESS;
221a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                // Do not play the sound in continuous autofocus mode. It does
222a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                // not do a full scan. The focus callback arrives before doSnap
223a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                // so the state is always STATE_FOCUSING.
224a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                if (!Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)
2251acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li                        && mSoundPlayer != null) {
2261acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li                    mSoundPlayer.play();
227d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                }
228d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            } else {
229d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mState = STATE_FAIL;
230d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
231d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            updateFocusUI();
232d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // If this is triggered by touch focus, cancel focus after a
233d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // while.
234bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            if (mFocusArea != null) {
235d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
236d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
237d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        } else if (mState == STATE_IDLE) {
238d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // User has released the focus key before focus completes.
239d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // Do nothing.
240d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
241d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
242d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
243d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public boolean onTouch(MotionEvent e) {
244d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) return false;
245d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
246d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // Let users be able to cancel previous touch focus.
247bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        if ((mFocusArea != null) && (mState == STATE_FOCUSING ||
248620e427c0aa990458d39b43477675b768d360327Wu-cheng Li                    mState == STATE_SUCCESS || mState == STATE_FAIL)) {
249d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            cancelAutoFocus();
250d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
251d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
252d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // Initialize variables.
253d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int x = Math.round(e.getX());
254d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int y = Math.round(e.getY());
25520b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        int focusWidth = mFocusIndicatorRotateLayout.getWidth();
25620b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        int focusHeight = mFocusIndicatorRotateLayout.getHeight();
257d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int previewWidth = mPreviewFrame.getWidth();
258d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int previewHeight = mPreviewFrame.getHeight();
259bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        if (mFocusArea == null) {
260bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            mFocusArea = new ArrayList<Area>();
261bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            mFocusArea.add(new Area(new Rect(), 1));
262bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            mMeteringArea = new ArrayList<Area>();
263bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            mMeteringArea.add(new Area(new Rect(), 1));
264d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
265d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
266bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        // Convert the coordinates to driver format.
267bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        // AE area is bigger because exposure is sensitive and
268bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        // easy to over- or underexposure if area is too small.
269048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        calculateTapArea(focusWidth, focusHeight, 1f, x, y, previewWidth, previewHeight,
270bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang                mFocusArea.get(0).rect);
271048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        calculateTapArea(focusWidth, focusHeight, 1.5f, x, y, previewWidth, previewHeight,
272bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang                mMeteringArea.get(0).rect);
273d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
27420b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        // Use margin to set the focus indicator to the touched area.
275d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        RelativeLayout.LayoutParams p =
27620b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li                (RelativeLayout.LayoutParams) mFocusIndicatorRotateLayout.getLayoutParams();
277d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int left = Util.clamp(x - focusWidth / 2, 0, previewWidth - focusWidth);
278d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int top = Util.clamp(y - focusHeight / 2, 0, previewHeight - focusHeight);
279d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        p.setMargins(left, top, 0, 0);
280d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // Disable "center" rule because we no longer want to put it in the center.
281d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int[] rules = p.getRules();
282d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        rules[RelativeLayout.CENTER_IN_PARENT] = 0;
28320b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        mFocusIndicatorRotateLayout.requestLayout();
284d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
285d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // Stop face detection because we want to specify focus and metering area.
286d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mListener.stopFaceDetection();
287d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
288d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // Set the focus area and metering area.
289d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mListener.setFocusParameters();
290d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (mFocusAreaSupported && (e.getAction() == MotionEvent.ACTION_UP)) {
291d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            autoFocus();
29220b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        } else {  // Just show the indicator in all other cases.
293d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            updateFocusUI();
294d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // Reset the metering area in 3 seconds.
295d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mHandler.removeMessages(RESET_TOUCH_FOCUS);
296d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
297d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
298d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
299d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        return true;
300d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
301d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
302d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void onPreviewStarted() {
303d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mState = STATE_IDLE;
304d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
305d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
306d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void onPreviewStopped() {
307d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mState = STATE_IDLE;
308d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        resetTouchFocus();
309d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // If auto focus was in progress, it would have been canceled.
310d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        updateFocusUI();
311d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
312d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
313d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void onCameraReleased() {
314d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        onPreviewStopped();
315d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
316d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
317d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private void autoFocus() {
318d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        Log.v(TAG, "Start autofocus.");
319d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mListener.autoFocus();
320d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mState = STATE_FOCUSING;
321d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // Pause the face view because the driver will keep sending face
322d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // callbacks after the focus completes.
323d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (mFaceView != null) mFaceView.pause();
324d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        updateFocusUI();
325d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mHandler.removeMessages(RESET_TOUCH_FOCUS);
326d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
327d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
328d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private void cancelAutoFocus() {
329d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        Log.v(TAG, "Cancel autofocus.");
3305d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman
3315d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman        // Reset the tap area before calling mListener.cancelAutofocus.
3325d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman        // Otherwise, focus mode stays at auto and the tap area passed to the
3335d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman        // driver is not reset.
3345d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman        resetTouchFocus();
335d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mListener.cancelAutoFocus();
336d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (mFaceView != null) mFaceView.resume();
337d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mState = STATE_IDLE;
338d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        updateFocusUI();
339d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mHandler.removeMessages(RESET_TOUCH_FOCUS);
340d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
341d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
342d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private void capture() {
343d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (mListener.capture()) {
344d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mState = STATE_IDLE;
345d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mHandler.removeMessages(RESET_TOUCH_FOCUS);
346d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
347d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
348d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
3491acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li    public void initializeSoundPlayer(AssetFileDescriptor fd) {
3501acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li        mSoundPlayer = new SoundPlayer(fd);
351d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
352d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
3531acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li    public void releaseSoundPlayer() {
3541acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li        if (mSoundPlayer != null) {
3551acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li            mSoundPlayer.release();
3561acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li            mSoundPlayer = null;
357d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
358d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
359d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
3601acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li
36158dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li    // This can only be called after mParameters is initialized.
362d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public String getFocusMode() {
363d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (mOverrideFocusMode != null) return mOverrideFocusMode;
36460dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang        List<String> supportedFocusModes = mParameters.getSupportedFocusModes();
365d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
36630e2c49eedfbce51be7458161829a750f809d56dWu-cheng Li        if (mFocusAreaSupported && mFocusArea != null) {
3676bc0f740f5d7fa6eb8aa8a4ba7dd3ab4dca999d4Wu-cheng Li            // Always use autofocus in tap-to-focus.
368d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mFocusMode = Parameters.FOCUS_MODE_AUTO;
369d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        } else {
370d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // The default is continuous autofocus.
371d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mFocusMode = mPreferences.getString(
37260dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                    CameraSettings.KEY_FOCUS_MODE, null);
37360dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang
37460dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang            // Try to find a supported focus mode from the default list.
37560dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang            if (mFocusMode == null) {
37660dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                for (int i = 0; i < mDefaultFocusModes.length; i++) {
37760dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                    String mode = mDefaultFocusModes[i];
37860dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                    if (isSupported(mode, supportedFocusModes)) {
37960dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                        mFocusMode = mode;
38060dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                        break;
38160dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                    }
38260dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                }
38360dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang            }
384d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
38560dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang        if (!isSupported(mFocusMode, supportedFocusModes)) {
386d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // For some reasons, the driver does not support the current
387d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // focus mode. Fall back to auto.
388d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            if (isSupported(Parameters.FOCUS_MODE_AUTO,
389d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                    mParameters.getSupportedFocusModes())) {
390d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mFocusMode = Parameters.FOCUS_MODE_AUTO;
391d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            } else {
392d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mFocusMode = mParameters.getFocusMode();
393d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
394d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
395d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        return mFocusMode;
396d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
397d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
398bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang    public List<Area> getFocusAreas() {
399bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        return mFocusArea;
400bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang    }
401bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang
402bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang    public List<Area> getMeteringAreas() {
403bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        return mMeteringArea;
404d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
405d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
406d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void updateFocusUI() {
407d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (!mInitialized) return;
408d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
40920b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        // Set the length of focus indicator according to preview frame size.
410d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int len = Math.min(mPreviewFrame.getWidth(), mPreviewFrame.getHeight()) / 4;
411bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        ViewGroup.LayoutParams layout = mFocusIndicator.getLayoutParams();
412d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        layout.width = len;
413d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        layout.height = len;
414d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
41520b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        // Show only focus indicator or face indicator.
41620b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        boolean faceExists = (mFaceView != null && mFaceView.faceExists());
41720b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        FocusIndicator focusIndicator = (faceExists) ? mFaceView : mFocusIndicator;
41820b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li
419d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (mState == STATE_IDLE) {
420bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            if (mFocusArea == null) {
42120b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li                focusIndicator.clear();
422d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            } else {
42320b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li                // Users touch on the preview and the indicator represents the
424d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                // metering area. Either focus area is not supported or
425d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                // autoFocus call is not required.
42620b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li                focusIndicator.showStart();
427d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
42820b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        } else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
42920b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li            focusIndicator.showStart();
430a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li        } else {
431a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            // In CAF, do not show success or failure because it only returns
432a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            // the focus status. It does not do a full scan. So the result is
433a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            // failure most of the time.
434a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            if (Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)) {
435a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                focusIndicator.showStart();
436a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            } else if (mState == STATE_SUCCESS) {
437a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                focusIndicator.showSuccess();
438a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            } else if (mState == STATE_FAIL) {
439a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                focusIndicator.showFail();
440a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            }
441d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
442d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
443d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
444d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void resetTouchFocus() {
445d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (!mInitialized) return;
446d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
44720b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        // Put focus indicator to the center.
448d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        RelativeLayout.LayoutParams p =
44920b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li                (RelativeLayout.LayoutParams) mFocusIndicatorRotateLayout.getLayoutParams();
450d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int[] rules = p.getRules();
451d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        rules[RelativeLayout.CENTER_IN_PARENT] = RelativeLayout.TRUE;
452d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        p.setMargins(0, 0, 0, 0);
453d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
454bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        mFocusArea = null;
455bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        mMeteringArea = null;
456bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang    }
457bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang
458048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang    public void calculateTapArea(int focusWidth, int focusHeight, float areaMultiple,
459bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            int x, int y, int previewWidth, int previewHeight, Rect rect) {
460bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        int areaWidth = (int)(focusWidth * areaMultiple);
461bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        int areaHeight = (int)(focusHeight * areaMultiple);
462048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        int left = Util.clamp(x - areaWidth / 2, 0, previewWidth - areaWidth);
463048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        int top = Util.clamp(y - areaHeight / 2, 0, previewHeight - areaHeight);
464048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang
465048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        RectF rectF = new RectF(left, top, left + areaWidth, top + areaHeight);
466048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        mMatrix.mapRect(rectF);
467048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        Util.rectFToRect(rectF, rect);
468d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
469d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
470d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public boolean isFocusCompleted() {
471d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        return mState == STATE_SUCCESS || mState == STATE_FAIL;
472d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
473d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
47472eaced345def3746038f1aba3efe2845b274884Wu-cheng Li    public boolean isFocusingSnapOnFinish() {
47572eaced345def3746038f1aba3efe2845b274884Wu-cheng Li        return mState == STATE_FOCUSING_SNAP_ON_FINISH;
47672eaced345def3746038f1aba3efe2845b274884Wu-cheng Li    }
47772eaced345def3746038f1aba3efe2845b274884Wu-cheng Li
478d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void removeMessages() {
479d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mHandler.removeMessages(RESET_TOUCH_FOCUS);
480d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
481d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
482d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void overrideFocusMode(String focusMode) {
483d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mOverrideFocusMode = focusMode;
484d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
485d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
48653be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    public void setAeAwbLock(boolean lock) {
48753be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        mAeAwbLock = lock;
48853be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    }
48953be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
49053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    public boolean getAeAwbLock() {
49153be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        return mAeAwbLock;
49253be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    }
49353be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
494d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static boolean isSupported(String value, List<String> supported) {
495d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        return supported == null ? false : supported.indexOf(value) >= 0;
496d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
49753be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
49853be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    private boolean needAutoFocusCall() {
49953be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        String focusMode = getFocusMode();
50053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        return !(focusMode.equals(Parameters.FOCUS_MODE_INFINITY)
50153be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li                || focusMode.equals(Parameters.FOCUS_MODE_FIXED)
50253be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li                || focusMode.equals(Parameters.FOCUS_MODE_EDOF));
50353be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    }
504d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li}
505