1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera; 18 19 import android.annotation.TargetApi; 20 import android.graphics.Matrix; 21 import android.graphics.Rect; 22 import android.graphics.RectF; 23 import android.hardware.Camera.Area; 24 import android.os.Build; 25 import android.os.Handler; 26 import android.os.Looper; 27 import android.os.Message; 28 29 import com.android.camera.app.AppController; 30 import com.android.camera.app.MotionManager; 31 import com.android.camera.debug.Log; 32 import com.android.camera.one.Settings3A; 33 import com.android.camera.settings.Keys; 34 import com.android.camera.settings.SettingsManager; 35 import com.android.camera.ui.PreviewStatusListener; 36 import com.android.camera.ui.TouchCoordinate; 37 import com.android.camera.util.CameraUtil; 38 import com.android.camera.util.UsageStatistics; 39 import com.android.ex.camera2.portability.CameraCapabilities; 40 41 import java.lang.ref.WeakReference; 42 import java.util.ArrayList; 43 import java.util.List; 44 45 /* A class that handles everything about focus in still picture mode. 46 * This also handles the metering area because it is the same as focus area. 47 * 48 * The test cases: 49 * (1) The camera has continuous autofocus. Move the camera. Take a picture when 50 * CAF is not in progress. 51 * (2) The camera has continuous autofocus. Move the camera. Take a picture when 52 * CAF is in progress. 53 * (3) The camera has face detection. Point the camera at some faces. Hold the 54 * shutter. Release to take a picture. 55 * (4) The camera has face detection. Point the camera at some faces. Single tap 56 * the shutter to take a picture. 57 * (5) The camera has autofocus. Single tap the shutter to take a picture. 58 * (6) The camera has autofocus. Hold the shutter. Release to take a picture. 59 * (7) The camera has no autofocus. Single tap the shutter and take a picture. 60 * (8) The camera has autofocus and supports focus area. Touch the screen to 61 * trigger autofocus. Take a picture. 62 * (9) The camera has autofocus and supports focus area. Touch the screen to 63 * trigger autofocus. Wait until it times out. 64 * (10) The camera has no autofocus and supports metering area. Touch the screen 65 * to change metering area. 66 */ 67 public class FocusOverlayManager implements PreviewStatusListener.PreviewAreaChangedListener, 68 MotionManager.MotionListener { 69 private static final Log.Tag TAG = new Log.Tag("FocusOverlayMgr"); 70 71 private static final int RESET_TOUCH_FOCUS = 0; 72 73 private static final int RESET_TOUCH_FOCUS_DELAY_MILLIS = Settings3A.getFocusHoldMillis(); 74 75 public static final float AF_REGION_BOX = Settings3A.getAutoFocusRegionWidth(); 76 public static final float AE_REGION_BOX = Settings3A.getMeteringRegionWidth(); 77 78 private int mState = STATE_IDLE; 79 private static final int STATE_IDLE = 0; // Focus is not active. 80 private static final int STATE_FOCUSING = 1; // Focus is in progress. 81 // Focus is in progress and the camera should take a picture after focus finishes. 82 private static final int STATE_FOCUSING_SNAP_ON_FINISH = 2; 83 private static final int STATE_SUCCESS = 3; // Focus finishes and succeeds. 84 private static final int STATE_FAIL = 4; // Focus finishes and fails. 85 86 private boolean mInitialized; 87 private boolean mFocusAreaSupported; 88 private boolean mMeteringAreaSupported; 89 private boolean mLockAeAwbNeeded; 90 private boolean mAeAwbLock; 91 private final Matrix mMatrix; 92 93 private boolean mMirror; // true if the camera is front-facing. 94 private int mDisplayOrientation; 95 private List<Area> mFocusArea; // focus area in driver format 96 private List<Area> mMeteringArea; // metering area in driver format 97 private CameraCapabilities.FocusMode mFocusMode; 98 private final List<CameraCapabilities.FocusMode> mDefaultFocusModes; 99 private CameraCapabilities.FocusMode mOverrideFocusMode; 100 private CameraCapabilities mCapabilities; 101 private final AppController mAppController; 102 private final SettingsManager mSettingsManager; 103 private final Handler mHandler; 104 Listener mListener; 105 private boolean mPreviousMoving; 106 private final FocusUI mUI; 107 private final Rect mPreviewRect = new Rect(0, 0, 0, 0); 108 private boolean mFocusLocked; 109 110 /** Manual tap to focus parameters */ 111 private TouchCoordinate mTouchCoordinate; 112 private long mTouchTime; 113 114 public interface FocusUI { hasFaces()115 public boolean hasFaces(); clearFocus()116 public void clearFocus(); setFocusPosition(int x, int y, boolean isPassiveScan, int aFsize, int aEsize)117 public void setFocusPosition(int x, int y, boolean isPassiveScan, int aFsize, int aEsize); setFocusPosition(int x, int y, boolean isPassiveScan)118 public void setFocusPosition(int x, int y, boolean isPassiveScan); onFocusStarted()119 public void onFocusStarted(); onFocusSucceeded()120 public void onFocusSucceeded(); onFocusFailed()121 public void onFocusFailed(); setPassiveFocusSuccess(boolean success)122 public void setPassiveFocusSuccess(boolean success); showDebugMessage(String message)123 public void showDebugMessage(String message); pauseFaceDetection()124 public void pauseFaceDetection(); resumeFaceDetection()125 public void resumeFaceDetection(); 126 } 127 128 public interface Listener { autoFocus()129 public void autoFocus(); cancelAutoFocus()130 public void cancelAutoFocus(); capture()131 public boolean capture(); startFaceDetection()132 public void startFaceDetection(); stopFaceDetection()133 public void stopFaceDetection(); setFocusParameters()134 public void setFocusParameters(); 135 } 136 137 /** 138 * TODO: Refactor this so that we either don't need a handler or make 139 * mListener not be the activity. 140 */ 141 private static class MainHandler extends Handler { 142 /** 143 * The outer mListener at the moment is actually the CameraActivity, 144 * which we would leak if we didn't break the GC path here using a 145 * WeakReference. 146 */ 147 final WeakReference<FocusOverlayManager> mManager; MainHandler(FocusOverlayManager manager, Looper looper)148 public MainHandler(FocusOverlayManager manager, Looper looper) { 149 super(looper); 150 mManager = new WeakReference<FocusOverlayManager>(manager); 151 } 152 153 @Override handleMessage(Message msg)154 public void handleMessage(Message msg) { 155 FocusOverlayManager manager = mManager.get(); 156 if (manager == null) { 157 return; 158 } 159 160 switch (msg.what) { 161 case RESET_TOUCH_FOCUS: { 162 manager.cancelAutoFocus(); 163 manager.mListener.startFaceDetection(); 164 break; 165 } 166 } 167 } 168 } 169 FocusOverlayManager(AppController appController, List<CameraCapabilities.FocusMode> defaultFocusModes, CameraCapabilities capabilities, Listener listener, boolean mirror, Looper looper, FocusUI ui)170 public FocusOverlayManager(AppController appController, 171 List<CameraCapabilities.FocusMode> defaultFocusModes, CameraCapabilities capabilities, 172 Listener listener, boolean mirror, Looper looper, FocusUI ui) { 173 mAppController = appController; 174 mSettingsManager = appController.getSettingsManager(); 175 mHandler = new MainHandler(this, looper); 176 mMatrix = new Matrix(); 177 mDefaultFocusModes = new ArrayList<CameraCapabilities.FocusMode>(defaultFocusModes); 178 updateCapabilities(capabilities); 179 mListener = listener; 180 setMirror(mirror); 181 mUI = ui; 182 mFocusLocked = false; 183 } 184 updateCapabilities(CameraCapabilities capabilities)185 public void updateCapabilities(CameraCapabilities capabilities) { 186 // capabilities can only be null when onConfigurationChanged is called 187 // before camera is open. We will just return in this case, because 188 // capabilities will be set again later with the right capabilities after 189 // camera is open. 190 if (capabilities == null) { 191 return; 192 } 193 mCapabilities = capabilities; 194 mFocusAreaSupported = mCapabilities.supports(CameraCapabilities.Feature.FOCUS_AREA); 195 mMeteringAreaSupported = mCapabilities.supports(CameraCapabilities.Feature.METERING_AREA); 196 mLockAeAwbNeeded = (mCapabilities.supports(CameraCapabilities.Feature.AUTO_EXPOSURE_LOCK) 197 || mCapabilities.supports(CameraCapabilities.Feature.AUTO_WHITE_BALANCE_LOCK)); 198 } 199 200 /** This setter should be the only way to mutate mPreviewRect. */ setPreviewRect(Rect previewRect)201 public void setPreviewRect(Rect previewRect) { 202 if (!mPreviewRect.equals(previewRect)) { 203 mPreviewRect.set(previewRect); 204 setMatrix(); 205 } 206 } 207 208 @Override onPreviewAreaChanged(RectF previewArea)209 public void onPreviewAreaChanged(RectF previewArea) { 210 setPreviewRect(CameraUtil.rectFToRect(previewArea)); 211 } 212 213 /** Returns a copy of mPreviewRect so that outside class cannot modify preview 214 * rect except deliberately doing so through the setter. */ getPreviewRect()215 public Rect getPreviewRect() { 216 return new Rect(mPreviewRect); 217 } 218 setMirror(boolean mirror)219 public void setMirror(boolean mirror) { 220 mMirror = mirror; 221 setMatrix(); 222 } 223 setDisplayOrientation(int displayOrientation)224 public void setDisplayOrientation(int displayOrientation) { 225 mDisplayOrientation = displayOrientation; 226 setMatrix(); 227 } 228 setMatrix()229 private void setMatrix() { 230 if (mPreviewRect.width() != 0 && mPreviewRect.height() != 0) { 231 Matrix matrix = new Matrix(); 232 CameraUtil.prepareMatrix(matrix, mMirror, mDisplayOrientation, getPreviewRect()); 233 // In face detection, the matrix converts the driver coordinates to UI 234 // coordinates. In tap focus, the inverted matrix converts the UI 235 // coordinates to driver coordinates. 236 matrix.invert(mMatrix); 237 mInitialized = true; 238 } 239 } 240 lockAeAwbIfNeeded()241 private void lockAeAwbIfNeeded() { 242 if (mLockAeAwbNeeded && !mAeAwbLock) { 243 mAeAwbLock = true; 244 mListener.setFocusParameters(); 245 } 246 } 247 unlockAeAwbIfNeeded()248 private void unlockAeAwbIfNeeded() { 249 if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) { 250 mAeAwbLock = false; 251 mListener.setFocusParameters(); 252 } 253 } 254 onShutterUp(CameraCapabilities.FocusMode currentFocusMode)255 public void onShutterUp(CameraCapabilities.FocusMode currentFocusMode) { 256 if (!mInitialized) { 257 return; 258 } 259 260 if (needAutoFocusCall(currentFocusMode)) { 261 // User releases half-pressed focus key. 262 if (mState == STATE_FOCUSING || mState == STATE_SUCCESS 263 || mState == STATE_FAIL) { 264 cancelAutoFocus(); 265 } 266 } 267 268 // Unlock AE and AWB after cancelAutoFocus. Camera API does not 269 // guarantee setParameters can be called during autofocus. 270 unlockAeAwbIfNeeded(); 271 } 272 focusAndCapture(CameraCapabilities.FocusMode currentFocusMode)273 public void focusAndCapture(CameraCapabilities.FocusMode currentFocusMode) { 274 if (!mInitialized) { 275 return; 276 } 277 278 if (!needAutoFocusCall(currentFocusMode)) { 279 // Focus is not needed. 280 capture(); 281 } else if (mState == STATE_SUCCESS || mState == STATE_FAIL) { 282 // Focus is done already. 283 capture(); 284 } else if (mState == STATE_FOCUSING) { 285 // Still focusing and will not trigger snap upon finish. 286 mState = STATE_FOCUSING_SNAP_ON_FINISH; 287 } else if (mState == STATE_IDLE) { 288 autoFocusAndCapture(); 289 } 290 } 291 onAutoFocus(boolean focused, boolean shutterButtonPressed)292 public void onAutoFocus(boolean focused, boolean shutterButtonPressed) { 293 if (mState == STATE_FOCUSING_SNAP_ON_FINISH) { 294 // Take the picture no matter focus succeeds or fails. No need 295 // to play the AF sound if we're about to play the shutter 296 // sound. 297 if (focused) { 298 mState = STATE_SUCCESS; 299 } else { 300 mState = STATE_FAIL; 301 } 302 updateFocusUI(); 303 capture(); 304 } else if (mState == STATE_FOCUSING) { 305 // This happens when (1) user is half-pressing the focus key or 306 // (2) touch focus is triggered. Play the focus tone. Do not 307 // take the picture now. 308 if (focused) { 309 mState = STATE_SUCCESS; 310 } else { 311 mState = STATE_FAIL; 312 } 313 updateFocusUI(); 314 // If this is triggered by touch focus, cancel focus after a 315 // while. 316 if (mFocusArea != null) { 317 mFocusLocked = true; 318 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY_MILLIS); 319 } 320 if (shutterButtonPressed) { 321 // Lock AE & AWB so users can half-press shutter and recompose. 322 lockAeAwbIfNeeded(); 323 } 324 } else if (mState == STATE_IDLE) { 325 // User has released the focus key before focus completes. 326 // Do nothing. 327 } 328 } 329 onAutoFocusMoving(boolean moving)330 public void onAutoFocusMoving(boolean moving) { 331 if (!mInitialized) { 332 return; 333 } 334 335 336 // Ignore if the camera has detected some faces. 337 if (mUI.hasFaces()) { 338 mUI.clearFocus(); 339 return; 340 } 341 342 // Ignore if we have requested autofocus. This method only handles 343 // continuous autofocus. 344 if (mState != STATE_IDLE) { 345 return; 346 } 347 348 // animate on false->true trasition only b/8219520 349 if (moving && !mPreviousMoving) { 350 // Auto focus at the center of the preview. 351 mUI.setFocusPosition(mPreviewRect.centerX(), mPreviewRect.centerY(), true, 352 getAFRegionEdge(), getAERegionEdge()); 353 mUI.onFocusStarted(); 354 } else if (!moving) { 355 mUI.onFocusSucceeded(); 356 } 357 mPreviousMoving = moving; 358 } 359 360 /** Returns width of auto focus region in pixels. */ getAFRegionEdge()361 private int getAFRegionEdge() { 362 return (int) (Math.min(mPreviewRect.width(), mPreviewRect.height()) * AF_REGION_BOX); 363 } 364 365 /** Returns width of metering region in pixels. */ getAERegionEdge()366 private int getAERegionEdge() { 367 return (int) (Math.min(mPreviewRect.width(), mPreviewRect.height()) * AE_REGION_BOX); 368 } 369 370 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) initializeFocusAreas(int x, int y)371 private void initializeFocusAreas(int x, int y) { 372 if (mFocusArea == null) { 373 mFocusArea = new ArrayList<Area>(); 374 mFocusArea.add(new Area(new Rect(), 1)); 375 } 376 377 // Convert the coordinates to driver format. 378 calculateTapArea(x, y, getAFRegionEdge(), mFocusArea.get(0).rect); 379 } 380 381 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) initializeMeteringAreas(int x, int y)382 private void initializeMeteringAreas(int x, int y) { 383 if (mMeteringArea == null) { 384 mMeteringArea = new ArrayList<Area>(); 385 mMeteringArea.add(new Area(new Rect(), 1)); 386 } 387 388 // Convert the coordinates to driver format. 389 calculateTapArea(x, y, getAERegionEdge(), mMeteringArea.get(0).rect); 390 } 391 onSingleTapUp(int x, int y)392 public void onSingleTapUp(int x, int y) { 393 if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) { 394 return; 395 } 396 397 // Let users be able to cancel previous touch focus. 398 if ((mFocusArea != null) && (mState == STATE_FOCUSING || 399 mState == STATE_SUCCESS || mState == STATE_FAIL)) { 400 cancelAutoFocus(); 401 } 402 if (mPreviewRect.width() == 0 || mPreviewRect.height() == 0) { 403 return; 404 } 405 // Initialize variables. 406 // Initialize mFocusArea. 407 if (mFocusAreaSupported) { 408 initializeFocusAreas(x, y); 409 } 410 // Initialize mMeteringArea. 411 if (mMeteringAreaSupported) { 412 initializeMeteringAreas(x, y); 413 } 414 415 // Use margin to set the focus indicator to the touched area. 416 mUI.setFocusPosition(x, y, false, getAFRegionEdge(), getAERegionEdge()); 417 // Log manual tap to focus. 418 mTouchCoordinate = new TouchCoordinate(x, y, mPreviewRect.width(), mPreviewRect.height()); 419 mTouchTime = System.currentTimeMillis(); 420 421 // Stop face detection because we want to specify focus and metering area. 422 mListener.stopFaceDetection(); 423 424 // Set the focus area and metering area. 425 mListener.setFocusParameters(); 426 if (mFocusAreaSupported) { 427 autoFocus(); 428 } else { // Just show the indicator in all other cases. 429 updateFocusUI(); 430 // Reset the metering area in 4 seconds. 431 mHandler.removeMessages(RESET_TOUCH_FOCUS); 432 mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY_MILLIS); 433 } 434 } 435 onPreviewStarted()436 public void onPreviewStarted() { 437 mState = STATE_IDLE; 438 resetTouchFocus(); 439 } 440 onPreviewStopped()441 public void onPreviewStopped() { 442 // If auto focus was in progress, it would have been stopped. 443 mState = STATE_IDLE; 444 updateFocusUI(); 445 } 446 onCameraReleased()447 public void onCameraReleased() { 448 onPreviewStopped(); 449 } 450 451 @Override onMoving()452 public void onMoving() { 453 if (mFocusLocked) { 454 Log.d(TAG, "onMoving: Early focus unlock."); 455 cancelAutoFocus(); 456 } 457 } 458 459 /** 460 * Triggers the autofocus and sets the specified state. 461 * 462 * @param focusingState The state to use when focus is in progress. 463 */ autoFocus(int focusingState)464 private void autoFocus(int focusingState) { 465 mListener.autoFocus(); 466 mState = focusingState; 467 // Pause the face view because the driver will keep sending face 468 // callbacks after the focus completes. 469 mUI.pauseFaceDetection(); 470 updateFocusUI(); 471 mHandler.removeMessages(RESET_TOUCH_FOCUS); 472 } 473 474 /** 475 * Triggers the autofocus and set the state to indicate the focus is in 476 * progress. 477 */ autoFocus()478 private void autoFocus() { 479 autoFocus(STATE_FOCUSING); 480 } 481 482 /** 483 * Triggers the autofocus and set the state to which a capture will happen 484 * in the following autofocus callback. 485 */ autoFocusAndCapture()486 private void autoFocusAndCapture() { 487 autoFocus(STATE_FOCUSING_SNAP_ON_FINISH); 488 } 489 cancelAutoFocus()490 private void cancelAutoFocus() { 491 Log.v(TAG, "Cancel autofocus."); 492 // Reset the tap area before calling mListener.cancelAutofocus. 493 // Otherwise, focus mode stays at auto and the tap area passed to the 494 // driver is not reset. 495 resetTouchFocus(); 496 mListener.cancelAutoFocus(); 497 mUI.resumeFaceDetection(); 498 mState = STATE_IDLE; 499 mFocusLocked = false; 500 updateFocusUI(); 501 mHandler.removeMessages(RESET_TOUCH_FOCUS); 502 } 503 capture()504 private void capture() { 505 if (mListener.capture()) { 506 mState = STATE_IDLE; 507 mHandler.removeMessages(RESET_TOUCH_FOCUS); 508 } 509 } 510 getFocusMode( final CameraCapabilities.FocusMode currentFocusMode)511 public CameraCapabilities.FocusMode getFocusMode( 512 final CameraCapabilities.FocusMode currentFocusMode) { 513 if (mOverrideFocusMode != null) { 514 Log.v(TAG, "returning override focus: " + mOverrideFocusMode); 515 return mOverrideFocusMode; 516 } 517 if (mCapabilities == null) { 518 Log.v(TAG, "no capabilities, returning default AUTO focus mode"); 519 return CameraCapabilities.FocusMode.AUTO; 520 } 521 522 if (mFocusAreaSupported && mFocusArea != null) { 523 Log.v(TAG, "in tap to focus, returning AUTO focus mode"); 524 // Always use autofocus in tap-to-focus. 525 mFocusMode = CameraCapabilities.FocusMode.AUTO; 526 } else { 527 String focusSetting = mSettingsManager.getString(mAppController.getCameraScope(), 528 Keys.KEY_FOCUS_MODE); 529 Log.v(TAG, "stored focus setting for camera: " + focusSetting); 530 // The default is continuous autofocus. 531 mFocusMode = mCapabilities.getStringifier().focusModeFromString(focusSetting); 532 Log.v(TAG, "focus mode resolved from setting: " + mFocusMode); 533 // Try to find a supported focus mode from the default list. 534 if (mFocusMode == null) { 535 for (CameraCapabilities.FocusMode mode : mDefaultFocusModes) { 536 if (mCapabilities.supports(mode)) { 537 mFocusMode = mode; 538 Log.v(TAG, "selected supported focus mode from default list" + mode); 539 break; 540 } 541 } 542 } 543 } 544 if (!mCapabilities.supports(mFocusMode)) { 545 // For some reasons, the driver does not support the current 546 // focus mode. Fall back to auto. 547 if (mCapabilities.supports(CameraCapabilities.FocusMode.AUTO)) { 548 Log.v(TAG, "no supported focus mode, falling back to AUTO"); 549 mFocusMode = CameraCapabilities.FocusMode.AUTO; 550 } else { 551 Log.v(TAG, "no supported focus mode, falling back to current: " + currentFocusMode); 552 mFocusMode = currentFocusMode; 553 } 554 } 555 return mFocusMode; 556 } 557 getFocusAreas()558 public List<Area> getFocusAreas() { 559 return mFocusArea; 560 } 561 getMeteringAreas()562 public List<Area> getMeteringAreas() { 563 return mMeteringArea; 564 } 565 updateFocusUI()566 public void updateFocusUI() { 567 if (!mInitialized) { 568 // Show only focus indicator or face indicator. 569 return; 570 } 571 if (mState == STATE_IDLE) { 572 if (mFocusArea == null) { 573 mUI.clearFocus(); 574 } else { 575 // Users touch on the preview and the indicator represents the 576 // metering area. Either focus area is not supported or 577 // autoFocus call is not required. 578 mUI.onFocusStarted(); 579 } 580 } else if (mState == STATE_FOCUSING) { 581 mUI.onFocusStarted(); 582 } else { 583 if (mFocusMode == CameraCapabilities.FocusMode.CONTINUOUS_PICTURE) { 584 // TODO: check HAL behavior and decide if this can be removed. 585 mUI.onFocusSucceeded(); 586 } else if (mState == STATE_SUCCESS) { 587 mUI.onFocusSucceeded(); 588 } else if (mState == STATE_FAIL) { 589 mUI.onFocusFailed(); 590 } 591 } 592 } 593 resetTouchFocus()594 public void resetTouchFocus() { 595 if (!mInitialized) { 596 return; 597 } 598 599 // Put focus indicator to the center. clear reset position 600 mUI.clearFocus(); 601 // Initialize mFocusArea. 602 mFocusArea = null; 603 mMeteringArea = null; 604 // This will cause current module to call getFocusAreas() and 605 // getMeteringAreas() and send updated regions to camera. 606 mListener.setFocusParameters(); 607 608 if (mTouchCoordinate != null) { 609 UsageStatistics.instance().tapToFocus(mTouchCoordinate, 610 0.001f * (System.currentTimeMillis() - mTouchTime)); 611 mTouchCoordinate = null; 612 } 613 } 614 calculateTapArea(int x, int y, int size, Rect rect)615 private void calculateTapArea(int x, int y, int size, Rect rect) { 616 int left = CameraUtil.clamp(x - size / 2, mPreviewRect.left, 617 mPreviewRect.right - size); 618 int top = CameraUtil.clamp(y - size / 2, mPreviewRect.top, 619 mPreviewRect.bottom - size); 620 621 RectF rectF = new RectF(left, top, left + size, top + size); 622 mMatrix.mapRect(rectF); 623 CameraUtil.rectFToRect(rectF, rect); 624 } 625 getFocusState()626 /* package */ int getFocusState() { 627 return mState; 628 } 629 isFocusCompleted()630 public boolean isFocusCompleted() { 631 return mState == STATE_SUCCESS || mState == STATE_FAIL; 632 } 633 isFocusingSnapOnFinish()634 public boolean isFocusingSnapOnFinish() { 635 return mState == STATE_FOCUSING_SNAP_ON_FINISH; 636 } 637 removeMessages()638 public void removeMessages() { 639 mHandler.removeMessages(RESET_TOUCH_FOCUS); 640 } 641 overrideFocusMode(CameraCapabilities.FocusMode focusMode)642 public void overrideFocusMode(CameraCapabilities.FocusMode focusMode) { 643 mOverrideFocusMode = focusMode; 644 } 645 setAeAwbLock(boolean lock)646 public void setAeAwbLock(boolean lock) { 647 mAeAwbLock = lock; 648 } 649 getAeAwbLock()650 public boolean getAeAwbLock() { 651 return mAeAwbLock; 652 } 653 needAutoFocusCall(CameraCapabilities.FocusMode focusMode)654 private boolean needAutoFocusCall(CameraCapabilities.FocusMode focusMode) { 655 return !(focusMode == CameraCapabilities.FocusMode.INFINITY 656 || focusMode == CameraCapabilities.FocusMode.FIXED 657 || focusMode == CameraCapabilities.FocusMode.EXTENDED_DOF); 658 } 659 } 660