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;
291461b5333aab31faee65272d64c2ac7f9809d4d0Eino-Ville Talvalaimport android.media.MediaActionSound;
30d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.os.Handler;
31d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.os.Message;
32d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.util.Log;
33d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.view.MotionEvent;
34d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.view.View;
35d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.view.ViewGroup;
36d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.widget.RelativeLayout;
37d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
38d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport java.util.ArrayList;
39d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport java.util.List;
40d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
41d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li// A class that handles everything about focus in still picture mode.
42d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li// This also handles the metering area because it is the same as focus area.
43d480002ccad05cf992c628c72884091c36cc654cWu-cheng Lipublic class FocusManager {
4458dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li    private static final String TAG = "FocusManager";
45d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
46d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int RESET_TOUCH_FOCUS = 0;
47d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int FOCUS_BEEP_VOLUME = 100;
48d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int RESET_TOUCH_FOCUS_DELAY = 3000;
49d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
50d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private int mState = STATE_IDLE;
51d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int STATE_IDLE = 0; // Focus is not active.
52d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int STATE_FOCUSING = 1; // Focus is in progress.
53d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    // Focus is in progress and the camera should take a picture after focus finishes.
54d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int STATE_FOCUSING_SNAP_ON_FINISH = 2;
55d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int STATE_SUCCESS = 3; // Focus finishes and succeeds.
56d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static final int STATE_FAIL = 4; // Focus finishes and fails.
57d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
58d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private boolean mInitialized;
59d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private boolean mFocusAreaSupported;
6053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    private boolean mLockAeAwbNeeded;
6153be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    private boolean mAeAwbLock;
62048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang    private Matrix mMatrix;
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();
84d628e27f561c4bedf0d457f64270fc12740b5280Eino-Ville Talvala        public void playSound(int soundId);
85d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
86d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
87d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private class MainHandler extends Handler {
88d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        @Override
89d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        public void handleMessage(Message msg) {
90d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            switch (msg.what) {
91d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                case RESET_TOUCH_FOCUS: {
92d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                    cancelAutoFocus();
93d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                    mListener.startFaceDetection();
94d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                    break;
95d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                }
96d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
97d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
98d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
99d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
10060dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang    public FocusManager(ComboPreferences preferences, String[] defaultFocusModes) {
101d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mPreferences = preferences;
10260dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang        mDefaultFocusModes = defaultFocusModes;
10358dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li        mHandler = new MainHandler();
104048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        mMatrix = new Matrix();
10558dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li    }
10658dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li
10758dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li    // This has to be initialized before initialize().
10858dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li    public void initializeParameters(Parameters parameters) {
109d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mParameters = parameters;
110d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mFocusAreaSupported = (mParameters.getMaxNumFocusAreas() > 0
111d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                && isSupported(Parameters.FOCUS_MODE_AUTO,
112d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                        mParameters.getSupportedFocusModes()));
11353be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        mLockAeAwbNeeded = (mParameters.isAutoExposureLockSupported() ||
11453be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li                mParameters.isAutoWhiteBalanceLockSupported());
115d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
116d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
11720b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li    public void initialize(View focusIndicatorRotate, View previewFrame,
118048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang            FaceView faceView, Listener listener, boolean mirror, int displayOrientation) {
11920b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        mFocusIndicatorRotateLayout = focusIndicatorRotate;
12020b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        mFocusIndicator = (FocusIndicatorView) focusIndicatorRotate.findViewById(
12120b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li                R.id.focus_indicator);
122d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mPreviewFrame = previewFrame;
123d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mFaceView = faceView;
124d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mListener = listener;
125048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang
126048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        Matrix matrix = new Matrix();
127048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        Util.prepareMatrix(matrix, mirror, displayOrientation,
128048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang                previewFrame.getWidth(), previewFrame.getHeight());
129048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        // In face detection, the matrix converts the driver coordinates to UI
130048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        // coordinates. In tap focus, the inverted matrix converts the UI
131048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        // coordinates to driver coordinates.
132048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        matrix.invert(mMatrix);
133048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang
13458dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li        if (mParameters != null) {
13558dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li            mInitialized = true;
13658dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li        } else {
13758dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li            Log.e(TAG, "mParameters is not initialized.");
13858dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li        }
139d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
140d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
14153be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    public void onShutterDown() {
142d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (!mInitialized) return;
143d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
14453be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        // Lock AE and AWB so users can half-press shutter and recompose.
14553be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        if (mLockAeAwbNeeded && !mAeAwbLock) {
14653be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            mAeAwbLock = true;
14753be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            mListener.setFocusParameters();
14853be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        }
14953be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
15053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        if (needAutoFocusCall()) {
15153be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            // Do not focus if touch focus has been triggered.
15253be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            if (mState != STATE_SUCCESS && mState != STATE_FAIL) {
15353be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li                autoFocus();
154d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
155d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
156d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
157d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
15853be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    public void onShutterUp() {
15953be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        if (!mInitialized) return;
16053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
16153be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        if (needAutoFocusCall()) {
16253be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            // User releases half-pressed focus key.
16353be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            if (mState == STATE_FOCUSING || mState == STATE_SUCCESS
16453be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li                    || mState == STATE_FAIL) {
16553be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li                cancelAutoFocus();
16653be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            }
16753be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        }
16853be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
16953be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        // Unlock AE and AWB after cancelAutoFocus. Camera API does not
17053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        // guarantee setParameters can be called during autofocus.
17153be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) {
17253be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            mAeAwbLock = false;
17353be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li            mListener.setFocusParameters();
17453be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        }
17553be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    }
17653be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
177d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void doSnap() {
178d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (!mInitialized) return;
179d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
180d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // If the user has half-pressed the shutter and focus is completed, we
181d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // can take the photo right away. If the focus mode is infinity, we can
182d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // also take the photo.
18353be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        if (!needAutoFocusCall() || (mState == STATE_SUCCESS || mState == STATE_FAIL)) {
184d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            capture();
185d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        } else if (mState == STATE_FOCUSING) {
186d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // Half pressing the shutter (i.e. the focus button event) will
187d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // already have requested AF for us, so just request capture on
188d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // focus here.
189d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mState = STATE_FOCUSING_SNAP_ON_FINISH;
190d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        } else if (mState == STATE_IDLE) {
1919d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang            // We didn't do focus. This can happen if the user press focus key
1929d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang            // while the snapshot is still in progress. The user probably wants
1939d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang            // the next snapshot as soon as possible, so we just do a snapshot
1949d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang            // without focusing again.
1959d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang            capture();
196d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
197d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
198d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
199d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void onShutter() {
200d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        resetTouchFocus();
201d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        updateFocusUI();
202d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
203d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
204d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void onAutoFocus(boolean focused) {
2056bc0f740f5d7fa6eb8aa8a4ba7dd3ab4dca999d4Wu-cheng Li        if (mState == STATE_FOCUSING_SNAP_ON_FINISH) {
206d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // Take the picture no matter focus succeeds or fails. No need
207d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // to play the AF sound if we're about to play the shutter
208d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // sound.
209d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            if (focused) {
210d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mState = STATE_SUCCESS;
211d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            } else {
212d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mState = STATE_FAIL;
213d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
214d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            updateFocusUI();
215d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            capture();
216d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        } else if (mState == STATE_FOCUSING) {
217d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // This happens when (1) user is half-pressing the focus key or
218d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // (2) touch focus is triggered. Play the focus tone. Do not
219d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // take the picture now.
220d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            if (focused) {
221d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mState = STATE_SUCCESS;
222a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                // Do not play the sound in continuous autofocus mode. It does
223a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                // not do a full scan. The focus callback arrives before doSnap
224a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                // so the state is always STATE_FOCUSING.
225d628e27f561c4bedf0d457f64270fc12740b5280Eino-Ville Talvala                if (!Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.
226d628e27f561c4bedf0d457f64270fc12740b5280Eino-Ville Talvala                        equals(mFocusMode)) {
2271461b5333aab31faee65272d64c2ac7f9809d4d0Eino-Ville Talvala                    mListener.playSound(MediaActionSound.FOCUS_COMPLETE);
228d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                }
229d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            } else {
230d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mState = STATE_FAIL;
231d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
232d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            updateFocusUI();
233d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // If this is triggered by touch focus, cancel focus after a
234d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // while.
235bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            if (mFocusArea != null) {
236d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
237d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
238d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        } else if (mState == STATE_IDLE) {
239d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // User has released the focus key before focus completes.
240d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // Do nothing.
241d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
242d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
243d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
244d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public boolean onTouch(MotionEvent e) {
245d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) return false;
246d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
247d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // Let users be able to cancel previous touch focus.
248bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        if ((mFocusArea != null) && (mState == STATE_FOCUSING ||
249620e427c0aa990458d39b43477675b768d360327Wu-cheng Li                    mState == STATE_SUCCESS || mState == STATE_FAIL)) {
250d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            cancelAutoFocus();
251d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
252d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
253d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // Initialize variables.
254d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int x = Math.round(e.getX());
255d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int y = Math.round(e.getY());
25620b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        int focusWidth = mFocusIndicatorRotateLayout.getWidth();
25720b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        int focusHeight = mFocusIndicatorRotateLayout.getHeight();
258d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int previewWidth = mPreviewFrame.getWidth();
259d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int previewHeight = mPreviewFrame.getHeight();
260bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        if (mFocusArea == null) {
261bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            mFocusArea = new ArrayList<Area>();
262bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            mFocusArea.add(new Area(new Rect(), 1));
263bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            mMeteringArea = new ArrayList<Area>();
264bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            mMeteringArea.add(new Area(new Rect(), 1));
265d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
266d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
267bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        // Convert the coordinates to driver format.
268bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        // AE area is bigger because exposure is sensitive and
269bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        // easy to over- or underexposure if area is too small.
270048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        calculateTapArea(focusWidth, focusHeight, 1f, x, y, previewWidth, previewHeight,
271bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang                mFocusArea.get(0).rect);
272048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        calculateTapArea(focusWidth, focusHeight, 1.5f, x, y, previewWidth, previewHeight,
273bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang                mMeteringArea.get(0).rect);
274d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
27520b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        // Use margin to set the focus indicator to the touched area.
276d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        RelativeLayout.LayoutParams p =
27720b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li                (RelativeLayout.LayoutParams) mFocusIndicatorRotateLayout.getLayoutParams();
278d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int left = Util.clamp(x - focusWidth / 2, 0, previewWidth - focusWidth);
279d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int top = Util.clamp(y - focusHeight / 2, 0, previewHeight - focusHeight);
280d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        p.setMargins(left, top, 0, 0);
281d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // Disable "center" rule because we no longer want to put it in the center.
282d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int[] rules = p.getRules();
283d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        rules[RelativeLayout.CENTER_IN_PARENT] = 0;
28420b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        mFocusIndicatorRotateLayout.requestLayout();
285d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
286d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // Stop face detection because we want to specify focus and metering area.
287d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mListener.stopFaceDetection();
288d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
289d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // Set the focus area and metering area.
290d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mListener.setFocusParameters();
291d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (mFocusAreaSupported && (e.getAction() == MotionEvent.ACTION_UP)) {
292d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            autoFocus();
29320b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        } else {  // Just show the indicator in all other cases.
294d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            updateFocusUI();
295d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // Reset the metering area in 3 seconds.
296d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mHandler.removeMessages(RESET_TOUCH_FOCUS);
297d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
298d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
299d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
300d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        return true;
301d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
302d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
303d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void onPreviewStarted() {
304d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mState = STATE_IDLE;
305d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
306d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
307d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void onPreviewStopped() {
308d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mState = STATE_IDLE;
309d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        resetTouchFocus();
310d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // If auto focus was in progress, it would have been canceled.
311d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        updateFocusUI();
312d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
313d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
314d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void onCameraReleased() {
315d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        onPreviewStopped();
316d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
317d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
318d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private void autoFocus() {
319d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        Log.v(TAG, "Start autofocus.");
320d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mListener.autoFocus();
321d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mState = STATE_FOCUSING;
322d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // Pause the face view because the driver will keep sending face
323d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        // callbacks after the focus completes.
324d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (mFaceView != null) mFaceView.pause();
325d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        updateFocusUI();
326d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mHandler.removeMessages(RESET_TOUCH_FOCUS);
327d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
328d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
329d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private void cancelAutoFocus() {
330d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        Log.v(TAG, "Cancel autofocus.");
3315d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman
3325d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman        // Reset the tap area before calling mListener.cancelAutofocus.
3335d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman        // Otherwise, focus mode stays at auto and the tap area passed to the
3345d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman        // driver is not reset.
3355d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman        resetTouchFocus();
336d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mListener.cancelAutoFocus();
337d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (mFaceView != null) mFaceView.resume();
338d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mState = STATE_IDLE;
339d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        updateFocusUI();
340d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mHandler.removeMessages(RESET_TOUCH_FOCUS);
341d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
342d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
343d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private void capture() {
344d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (mListener.capture()) {
345d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mState = STATE_IDLE;
346d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mHandler.removeMessages(RESET_TOUCH_FOCUS);
347d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
348d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
349d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
35058dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li    // This can only be called after mParameters is initialized.
351d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public String getFocusMode() {
352d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (mOverrideFocusMode != null) return mOverrideFocusMode;
35360dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang        List<String> supportedFocusModes = mParameters.getSupportedFocusModes();
354d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
35530e2c49eedfbce51be7458161829a750f809d56dWu-cheng Li        if (mFocusAreaSupported && mFocusArea != null) {
3566bc0f740f5d7fa6eb8aa8a4ba7dd3ab4dca999d4Wu-cheng Li            // Always use autofocus in tap-to-focus.
357d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mFocusMode = Parameters.FOCUS_MODE_AUTO;
358d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        } else {
359d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // The default is continuous autofocus.
360d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            mFocusMode = mPreferences.getString(
36160dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                    CameraSettings.KEY_FOCUS_MODE, null);
36260dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang
36360dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang            // Try to find a supported focus mode from the default list.
36460dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang            if (mFocusMode == null) {
36560dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                for (int i = 0; i < mDefaultFocusModes.length; i++) {
36660dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                    String mode = mDefaultFocusModes[i];
36760dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                    if (isSupported(mode, supportedFocusModes)) {
36860dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                        mFocusMode = mode;
36960dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                        break;
37060dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                    }
37160dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang                }
37260dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang            }
373d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
37460dc073ff3087af41f9cf3b738eaa74bb2212f95Chih-Chung Chang        if (!isSupported(mFocusMode, supportedFocusModes)) {
375d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // For some reasons, the driver does not support the current
376d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            // focus mode. Fall back to auto.
377d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            if (isSupported(Parameters.FOCUS_MODE_AUTO,
378d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                    mParameters.getSupportedFocusModes())) {
379d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mFocusMode = Parameters.FOCUS_MODE_AUTO;
380d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            } else {
381d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                mFocusMode = mParameters.getFocusMode();
382d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
383d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
384d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        return mFocusMode;
385d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
386d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
387bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang    public List<Area> getFocusAreas() {
388bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        return mFocusArea;
389bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang    }
390bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang
391bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang    public List<Area> getMeteringAreas() {
392bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        return mMeteringArea;
393d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
394d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
395d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void updateFocusUI() {
396d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (!mInitialized) return;
397d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
39820b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        // Set the length of focus indicator according to preview frame size.
399d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int len = Math.min(mPreviewFrame.getWidth(), mPreviewFrame.getHeight()) / 4;
400bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        ViewGroup.LayoutParams layout = mFocusIndicator.getLayoutParams();
401d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        layout.width = len;
402d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        layout.height = len;
403d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
40420b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        // Show only focus indicator or face indicator.
40520b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        boolean faceExists = (mFaceView != null && mFaceView.faceExists());
40620b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        FocusIndicator focusIndicator = (faceExists) ? mFaceView : mFocusIndicator;
40720b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li
408d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (mState == STATE_IDLE) {
409bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            if (mFocusArea == null) {
41020b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li                focusIndicator.clear();
411d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            } else {
41220b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li                // Users touch on the preview and the indicator represents the
413d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                // metering area. Either focus area is not supported or
414d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li                // autoFocus call is not required.
41520b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li                focusIndicator.showStart();
416d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li            }
41720b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        } else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
41820b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li            focusIndicator.showStart();
419a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li        } else {
420a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            // In CAF, do not show success or failure because it only returns
421a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            // the focus status. It does not do a full scan. So the result is
422a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            // failure most of the time.
423a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            if (Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)) {
424a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                focusIndicator.showStart();
425a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            } else if (mState == STATE_SUCCESS) {
426a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                focusIndicator.showSuccess();
427a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            } else if (mState == STATE_FAIL) {
428a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li                focusIndicator.showFail();
429a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li            }
430d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        }
431d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
432d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
433d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void resetTouchFocus() {
434d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        if (!mInitialized) return;
435d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
43620b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li        // Put focus indicator to the center.
437d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        RelativeLayout.LayoutParams p =
43820b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li                (RelativeLayout.LayoutParams) mFocusIndicatorRotateLayout.getLayoutParams();
439d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        int[] rules = p.getRules();
440d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        rules[RelativeLayout.CENTER_IN_PARENT] = RelativeLayout.TRUE;
441d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        p.setMargins(0, 0, 0, 0);
442d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
443bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        mFocusArea = null;
444bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        mMeteringArea = null;
445bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang    }
446bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang
447048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang    public void calculateTapArea(int focusWidth, int focusHeight, float areaMultiple,
448bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang            int x, int y, int previewWidth, int previewHeight, Rect rect) {
449bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        int areaWidth = (int)(focusWidth * areaMultiple);
450bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang        int areaHeight = (int)(focusHeight * areaMultiple);
451048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        int left = Util.clamp(x - areaWidth / 2, 0, previewWidth - areaWidth);
452048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        int top = Util.clamp(y - areaHeight / 2, 0, previewHeight - areaHeight);
453048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang
454048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        RectF rectF = new RectF(left, top, left + areaWidth, top + areaHeight);
455048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        mMatrix.mapRect(rectF);
456048edf2ef22607b85bc4b062e2af71804f5b3530Chih-yu Huang        Util.rectFToRect(rectF, rect);
457d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
458d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
459d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public boolean isFocusCompleted() {
460d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        return mState == STATE_SUCCESS || mState == STATE_FAIL;
461d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
462d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
46372eaced345def3746038f1aba3efe2845b274884Wu-cheng Li    public boolean isFocusingSnapOnFinish() {
46472eaced345def3746038f1aba3efe2845b274884Wu-cheng Li        return mState == STATE_FOCUSING_SNAP_ON_FINISH;
46572eaced345def3746038f1aba3efe2845b274884Wu-cheng Li    }
46672eaced345def3746038f1aba3efe2845b274884Wu-cheng Li
467d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void removeMessages() {
468d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mHandler.removeMessages(RESET_TOUCH_FOCUS);
469d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
470d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
471d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    public void overrideFocusMode(String focusMode) {
472d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        mOverrideFocusMode = focusMode;
473d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
474d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li
47553be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    public void setAeAwbLock(boolean lock) {
47653be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        mAeAwbLock = lock;
47753be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    }
47853be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
47953be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    public boolean getAeAwbLock() {
48053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        return mAeAwbLock;
48153be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    }
48253be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
483d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    private static boolean isSupported(String value, List<String> supported) {
484d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li        return supported == null ? false : supported.indexOf(value) >= 0;
485d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li    }
48653be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li
48753be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    private boolean needAutoFocusCall() {
48853be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        String focusMode = getFocusMode();
48953be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li        return !(focusMode.equals(Parameters.FOCUS_MODE_INFINITY)
49053be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li                || focusMode.equals(Parameters.FOCUS_MODE_FIXED)
49153be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li                || focusMode.equals(Parameters.FOCUS_MODE_EDOF));
49253be34deae057cfa297c3ee73eee91f880272650Wu-cheng Li    }
493d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li}
494