blob: 92372e4d3901b8e303ad827ece21ce1f77e0c9a6 [file] [log] [blame]
Michael Kolb8872c232013-01-29 10:33:22 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera;
18
Michael Kolb8872c232013-01-29 10:33:22 -080019import android.graphics.Rect;
20import android.graphics.RectF;
21import android.hardware.Camera.Area;
Michael Kolb8872c232013-01-29 10:33:22 -080022import android.os.Handler;
23import android.os.Looper;
24import android.os.Message;
Michael Kolb8872c232013-01-29 10:33:22 -080025
Erin Dahlgren6190c362014-06-13 14:12:08 -070026import com.android.camera.app.AppController;
Kevin Gabayanfb333362014-06-02 14:48:20 -070027import com.android.camera.app.MotionManager;
Angus Kong5596b4c2014-03-11 16:27:30 -070028import com.android.camera.debug.Log;
Andy Huibersb8682742014-08-27 15:28:42 -070029import com.android.camera.one.Settings3A;
Erin Dahlgren6190c362014-06-13 14:12:08 -070030import com.android.camera.settings.Keys;
Erin Dahlgren357b7672013-11-20 17:38:14 -080031import com.android.camera.settings.SettingsManager;
Doris Liu482de022013-12-18 19:18:16 -080032import com.android.camera.ui.PreviewStatusListener;
Andy Huibersb7c7d9a2014-06-18 22:26:14 -070033import com.android.camera.ui.TouchCoordinate;
Alan Newbergera8923a72014-12-09 11:28:45 -080034import com.android.camera.util.ApiHelper;
Paul Rohde987ee642014-12-05 12:17:15 -080035import com.android.camera.ui.focus.CameraCoordinateTransformer;
36import com.android.camera.ui.focus.FocusRing;
Angus Kongb50b5cb2013-08-09 14:55:20 -070037import com.android.camera.util.CameraUtil;
Andy Huibersb6605382014-06-24 10:46:36 -070038import com.android.camera.util.UsageStatistics;
Sol Boucher5a344962014-06-17 14:05:08 -070039import com.android.ex.camera2.portability.CameraCapabilities;
Michael Kolb8872c232013-01-29 10:33:22 -080040
Sascha Haeberling375f9d12014-10-17 19:05:12 -070041import java.lang.ref.WeakReference;
Sascha Haeberling638e6f02013-09-18 14:28:51 -070042import java.util.ArrayList;
43import java.util.List;
44
Michael Kolb8872c232013-01-29 10:33:22 -080045/* A class that handles everything about focus in still picture mode.
46 * This also handles the metering area because it is the same as focus area.
47 *
48 * The test cases:
49 * (1) The camera has continuous autofocus. Move the camera. Take a picture when
50 * CAF is not in progress.
51 * (2) The camera has continuous autofocus. Move the camera. Take a picture when
52 * CAF is in progress.
53 * (3) The camera has face detection. Point the camera at some faces. Hold the
54 * shutter. Release to take a picture.
55 * (4) The camera has face detection. Point the camera at some faces. Single tap
56 * the shutter to take a picture.
57 * (5) The camera has autofocus. Single tap the shutter to take a picture.
58 * (6) The camera has autofocus. Hold the shutter. Release to take a picture.
59 * (7) The camera has no autofocus. Single tap the shutter and take a picture.
60 * (8) The camera has autofocus and supports focus area. Touch the screen to
61 * trigger autofocus. Take a picture.
62 * (9) The camera has autofocus and supports focus area. Touch the screen to
63 * trigger autofocus. Wait until it times out.
64 * (10) The camera has no autofocus and supports metering area. Touch the screen
65 * to change metering area.
66 */
Kevin Gabayanfb333362014-06-02 14:48:20 -070067public class FocusOverlayManager implements PreviewStatusListener.PreviewAreaChangedListener,
68 MotionManager.MotionListener {
Angus Kong5596b4c2014-03-11 16:27:30 -070069 private static final Log.Tag TAG = new Log.Tag("FocusOverlayMgr");
Michael Kolb8872c232013-01-29 10:33:22 -080070
71 private static final int RESET_TOUCH_FOCUS = 0;
Andy Huiberse2f5fdd2014-08-26 11:16:59 -070072
Andy Huibersb8682742014-08-27 15:28:42 -070073 private static final int RESET_TOUCH_FOCUS_DELAY_MILLIS = Settings3A.getFocusHoldMillis();
74
75 public static final float AF_REGION_BOX = Settings3A.getAutoFocusRegionWidth();
76 public static final float AE_REGION_BOX = Settings3A.getMeteringRegionWidth();
Michael Kolb8872c232013-01-29 10:33:22 -080077
78 private int mState = STATE_IDLE;
79 private static final int STATE_IDLE = 0; // Focus is not active.
80 private static final int STATE_FOCUSING = 1; // Focus is in progress.
81 // Focus is in progress and the camera should take a picture after focus finishes.
82 private static final int STATE_FOCUSING_SNAP_ON_FINISH = 2;
83 private static final int STATE_SUCCESS = 3; // Focus finishes and succeeds.
84 private static final int STATE_FAIL = 4; // Focus finishes and fails.
85
86 private boolean mInitialized;
87 private boolean mFocusAreaSupported;
88 private boolean mMeteringAreaSupported;
89 private boolean mLockAeAwbNeeded;
90 private boolean mAeAwbLock;
Paul Rohde987ee642014-12-05 12:17:15 -080091 private CameraCoordinateTransformer mCoordinateTransformer;
Michael Kolb8872c232013-01-29 10:33:22 -080092
Michael Kolb8872c232013-01-29 10:33:22 -080093 private boolean mMirror; // true if the camera is front-facing.
94 private int mDisplayOrientation;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080095 private List<Area> mFocusArea; // focus area in driver format
96 private List<Area> mMeteringArea; // metering area in driver format
Angus Kong831347d2014-06-16 16:07:28 -070097 private CameraCapabilities.FocusMode mFocusMode;
98 private final List<CameraCapabilities.FocusMode> mDefaultFocusModes;
99 private CameraCapabilities.FocusMode mOverrideFocusMode;
Angus Kong88289042014-04-22 16:39:42 -0700100 private CameraCapabilities mCapabilities;
Erin Dahlgren6190c362014-06-13 14:12:08 -0700101 private final AppController mAppController;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800102 private final SettingsManager mSettingsManager;
103 private final Handler mHandler;
Michael Kolb8872c232013-01-29 10:33:22 -0800104 Listener mListener;
Michael Kolbe3de7222013-02-18 15:16:44 -0800105 private boolean mPreviousMoving;
Paul Rohde987ee642014-12-05 12:17:15 -0800106 private final FocusRing mFocusRing;
Doris Liu36ebcb12013-10-28 14:44:24 -0700107 private final Rect mPreviewRect = new Rect(0, 0, 0, 0);
Kevin Gabayanfb333362014-06-02 14:48:20 -0700108 private boolean mFocusLocked;
Michael Kolbd6954f32013-03-08 20:43:01 -0800109
Andy Huibersb7c7d9a2014-06-18 22:26:14 -0700110 /** Manual tap to focus parameters */
111 private TouchCoordinate mTouchCoordinate;
112 private long mTouchTime;
113
Michael Kolb8872c232013-01-29 10:33:22 -0800114 public interface Listener {
115 public void autoFocus();
116 public void cancelAutoFocus();
117 public boolean capture();
118 public void startFaceDetection();
119 public void stopFaceDetection();
120 public void setFocusParameters();
121 }
122
Sascha Haeberling375f9d12014-10-17 19:05:12 -0700123 /**
124 * TODO: Refactor this so that we either don't need a handler or make
125 * mListener not be the activity.
126 */
127 private static class MainHandler extends Handler {
128 /**
129 * The outer mListener at the moment is actually the CameraActivity,
130 * which we would leak if we didn't break the GC path here using a
131 * WeakReference.
132 */
133 final WeakReference<FocusOverlayManager> mManager;
134 public MainHandler(FocusOverlayManager manager, Looper looper) {
Michael Kolb8872c232013-01-29 10:33:22 -0800135 super(looper);
Sascha Haeberling375f9d12014-10-17 19:05:12 -0700136 mManager = new WeakReference<FocusOverlayManager>(manager);
Michael Kolb8872c232013-01-29 10:33:22 -0800137 }
138
139 @Override
140 public void handleMessage(Message msg) {
Sascha Haeberling375f9d12014-10-17 19:05:12 -0700141 FocusOverlayManager manager = mManager.get();
142 if (manager == null) {
143 return;
144 }
145
Michael Kolb8872c232013-01-29 10:33:22 -0800146 switch (msg.what) {
147 case RESET_TOUCH_FOCUS: {
Sascha Haeberling375f9d12014-10-17 19:05:12 -0700148 manager.cancelAutoFocus();
149 manager.mListener.startFaceDetection();
Michael Kolb8872c232013-01-29 10:33:22 -0800150 break;
151 }
152 }
153 }
154 }
155
Erin Dahlgren6190c362014-06-13 14:12:08 -0700156 public FocusOverlayManager(AppController appController,
Angus Kong831347d2014-06-16 16:07:28 -0700157 List<CameraCapabilities.FocusMode> defaultFocusModes, CameraCapabilities capabilities,
Paul Rohde987ee642014-12-05 12:17:15 -0800158 Listener listener, boolean mirror, Looper looper, FocusRing focusRing) {
Erin Dahlgren6190c362014-06-13 14:12:08 -0700159 mAppController = appController;
160 mSettingsManager = appController.getSettingsManager();
Sascha Haeberling375f9d12014-10-17 19:05:12 -0700161 mHandler = new MainHandler(this, looper);
Sascha Haeberlingee36c5f2014-07-29 17:05:43 -0700162 mDefaultFocusModes = new ArrayList<CameraCapabilities.FocusMode>(defaultFocusModes);
Angus Kong831347d2014-06-16 16:07:28 -0700163 updateCapabilities(capabilities);
Michael Kolb8872c232013-01-29 10:33:22 -0800164 mListener = listener;
165 setMirror(mirror);
Paul Rohde987ee642014-12-05 12:17:15 -0800166 mFocusRing = focusRing;
Kevin Gabayanfb333362014-06-02 14:48:20 -0700167 mFocusLocked = false;
Michael Kolb8872c232013-01-29 10:33:22 -0800168 }
169
Angus Kong831347d2014-06-16 16:07:28 -0700170 public void updateCapabilities(CameraCapabilities capabilities) {
Andy Huibers09e13402014-06-27 17:29:23 -0700171 // capabilities can only be null when onConfigurationChanged is called
Michael Kolb8872c232013-01-29 10:33:22 -0800172 // before camera is open. We will just return in this case, because
Andy Huibers09e13402014-06-27 17:29:23 -0700173 // capabilities will be set again later with the right capabilities after
Michael Kolb8872c232013-01-29 10:33:22 -0800174 // camera is open.
Andy Huibers09e13402014-06-27 17:29:23 -0700175 if (capabilities == null) {
Sascha Haeberlinge3f9ce22014-06-25 11:12:22 -0700176 return;
177 }
Angus Kong88289042014-04-22 16:39:42 -0700178 mCapabilities = capabilities;
179 mFocusAreaSupported = mCapabilities.supports(CameraCapabilities.Feature.FOCUS_AREA);
180 mMeteringAreaSupported = mCapabilities.supports(CameraCapabilities.Feature.METERING_AREA);
181 mLockAeAwbNeeded = (mCapabilities.supports(CameraCapabilities.Feature.AUTO_EXPOSURE_LOCK)
182 || mCapabilities.supports(CameraCapabilities.Feature.AUTO_WHITE_BALANCE_LOCK));
Michael Kolb8872c232013-01-29 10:33:22 -0800183 }
184
Doris Liu36ebcb12013-10-28 14:44:24 -0700185 /** This setter should be the only way to mutate mPreviewRect. */
186 public void setPreviewRect(Rect previewRect) {
187 if (!mPreviewRect.equals(previewRect)) {
188 mPreviewRect.set(previewRect);
Paul Rohde987ee642014-12-05 12:17:15 -0800189 resetCoordinateTransformer();
190 mInitialized = true;
Michael Kolb8872c232013-01-29 10:33:22 -0800191 }
192 }
193
Doris Liu482de022013-12-18 19:18:16 -0800194 @Override
Angus Kong2bacca72014-03-06 12:57:29 -0800195 public void onPreviewAreaChanged(RectF previewArea) {
Doris Liua1ec04a2014-01-13 17:29:40 -0800196 setPreviewRect(CameraUtil.rectFToRect(previewArea));
Doris Liu482de022013-12-18 19:18:16 -0800197 }
198
Michael Kolb8872c232013-01-29 10:33:22 -0800199 public void setMirror(boolean mirror) {
200 mMirror = mirror;
Paul Rohde987ee642014-12-05 12:17:15 -0800201 resetCoordinateTransformer();
Michael Kolb8872c232013-01-29 10:33:22 -0800202 }
203
204 public void setDisplayOrientation(int displayOrientation) {
205 mDisplayOrientation = displayOrientation;
Paul Rohde987ee642014-12-05 12:17:15 -0800206 resetCoordinateTransformer();
Michael Kolb8872c232013-01-29 10:33:22 -0800207 }
208
Paul Rohde987ee642014-12-05 12:17:15 -0800209 private void resetCoordinateTransformer() {
210 if (mPreviewRect.width() > 0 && mPreviewRect.height() > 0) {
211 mCoordinateTransformer = new CameraCoordinateTransformer(mMirror, mDisplayOrientation,
212 CameraUtil.rectToRectF(mPreviewRect));
213 } else {
214 Log.w(TAG, "The coordinate transformer could not be built because the preview rect"
215 + "did not have a width and height");
Michael Kolb8872c232013-01-29 10:33:22 -0800216 }
217 }
218
Paul Rohde987ee642014-12-05 12:17:15 -0800219
Michael Kolb8872c232013-01-29 10:33:22 -0800220 private void lockAeAwbIfNeeded() {
221 if (mLockAeAwbNeeded && !mAeAwbLock) {
222 mAeAwbLock = true;
223 mListener.setFocusParameters();
224 }
225 }
226
227 private void unlockAeAwbIfNeeded() {
228 if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) {
229 mAeAwbLock = false;
230 mListener.setFocusParameters();
231 }
232 }
233
Angus Kong831347d2014-06-16 16:07:28 -0700234 public void onShutterUp(CameraCapabilities.FocusMode currentFocusMode) {
Sascha Haeberlinge3f9ce22014-06-25 11:12:22 -0700235 if (!mInitialized) {
236 return;
237 }
Michael Kolb8872c232013-01-29 10:33:22 -0800238
Angus Kong831347d2014-06-16 16:07:28 -0700239 if (needAutoFocusCall(currentFocusMode)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800240 // User releases half-pressed focus key.
241 if (mState == STATE_FOCUSING || mState == STATE_SUCCESS
242 || mState == STATE_FAIL) {
243 cancelAutoFocus();
244 }
245 }
246
247 // Unlock AE and AWB after cancelAutoFocus. Camera API does not
248 // guarantee setParameters can be called during autofocus.
249 unlockAeAwbIfNeeded();
250 }
251
Angus Kong831347d2014-06-16 16:07:28 -0700252 public void focusAndCapture(CameraCapabilities.FocusMode currentFocusMode) {
Sascha Haeberlinge3f9ce22014-06-25 11:12:22 -0700253 if (!mInitialized) {
254 return;
255 }
Michael Kolb8872c232013-01-29 10:33:22 -0800256
Angus Kong831347d2014-06-16 16:07:28 -0700257 if (!needAutoFocusCall(currentFocusMode)) {
Angus Kongeaaf56d2014-02-20 11:59:10 -0800258 // Focus is not needed.
259 capture();
260 } else if (mState == STATE_SUCCESS || mState == STATE_FAIL) {
261 // Focus is done already.
Michael Kolb8872c232013-01-29 10:33:22 -0800262 capture();
263 } else if (mState == STATE_FOCUSING) {
Angus Kongeaaf56d2014-02-20 11:59:10 -0800264 // Still focusing and will not trigger snap upon finish.
Michael Kolb8872c232013-01-29 10:33:22 -0800265 mState = STATE_FOCUSING_SNAP_ON_FINISH;
266 } else if (mState == STATE_IDLE) {
Angus Kongeaaf56d2014-02-20 11:59:10 -0800267 autoFocusAndCapture();
Michael Kolb8872c232013-01-29 10:33:22 -0800268 }
269 }
270
271 public void onAutoFocus(boolean focused, boolean shutterButtonPressed) {
272 if (mState == STATE_FOCUSING_SNAP_ON_FINISH) {
273 // Take the picture no matter focus succeeds or fails. No need
274 // to play the AF sound if we're about to play the shutter
275 // sound.
276 if (focused) {
277 mState = STATE_SUCCESS;
278 } else {
279 mState = STATE_FAIL;
280 }
Michael Kolb8872c232013-01-29 10:33:22 -0800281 capture();
282 } else if (mState == STATE_FOCUSING) {
283 // This happens when (1) user is half-pressing the focus key or
284 // (2) touch focus is triggered. Play the focus tone. Do not
285 // take the picture now.
286 if (focused) {
287 mState = STATE_SUCCESS;
288 } else {
289 mState = STATE_FAIL;
290 }
Michael Kolb8872c232013-01-29 10:33:22 -0800291 // If this is triggered by touch focus, cancel focus after a
292 // while.
Michael Kolbb0579432013-07-11 13:48:15 -0700293 if (mFocusArea != null) {
Kevin Gabayanfb333362014-06-02 14:48:20 -0700294 mFocusLocked = true;
Andy Huibersb8682742014-08-27 15:28:42 -0700295 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY_MILLIS);
Michael Kolb8872c232013-01-29 10:33:22 -0800296 }
297 if (shutterButtonPressed) {
298 // Lock AE & AWB so users can half-press shutter and recompose.
299 lockAeAwbIfNeeded();
300 }
301 } else if (mState == STATE_IDLE) {
302 // User has released the focus key before focus completes.
303 // Do nothing.
304 }
305 }
306
307 public void onAutoFocusMoving(boolean moving) {
Sascha Haeberlinge3f9ce22014-06-25 11:12:22 -0700308 if (!mInitialized) {
309 return;
310 }
Michael Kolbd6954f32013-03-08 20:43:01 -0800311
Michael Kolb8872c232013-01-29 10:33:22 -0800312 // Ignore if we have requested autofocus. This method only handles
313 // continuous autofocus.
Sascha Haeberlinge3f9ce22014-06-25 11:12:22 -0700314 if (mState != STATE_IDLE) {
315 return;
316 }
Michael Kolb8872c232013-01-29 10:33:22 -0800317
Michael Kolbe3de7222013-02-18 15:16:44 -0800318 // animate on false->true trasition only b/8219520
319 if (moving && !mPreviousMoving) {
Doris Liuca4a5662014-01-02 17:40:12 -0800320 // Auto focus at the center of the preview.
Paul Rohde987ee642014-12-05 12:17:15 -0800321 mFocusRing.startPassiveFocus();
322 } else if (!moving && mFocusRing.isPassiveFocusRunning()) {
323 mFocusRing.stopFocusAnimations();
Michael Kolb8872c232013-01-29 10:33:22 -0800324 }
Michael Kolbe3de7222013-02-18 15:16:44 -0800325 mPreviousMoving = moving;
Michael Kolb8872c232013-01-29 10:33:22 -0800326 }
327
Andy Huiberse2f5fdd2014-08-26 11:16:59 -0700328 /** Returns width of auto focus region in pixels. */
Paul Rohde987ee642014-12-05 12:17:15 -0800329 private int getAFRegionSizePx() {
Andy Huiberse2f5fdd2014-08-26 11:16:59 -0700330 return (int) (Math.min(mPreviewRect.width(), mPreviewRect.height()) * AF_REGION_BOX);
331 }
332
333 /** Returns width of metering region in pixels. */
Paul Rohde987ee642014-12-05 12:17:15 -0800334 private int getAERegionSizePx() {
Andy Huibersb8682742014-08-27 15:28:42 -0700335 return (int) (Math.min(mPreviewRect.width(), mPreviewRect.height()) * AE_REGION_BOX);
Andy Huiberse2f5fdd2014-08-26 11:16:59 -0700336 }
337
Michael Kolb0718d482013-02-16 13:13:47 -0800338 private void initializeFocusAreas(int x, int y) {
Michael Kolb8872c232013-01-29 10:33:22 -0800339 if (mFocusArea == null) {
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800340 mFocusArea = new ArrayList<Area>();
Michael Kolb8872c232013-01-29 10:33:22 -0800341 mFocusArea.add(new Area(new Rect(), 1));
342 }
343
344 // Convert the coordinates to driver format.
Paul Rohde987ee642014-12-05 12:17:15 -0800345 mFocusArea.get(0).rect = computeCameraRectFromPreviewCoordinates(x, y, getAFRegionSizePx());
Michael Kolb8872c232013-01-29 10:33:22 -0800346 }
347
Michael Kolb0718d482013-02-16 13:13:47 -0800348 private void initializeMeteringAreas(int x, int y) {
Michael Kolb8872c232013-01-29 10:33:22 -0800349 if (mMeteringArea == null) {
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800350 mMeteringArea = new ArrayList<Area>();
Michael Kolb8872c232013-01-29 10:33:22 -0800351 mMeteringArea.add(new Area(new Rect(), 1));
352 }
353
354 // Convert the coordinates to driver format.
Paul Rohde987ee642014-12-05 12:17:15 -0800355 mMeteringArea.get(0).rect = computeCameraRectFromPreviewCoordinates(x, y, getAERegionSizePx());
Michael Kolb8872c232013-01-29 10:33:22 -0800356 }
357
358 public void onSingleTapUp(int x, int y) {
Sascha Haeberlinge3f9ce22014-06-25 11:12:22 -0700359 if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
360 return;
361 }
Michael Kolb8872c232013-01-29 10:33:22 -0800362
363 // Let users be able to cancel previous touch focus.
Michael Kolbb0579432013-07-11 13:48:15 -0700364 if ((mFocusArea != null) && (mState == STATE_FOCUSING ||
Michael Kolb8872c232013-01-29 10:33:22 -0800365 mState == STATE_SUCCESS || mState == STATE_FAIL)) {
366 cancelAutoFocus();
367 }
Sascha Haeberlinge3f9ce22014-06-25 11:12:22 -0700368 if (mPreviewRect.width() == 0 || mPreviewRect.height() == 0) {
369 return;
370 }
Michael Kolbb0579432013-07-11 13:48:15 -0700371 // Initialize variables.
Michael Kolb8872c232013-01-29 10:33:22 -0800372 // Initialize mFocusArea.
373 if (mFocusAreaSupported) {
Michael Kolb0718d482013-02-16 13:13:47 -0800374 initializeFocusAreas(x, y);
Michael Kolb8872c232013-01-29 10:33:22 -0800375 }
376 // Initialize mMeteringArea.
377 if (mMeteringAreaSupported) {
Michael Kolb0718d482013-02-16 13:13:47 -0800378 initializeMeteringAreas(x, y);
Michael Kolb8872c232013-01-29 10:33:22 -0800379 }
380
Paul Rohde987ee642014-12-05 12:17:15 -0800381 mFocusRing.startActiveFocus();
382 mFocusRing.setFocusLocation(x, y);
383
Andy Huibersb7c7d9a2014-06-18 22:26:14 -0700384 // Log manual tap to focus.
385 mTouchCoordinate = new TouchCoordinate(x, y, mPreviewRect.width(), mPreviewRect.height());
386 mTouchTime = System.currentTimeMillis();
Michael Kolb8872c232013-01-29 10:33:22 -0800387
388 // Stop face detection because we want to specify focus and metering area.
389 mListener.stopFaceDetection();
390
391 // Set the focus area and metering area.
392 mListener.setFocusParameters();
393 if (mFocusAreaSupported) {
394 autoFocus();
395 } else { // Just show the indicator in all other cases.
Kevin Gabayand4a68ca2014-03-24 14:13:12 -0700396 // Reset the metering area in 4 seconds.
Michael Kolb8872c232013-01-29 10:33:22 -0800397 mHandler.removeMessages(RESET_TOUCH_FOCUS);
Andy Huibersb8682742014-08-27 15:28:42 -0700398 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY_MILLIS);
Michael Kolb8872c232013-01-29 10:33:22 -0800399 }
400 }
401
402 public void onPreviewStarted() {
403 mState = STATE_IDLE;
Alan Newbergera8923a72014-12-09 11:28:45 -0800404 // Avoid resetting touch focus if N4, b/18681082.
405 if (!ApiHelper.IS_NEXUS_4) {
406 resetTouchFocus();
407 }
Michael Kolb8872c232013-01-29 10:33:22 -0800408 }
409
410 public void onPreviewStopped() {
411 // If auto focus was in progress, it would have been stopped.
412 mState = STATE_IDLE;
Michael Kolb8872c232013-01-29 10:33:22 -0800413 }
414
415 public void onCameraReleased() {
416 onPreviewStopped();
417 }
418
Kevin Gabayanfb333362014-06-02 14:48:20 -0700419 @Override
420 public void onMoving() {
421 if (mFocusLocked) {
422 Log.d(TAG, "onMoving: Early focus unlock.");
423 cancelAutoFocus();
424 }
425 }
426
Angus Kongeaaf56d2014-02-20 11:59:10 -0800427 /**
428 * Triggers the autofocus and sets the specified state.
429 *
430 * @param focusingState The state to use when focus is in progress.
431 */
432 private void autoFocus(int focusingState) {
Michael Kolb8872c232013-01-29 10:33:22 -0800433 mListener.autoFocus();
Angus Kongeaaf56d2014-02-20 11:59:10 -0800434 mState = focusingState;
Michael Kolb8872c232013-01-29 10:33:22 -0800435 mHandler.removeMessages(RESET_TOUCH_FOCUS);
436 }
437
Angus Kongeaaf56d2014-02-20 11:59:10 -0800438 /**
439 * Triggers the autofocus and set the state to indicate the focus is in
440 * progress.
441 */
442 private void autoFocus() {
443 autoFocus(STATE_FOCUSING);
444 }
445
446 /**
447 * Triggers the autofocus and set the state to which a capture will happen
448 * in the following autofocus callback.
449 */
450 private void autoFocusAndCapture() {
451 autoFocus(STATE_FOCUSING_SNAP_ON_FINISH);
452 }
453
Michael Kolb8872c232013-01-29 10:33:22 -0800454 private void cancelAutoFocus() {
Kevin Gabayan516c11a2014-06-13 20:49:48 +0000455 Log.v(TAG, "Cancel autofocus.");
Michael Kolb8872c232013-01-29 10:33:22 -0800456 // Reset the tap area before calling mListener.cancelAutofocus.
457 // Otherwise, focus mode stays at auto and the tap area passed to the
458 // driver is not reset.
459 resetTouchFocus();
460 mListener.cancelAutoFocus();
Michael Kolb8872c232013-01-29 10:33:22 -0800461 mState = STATE_IDLE;
Kevin Gabayanfb333362014-06-02 14:48:20 -0700462 mFocusLocked = false;
Michael Kolb8872c232013-01-29 10:33:22 -0800463 mHandler.removeMessages(RESET_TOUCH_FOCUS);
464 }
465
466 private void capture() {
467 if (mListener.capture()) {
468 mState = STATE_IDLE;
469 mHandler.removeMessages(RESET_TOUCH_FOCUS);
470 }
471 }
472
Angus Kong831347d2014-06-16 16:07:28 -0700473 public CameraCapabilities.FocusMode getFocusMode(
474 final CameraCapabilities.FocusMode currentFocusMode) {
475 if (mOverrideFocusMode != null) {
Alan Newbergerec4a3fc2014-07-24 15:55:37 -0700476 Log.v(TAG, "returning override focus: " + mOverrideFocusMode);
Angus Kong831347d2014-06-16 16:07:28 -0700477 return mOverrideFocusMode;
478 }
479 if (mCapabilities == null) {
Alan Newbergerec4a3fc2014-07-24 15:55:37 -0700480 Log.v(TAG, "no capabilities, returning default AUTO focus mode");
Angus Kong831347d2014-06-16 16:07:28 -0700481 return CameraCapabilities.FocusMode.AUTO;
482 }
Michael Kolb8872c232013-01-29 10:33:22 -0800483
Michael Kolbb0579432013-07-11 13:48:15 -0700484 if (mFocusAreaSupported && mFocusArea != null) {
Alan Newbergerec4a3fc2014-07-24 15:55:37 -0700485 Log.v(TAG, "in tap to focus, returning AUTO focus mode");
Michael Kolb8872c232013-01-29 10:33:22 -0800486 // Always use autofocus in tap-to-focus.
Angus Kong831347d2014-06-16 16:07:28 -0700487 mFocusMode = CameraCapabilities.FocusMode.AUTO;
Michael Kolb8872c232013-01-29 10:33:22 -0800488 } else {
Alan Newbergerec4a3fc2014-07-24 15:55:37 -0700489 String focusSetting = mSettingsManager.getString(mAppController.getCameraScope(),
490 Keys.KEY_FOCUS_MODE);
491 Log.v(TAG, "stored focus setting for camera: " + focusSetting);
Michael Kolb8872c232013-01-29 10:33:22 -0800492 // The default is continuous autofocus.
Alan Newbergerec4a3fc2014-07-24 15:55:37 -0700493 mFocusMode = mCapabilities.getStringifier().focusModeFromString(focusSetting);
494 Log.v(TAG, "focus mode resolved from setting: " + mFocusMode);
Michael Kolb8872c232013-01-29 10:33:22 -0800495 // Try to find a supported focus mode from the default list.
496 if (mFocusMode == null) {
Angus Kong831347d2014-06-16 16:07:28 -0700497 for (CameraCapabilities.FocusMode mode : mDefaultFocusModes) {
498 if (mCapabilities.supports(mode)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800499 mFocusMode = mode;
Alan Newbergerec4a3fc2014-07-24 15:55:37 -0700500 Log.v(TAG, "selected supported focus mode from default list" + mode);
Michael Kolb8872c232013-01-29 10:33:22 -0800501 break;
502 }
503 }
504 }
505 }
Angus Kong831347d2014-06-16 16:07:28 -0700506 if (!mCapabilities.supports(mFocusMode)) {
Michael Kolb8872c232013-01-29 10:33:22 -0800507 // For some reasons, the driver does not support the current
508 // focus mode. Fall back to auto.
Angus Kong831347d2014-06-16 16:07:28 -0700509 if (mCapabilities.supports(CameraCapabilities.FocusMode.AUTO)) {
Alan Newbergerec4a3fc2014-07-24 15:55:37 -0700510 Log.v(TAG, "no supported focus mode, falling back to AUTO");
Angus Kong831347d2014-06-16 16:07:28 -0700511 mFocusMode = CameraCapabilities.FocusMode.AUTO;
Michael Kolb8872c232013-01-29 10:33:22 -0800512 } else {
Alan Newbergerec4a3fc2014-07-24 15:55:37 -0700513 Log.v(TAG, "no supported focus mode, falling back to current: " + currentFocusMode);
Angus Kong831347d2014-06-16 16:07:28 -0700514 mFocusMode = currentFocusMode;
Michael Kolb8872c232013-01-29 10:33:22 -0800515 }
516 }
517 return mFocusMode;
518 }
519
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800520 public List<Area> getFocusAreas() {
Michael Kolb8872c232013-01-29 10:33:22 -0800521 return mFocusArea;
522 }
523
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800524 public List<Area> getMeteringAreas() {
Michael Kolb8872c232013-01-29 10:33:22 -0800525 return mMeteringArea;
526 }
527
Michael Kolb8872c232013-01-29 10:33:22 -0800528 public void resetTouchFocus() {
Sascha Haeberlinge3f9ce22014-06-25 11:12:22 -0700529 if (!mInitialized) {
530 return;
531 }
Michael Kolb8872c232013-01-29 10:33:22 -0800532
Michael Kolbb0579432013-07-11 13:48:15 -0700533 mFocusArea = null;
534 mMeteringArea = null;
Andy Huibersbd9b80b2014-08-26 16:21:15 -0700535 // This will cause current module to call getFocusAreas() and
536 // getMeteringAreas() and send updated regions to camera.
537 mListener.setFocusParameters();
Andy Huibersb7c7d9a2014-06-18 22:26:14 -0700538
539 if (mTouchCoordinate != null) {
540 UsageStatistics.instance().tapToFocus(mTouchCoordinate,
541 0.001f * (System.currentTimeMillis() - mTouchTime));
542 mTouchCoordinate = null;
543 }
Michael Kolb8872c232013-01-29 10:33:22 -0800544 }
545
Paul Rohde987ee642014-12-05 12:17:15 -0800546 private Rect computeCameraRectFromPreviewCoordinates(int x, int y, int size) {
Andy Huiberse2f5fdd2014-08-26 11:16:59 -0700547 int left = CameraUtil.clamp(x - size / 2, mPreviewRect.left,
548 mPreviewRect.right - size);
549 int top = CameraUtil.clamp(y - size / 2, mPreviewRect.top,
550 mPreviewRect.bottom - size);
Michael Kolb8872c232013-01-29 10:33:22 -0800551
Andy Huiberse2f5fdd2014-08-26 11:16:59 -0700552 RectF rectF = new RectF(left, top, left + size, top + size);
Paul Rohde987ee642014-12-05 12:17:15 -0800553 return CameraUtil.rectFToRect(mCoordinateTransformer.toCameraSpace(rectF));
Michael Kolb8872c232013-01-29 10:33:22 -0800554 }
555
Michael Kolb8872c232013-01-29 10:33:22 -0800556 /* package */ int getFocusState() {
557 return mState;
558 }
559
560 public boolean isFocusCompleted() {
561 return mState == STATE_SUCCESS || mState == STATE_FAIL;
562 }
563
564 public boolean isFocusingSnapOnFinish() {
565 return mState == STATE_FOCUSING_SNAP_ON_FINISH;
566 }
567
568 public void removeMessages() {
569 mHandler.removeMessages(RESET_TOUCH_FOCUS);
570 }
571
Angus Kong831347d2014-06-16 16:07:28 -0700572 public void overrideFocusMode(CameraCapabilities.FocusMode focusMode) {
Michael Kolb8872c232013-01-29 10:33:22 -0800573 mOverrideFocusMode = focusMode;
574 }
575
576 public void setAeAwbLock(boolean lock) {
577 mAeAwbLock = lock;
578 }
579
580 public boolean getAeAwbLock() {
581 return mAeAwbLock;
582 }
583
Angus Kong831347d2014-06-16 16:07:28 -0700584 private boolean needAutoFocusCall(CameraCapabilities.FocusMode focusMode) {
585 return !(focusMode == CameraCapabilities.FocusMode.INFINITY
586 || focusMode == CameraCapabilities.FocusMode.FIXED
587 || focusMode == CameraCapabilities.FocusMode.EXTENDED_DOF);
Michael Kolb8872c232013-01-29 10:33:22 -0800588 }
589}