FocusManager.java revision 9d80a29af1ed57eded5d20af51ef5e704b32b452
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; 24d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.graphics.Rect; 25d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.hardware.Camera.Area; 26d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.hardware.Camera.Parameters; 27d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.os.Handler; 28d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.os.Message; 29d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.util.Log; 30d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.view.MotionEvent; 31d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.view.View; 32d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.view.ViewGroup; 33d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport android.widget.RelativeLayout; 34d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 35d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport java.util.ArrayList; 36d480002ccad05cf992c628c72884091c36cc654cWu-cheng Liimport java.util.List; 37d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 38d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li// A class that handles everything about focus in still picture mode. 39d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li// This also handles the metering area because it is the same as focus area. 40d480002ccad05cf992c628c72884091c36cc654cWu-cheng Lipublic class FocusManager { 4158dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li private static final String TAG = "FocusManager"; 42d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 43d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private static final int RESET_TOUCH_FOCUS = 0; 44d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private static final int FOCUS_BEEP_VOLUME = 100; 45d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private static final int RESET_TOUCH_FOCUS_DELAY = 3000; 46d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 47d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private int mState = STATE_IDLE; 48d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private static final int STATE_IDLE = 0; // Focus is not active. 49d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private static final int STATE_FOCUSING = 1; // Focus is in progress. 50d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Focus is in progress and the camera should take a picture after focus finishes. 51d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private static final int STATE_FOCUSING_SNAP_ON_FINISH = 2; 52d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private static final int STATE_SUCCESS = 3; // Focus finishes and succeeds. 53d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private static final int STATE_FAIL = 4; // Focus finishes and fails. 54d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 55d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private boolean mInitialized; 56d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private boolean mFocusAreaSupported; 571acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li private SoundPlayer mSoundPlayer; 5820b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li private View mFocusIndicatorRotateLayout; 5920b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li private FocusIndicatorView mFocusIndicator; 60d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private View mPreviewFrame; 61d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private FaceView mFaceView; 62bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang private List<Area> mFocusArea; // focus area in driver format 63bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang private List<Area> mMeteringArea; // metering area in driver format 64d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private String mFocusMode; 65d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private String mDefaultFocusMode; 66d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private String mOverrideFocusMode; 67d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private Parameters mParameters; 68d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private ComboPreferences mPreferences; 69d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private Handler mHandler; 70d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li Listener mListener; 71d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 72d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public interface Listener { 73d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void autoFocus(); 74d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void cancelAutoFocus(); 75d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public boolean capture(); 76d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void startFaceDetection(); 77d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void stopFaceDetection(); 78d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void setFocusParameters(); 79d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 80d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 81d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private class MainHandler extends Handler { 82d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li @Override 83d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void handleMessage(Message msg) { 84d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li switch (msg.what) { 85d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li case RESET_TOUCH_FOCUS: { 86d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li cancelAutoFocus(); 87d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mListener.startFaceDetection(); 88d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li break; 89d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 90d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 91d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 92d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 93d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 9458dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li public FocusManager(ComboPreferences preferences, String defaultFocusMode) { 95d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mPreferences = preferences; 96d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mDefaultFocusMode = defaultFocusMode; 9758dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li mHandler = new MainHandler(); 9858dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li } 9958dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li 10058dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li // This has to be initialized before initialize(). 10158dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li public void initializeParameters(Parameters parameters) { 102d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mParameters = parameters; 103d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mFocusAreaSupported = (mParameters.getMaxNumFocusAreas() > 0 104d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li && isSupported(Parameters.FOCUS_MODE_AUTO, 105d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mParameters.getSupportedFocusModes())); 106d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 107d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 10820b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li public void initialize(View focusIndicatorRotate, View previewFrame, 109d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li FaceView faceView, Listener listener) { 11020b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li mFocusIndicatorRotateLayout = focusIndicatorRotate; 11120b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li mFocusIndicator = (FocusIndicatorView) focusIndicatorRotate.findViewById( 11220b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li R.id.focus_indicator); 113d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mPreviewFrame = previewFrame; 114d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mFaceView = faceView; 115d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mListener = listener; 11658dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li if (mParameters != null) { 11758dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li mInitialized = true; 11858dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li } else { 11958dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li Log.e(TAG, "mParameters is not initialized."); 12058dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li } 121d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 122d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 123d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void doFocus(boolean pressed) { 124d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (!mInitialized) return; 125d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 126d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (!(getFocusMode().equals(Parameters.FOCUS_MODE_INFINITY) 127d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li || getFocusMode().equals(Parameters.FOCUS_MODE_FIXED) 128d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li || getFocusMode().equals(Parameters.FOCUS_MODE_EDOF))) { 129d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (pressed) { // Focus key down. 130d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Do not focus if touch focus has been triggered. 131d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (mState != STATE_SUCCESS && mState != STATE_FAIL) { 132d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li autoFocus(); 133d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 134d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } else { // Focus key up. 135d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // User releases half-pressed focus key. 136d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (mState == STATE_FOCUSING || mState == STATE_SUCCESS 137d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li || mState == STATE_FAIL) { 138d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li cancelAutoFocus(); 139d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 140d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 141d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 142d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 143d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 144d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void doSnap() { 145d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (!mInitialized) return; 146d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 147d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // If the user has half-pressed the shutter and focus is completed, we 148d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // can take the photo right away. If the focus mode is infinity, we can 149d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // also take the photo. 150d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (getFocusMode().equals(Parameters.FOCUS_MODE_INFINITY) 151d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li || getFocusMode().equals(Parameters.FOCUS_MODE_FIXED) 152d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li || getFocusMode().equals(Parameters.FOCUS_MODE_EDOF) 153d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li || (mState == STATE_SUCCESS 154d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li || mState == STATE_FAIL)) { 155d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li capture(); 156d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } else if (mState == STATE_FOCUSING) { 157d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Half pressing the shutter (i.e. the focus button event) will 158d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // already have requested AF for us, so just request capture on 159d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // focus here. 160d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mState = STATE_FOCUSING_SNAP_ON_FINISH; 161d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } else if (mState == STATE_IDLE) { 1629d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang // We didn't do focus. This can happen if the user press focus key 1639d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang // while the snapshot is still in progress. The user probably wants 1649d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang // the next snapshot as soon as possible, so we just do a snapshot 1659d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang // without focusing again. 1669d80a29af1ed57eded5d20af51ef5e704b32b452Chih-Chung Chang capture(); 167d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 168d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 169d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 170d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void onShutter() { 171d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li resetTouchFocus(); 172d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li updateFocusUI(); 173d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 174d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 175d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void onAutoFocus(boolean focused) { 1766bc0f740f5d7fa6eb8aa8a4ba7dd3ab4dca999d4Wu-cheng Li if (mState == STATE_FOCUSING_SNAP_ON_FINISH) { 177d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Take the picture no matter focus succeeds or fails. No need 178d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // to play the AF sound if we're about to play the shutter 179d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // sound. 180d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (focused) { 181d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mState = STATE_SUCCESS; 182d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } else { 183d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mState = STATE_FAIL; 184d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 185d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li updateFocusUI(); 186d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li capture(); 187d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } else if (mState == STATE_FOCUSING) { 188d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // This happens when (1) user is half-pressing the focus key or 189d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // (2) touch focus is triggered. Play the focus tone. Do not 190d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // take the picture now. 191d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (focused) { 192d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mState = STATE_SUCCESS; 193a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li // Do not play the sound in continuous autofocus mode. It does 194a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li // not do a full scan. The focus callback arrives before doSnap 195a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li // so the state is always STATE_FOCUSING. 196a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li if (!Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode) 1971acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li && mSoundPlayer != null) { 1981acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li mSoundPlayer.play(); 199d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 200d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } else { 201d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mState = STATE_FAIL; 202d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 203d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li updateFocusUI(); 204d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // If this is triggered by touch focus, cancel focus after a 205d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // while. 206bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang if (mFocusArea != null) { 207d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY); 208d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 209d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } else if (mState == STATE_IDLE) { 210d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // User has released the focus key before focus completes. 211d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Do nothing. 212d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 213d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 214d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 215d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public boolean onTouch(MotionEvent e) { 216d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) return false; 217d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 218d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Let users be able to cancel previous touch focus. 219bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang if ((mFocusArea != null) && (mState == STATE_FOCUSING || 220620e427c0aa990458d39b43477675b768d360327Wu-cheng Li mState == STATE_SUCCESS || mState == STATE_FAIL)) { 221d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li cancelAutoFocus(); 222d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 223d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 224d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Initialize variables. 225d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li int x = Math.round(e.getX()); 226d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li int y = Math.round(e.getY()); 22720b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li int focusWidth = mFocusIndicatorRotateLayout.getWidth(); 22820b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li int focusHeight = mFocusIndicatorRotateLayout.getHeight(); 229d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li int previewWidth = mPreviewFrame.getWidth(); 230d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li int previewHeight = mPreviewFrame.getHeight(); 231bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang if (mFocusArea == null) { 232bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang mFocusArea = new ArrayList<Area>(); 233bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang mFocusArea.add(new Area(new Rect(), 1)); 234bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang mMeteringArea = new ArrayList<Area>(); 235bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang mMeteringArea.add(new Area(new Rect(), 1)); 236d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 237d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 238bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang // Convert the coordinates to driver format. 239bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang // AE area is bigger because exposure is sensitive and 240bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang // easy to over- or underexposure if area is too small. 241bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang calculateTapArea(focusWidth, focusHeight, 1, x, y, previewWidth, previewHeight, 242bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang mFocusArea.get(0).rect); 243bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang calculateTapArea(focusWidth, focusHeight, 1.5, x, y, previewWidth, previewHeight, 244bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang mMeteringArea.get(0).rect); 245d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 24620b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li // Use margin to set the focus indicator to the touched area. 247d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li RelativeLayout.LayoutParams p = 24820b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li (RelativeLayout.LayoutParams) mFocusIndicatorRotateLayout.getLayoutParams(); 249d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li int left = Util.clamp(x - focusWidth / 2, 0, previewWidth - focusWidth); 250d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li int top = Util.clamp(y - focusHeight / 2, 0, previewHeight - focusHeight); 251d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li p.setMargins(left, top, 0, 0); 252d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Disable "center" rule because we no longer want to put it in the center. 253d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li int[] rules = p.getRules(); 254d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li rules[RelativeLayout.CENTER_IN_PARENT] = 0; 25520b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li mFocusIndicatorRotateLayout.requestLayout(); 256d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 257d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Stop face detection because we want to specify focus and metering area. 258d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mListener.stopFaceDetection(); 259d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 260d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Set the focus area and metering area. 261d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mListener.setFocusParameters(); 262d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (mFocusAreaSupported && (e.getAction() == MotionEvent.ACTION_UP)) { 263d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li autoFocus(); 26420b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li } else { // Just show the indicator in all other cases. 265d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li updateFocusUI(); 266d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Reset the metering area in 3 seconds. 267d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mHandler.removeMessages(RESET_TOUCH_FOCUS); 268d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY); 269d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 270d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 271d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li return true; 272d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 273d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 274d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void onPreviewStarted() { 275d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mState = STATE_IDLE; 276d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 277d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 278d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void onPreviewStopped() { 279d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mState = STATE_IDLE; 280d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li resetTouchFocus(); 281d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // If auto focus was in progress, it would have been canceled. 282d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li updateFocusUI(); 283d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 284d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 285d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void onCameraReleased() { 286d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li onPreviewStopped(); 287d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 288d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 289d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private void autoFocus() { 290d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li Log.v(TAG, "Start autofocus."); 291d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mListener.autoFocus(); 292d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mState = STATE_FOCUSING; 293d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Pause the face view because the driver will keep sending face 294d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // callbacks after the focus completes. 295d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (mFaceView != null) mFaceView.pause(); 296d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li updateFocusUI(); 297d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mHandler.removeMessages(RESET_TOUCH_FOCUS); 298d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 299d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 300d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private void cancelAutoFocus() { 301d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li Log.v(TAG, "Cancel autofocus."); 3025d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman 3035d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman // Reset the tap area before calling mListener.cancelAutofocus. 3045d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman // Otherwise, focus mode stays at auto and the tap area passed to the 3055d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman // driver is not reset. 3065d4972e63a1f81139c6503fd433f06c77276fc38Sundar Raman resetTouchFocus(); 307d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mListener.cancelAutoFocus(); 308d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (mFaceView != null) mFaceView.resume(); 309d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mState = STATE_IDLE; 310d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li updateFocusUI(); 311d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mHandler.removeMessages(RESET_TOUCH_FOCUS); 312d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 313d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 314d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private void capture() { 315d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (mListener.capture()) { 316d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mState = STATE_IDLE; 317d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mHandler.removeMessages(RESET_TOUCH_FOCUS); 318d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 319d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 320d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 3211acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li public void initializeSoundPlayer(AssetFileDescriptor fd) { 3221acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li mSoundPlayer = new SoundPlayer(fd); 323d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 324d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 3251acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li public void releaseSoundPlayer() { 3261acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li if (mSoundPlayer != null) { 3271acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li mSoundPlayer.release(); 3281acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li mSoundPlayer = null; 329d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 330d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 331d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 3321acf35ce296efc6b3ad823a9500f79f71c545201Wu-cheng Li 33358dadc3028b3af2e9895089e1b39ad1ab982ece2Wu-cheng Li // This can only be called after mParameters is initialized. 334d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public String getFocusMode() { 335d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (mOverrideFocusMode != null) return mOverrideFocusMode; 336d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 337bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang if (mFocusAreaSupported && mFocusArea != null) { 3386bc0f740f5d7fa6eb8aa8a4ba7dd3ab4dca999d4Wu-cheng Li // Always use autofocus in tap-to-focus. 339d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mFocusMode = Parameters.FOCUS_MODE_AUTO; 340d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } else { 341d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // The default is continuous autofocus. 342d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mFocusMode = mPreferences.getString( 343d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li CameraSettings.KEY_FOCUS_MODE, mDefaultFocusMode); 344d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 345d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (!isSupported(mFocusMode, mParameters.getSupportedFocusModes())) { 346d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // For some reasons, the driver does not support the current 347d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // focus mode. Fall back to auto. 348d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (isSupported(Parameters.FOCUS_MODE_AUTO, 349d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mParameters.getSupportedFocusModes())) { 350d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mFocusMode = Parameters.FOCUS_MODE_AUTO; 351d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } else { 352d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mFocusMode = mParameters.getFocusMode(); 353d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 354d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 355d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li return mFocusMode; 356d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 357d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 358bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang public List<Area> getFocusAreas() { 359bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang return mFocusArea; 360bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang } 361bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang 362bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang public List<Area> getMeteringAreas() { 363bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang return mMeteringArea; 364d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 365d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 366d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void updateFocusUI() { 367d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (!mInitialized) return; 368d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 36920b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li // Set the length of focus indicator according to preview frame size. 370d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li int len = Math.min(mPreviewFrame.getWidth(), mPreviewFrame.getHeight()) / 4; 371bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang ViewGroup.LayoutParams layout = mFocusIndicator.getLayoutParams(); 372d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li layout.width = len; 373d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li layout.height = len; 374d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 37520b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li // Show only focus indicator or face indicator. 37620b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li boolean faceExists = (mFaceView != null && mFaceView.faceExists()); 37720b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li FocusIndicator focusIndicator = (faceExists) ? mFaceView : mFocusIndicator; 37820b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li 379d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (mState == STATE_IDLE) { 380bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang if (mFocusArea == null) { 38120b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li focusIndicator.clear(); 382d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } else { 38320b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li // Users touch on the preview and the indicator represents the 384d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // metering area. Either focus area is not supported or 385d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // autoFocus call is not required. 38620b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li focusIndicator.showStart(); 387d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 38820b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li } else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) { 38920b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li focusIndicator.showStart(); 390a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li } else { 391a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li // In CAF, do not show success or failure because it only returns 392a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li // the focus status. It does not do a full scan. So the result is 393a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li // failure most of the time. 394a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li if (Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)) { 395a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li focusIndicator.showStart(); 396a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li } else if (mState == STATE_SUCCESS) { 397a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li focusIndicator.showSuccess(); 398a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li } else if (mState == STATE_FAIL) { 399a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li focusIndicator.showFail(); 400a7a50a45c75585e350eb730574b1e531468e8b18Wu-cheng Li } 401d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 402d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 403d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 404d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void resetTouchFocus() { 405d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li if (!mInitialized) return; 406d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 40720b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li // Put focus indicator to the center. 408d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li RelativeLayout.LayoutParams p = 40920b3c3526ebb8d8a6873f7a1110f23847a843515Wu-cheng Li (RelativeLayout.LayoutParams) mFocusIndicatorRotateLayout.getLayoutParams(); 410d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li int[] rules = p.getRules(); 411d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li rules[RelativeLayout.CENTER_IN_PARENT] = RelativeLayout.TRUE; 412d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li p.setMargins(0, 0, 0, 0); 413d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 414bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang mFocusArea = null; 415bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang mMeteringArea = null; 416bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang } 417bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang 418bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang public void calculateTapArea(int focusWidth, int focusHeight, double areaMultiple, 419bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang int x, int y, int previewWidth, int previewHeight, Rect rect) { 420bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang int areaWidth = (int)(focusWidth * areaMultiple); 421bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang int areaHeight = (int)(focusHeight * areaMultiple); 422bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang int areaLeft = Util.clamp(x - areaWidth / 2, 0, previewWidth - areaWidth); 423bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang int areaTop = Util.clamp(y - areaHeight / 2, 0, previewHeight - areaHeight); 424bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang convertToFocusArea(areaLeft, areaTop, areaWidth, areaHeight, previewWidth, previewHeight, 425bd29d3c5d59b375d77334aaa426545dc781b95fdChih-yu Huang rect); 426d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 427d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 428d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li // Convert the touch point to the focus area in driver format. 429d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public static void convertToFocusArea(int left, int top, int focusWidth, int focusHeight, 430d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li int previewWidth, int previewHeight, Rect rect) { 431d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li rect.left = Math.round((float) left / previewWidth * 2000 - 1000); 432d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li rect.top = Math.round((float) top / previewHeight * 2000 - 1000); 433d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li rect.right = Math.round((float) (left + focusWidth) / previewWidth * 2000 - 1000); 434d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li rect.bottom = Math.round((float) (top + focusHeight) / previewHeight * 2000 - 1000); 435d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 436d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 437d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public boolean isFocusCompleted() { 438d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li return mState == STATE_SUCCESS || mState == STATE_FAIL; 439d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 440d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 441d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void removeMessages() { 442d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mHandler.removeMessages(RESET_TOUCH_FOCUS); 443d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 444d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 445d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li public void overrideFocusMode(String focusMode) { 446d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li mOverrideFocusMode = focusMode; 447d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 448d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li 449d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li private static boolean isSupported(String value, List<String> supported) { 450d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li return supported == null ? false : supported.indexOf(value) >= 0; 451d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li } 452d480002ccad05cf992c628c72884091c36cc654cWu-cheng Li} 453