1717package com .google .android .cameraview ;
1818
1919import android .annotation .SuppressLint ;
20+ import android .graphics .Rect ;
21+ import android .graphics .RectF ;
2022import android .graphics .SurfaceTexture ;
2123import android .hardware .Camera ;
2224import android .os .Build ;
25+ import android .os .Handler ;
2326import android .support .v4 .util .SparseArrayCompat ;
2427import android .view .SurfaceHolder ;
2528import java .io .IOException ;
29+ import java .util .Collections ;
2630import java .util .List ;
2731import java .util .Set ;
2832import java .util .SortedSet ;
@@ -49,6 +53,8 @@ class Camera1 extends CameraViewImpl {
4953
5054 private final AtomicBoolean isPictureCaptureInProgress = new AtomicBoolean (false );
5155
56+ private final AtomicBoolean isAutoFocusInProgress = new AtomicBoolean (false );
57+
5258 Camera mCamera ;
5359
5460 private Camera .Parameters mCameraParameters ;
@@ -71,11 +77,30 @@ class Camera1 extends CameraViewImpl {
7177
7278 private int mDisplayOrientation ;
7379
80+ private CameraCoordinateTransformer mCoordinateTransformer ;
81+
82+ private Rect mPreviewRect = new Rect (0 , 0 , 0 , 0 );
83+
84+ private final Handler mCameraHandler ;
85+
86+ private final Runnable mReturnToContinuousAFRunnable = new Runnable () {
87+ @ Override
88+ public void run () {
89+ if (setAutoFocusInternal (mAutoFocus )) {
90+ mCamera .setParameters (mCameraParameters );
91+ mCamera .cancelAutoFocus ();
92+ }
93+ }
94+ };
95+
7496 Camera1 (Callback callback , PreviewImpl preview ) {
7597 super (callback , preview );
98+ mCameraHandler = new Handler ();
7699 preview .setCallback (new PreviewImpl .Callback () {
77100 @ Override
78101 public void onSurfaceChanged () {
102+ mPreviewRect .set (0 , 0 , mPreview .getWidth (), mPreview .getHeight ());
103+ resetCoordinateTransformer ();
79104 if (mCamera != null ) {
80105 setUpPreview ();
81106 adjustCameraParameters ();
@@ -108,6 +133,8 @@ void stop() {
108133 }
109134 mShowingPreview = false ;
110135 releaseCamera ();
136+
137+ mCameraHandler .removeCallbacks (mReturnToContinuousAFRunnable );
111138 }
112139
113140 // Suppresses Camera#setPreviewTexture
@@ -146,6 +173,8 @@ void setFacing(int facing) {
146173 stop ();
147174 start ();
148175 }
176+
177+ resetCoordinateTransformer ();
149178 }
150179
151180 @ Override
@@ -229,11 +258,12 @@ void takePicture() {
229258 throw new IllegalStateException (
230259 "Camera is not ready. Call start() before takePicture()." );
231260 }
232- if (getAutoFocus ()) {
261+ if (getAutoFocus () || isAutoFocusInProgress . get () ) {
233262 mCamera .cancelAutoFocus ();
234263 mCamera .autoFocus (new Camera .AutoFocusCallback () {
235264 @ Override
236265 public void onAutoFocus (boolean success , Camera camera ) {
266+ isAutoFocusInProgress .set (false );
237267 takePictureInternal ();
238268 }
239269 });
@@ -244,7 +274,14 @@ public void onAutoFocus(boolean success, Camera camera) {
244274
245275 void takePictureInternal () {
246276 if (!isPictureCaptureInProgress .getAndSet (true )) {
247- mCamera .takePicture (null , null , null , new Camera .PictureCallback () {
277+ mCamera .takePicture (new Camera .ShutterCallback () {
278+ @ Override
279+ public void onShutter () {
280+ if (setAutoFocusInternal (mAutoFocus )) {
281+ mCamera .setParameters (mCameraParameters );
282+ }
283+ }
284+ }, null , null , new Camera .PictureCallback () {
248285 @ Override
249286 public void onPictureTaken (byte [] data , Camera camera ) {
250287 isPictureCaptureInProgress .set (false );
@@ -256,6 +293,7 @@ public void onPictureTaken(byte[] data, Camera camera) {
256293 }
257294 }
258295 });
296+ mCameraHandler .removeCallbacks (mReturnToContinuousAFRunnable );
259297 }
260298 }
261299
@@ -265,6 +303,7 @@ void setDisplayOrientation(int displayOrientation) {
265303 return ;
266304 }
267305 mDisplayOrientation = displayOrientation ;
306+ resetCoordinateTransformer ();
268307 if (isCameraOpened ()) {
269308 mCameraParameters .setRotation (calcCameraRotation (displayOrientation ));
270309 mCamera .setParameters (mCameraParameters );
@@ -279,6 +318,49 @@ void setDisplayOrientation(int displayOrientation) {
279318 }
280319 }
281320
321+ @ Override
322+ boolean hasManualFocus () {
323+ return isCameraOpened () && getFacing () == Constants .FACING_BACK
324+ && (isFocusAreaSupported () || isMeteringAreaSupported ());
325+ }
326+
327+ @ Override
328+ void setFocusAt (int x , int y ) {
329+ if (isPictureCaptureInProgress .get ()) {
330+ return ;
331+ }
332+ mCallback .onFocusAt (x , y );
333+ if (isAutoFocusInProgress .getAndSet (false )) {
334+ mCamera .cancelAutoFocus ();
335+ }
336+ if (!isAutoFocusInProgress .getAndSet (true ) && setFocusAndMeterInternal (x , y )) {
337+ mCamera .setParameters (mCameraParameters );
338+ mCamera .autoFocus (new Camera .AutoFocusCallback () {
339+ @ Override
340+ public void onAutoFocus (boolean success , Camera camera ) {
341+ isAutoFocusInProgress .set (false );
342+ resumeContinuousAFAfterDelay (Constants .FOCUS_HOLD_MILLIS );
343+ }
344+ });
345+ }
346+ }
347+
348+ boolean isFocusAreaSupported () {
349+ if (Build .VERSION .SDK_INT >= 14 ) {
350+ List <String > supportedFocusModes = mCameraParameters .getSupportedFocusModes ();
351+ return (supportedFocusModes .contains (Camera .Parameters .FOCUS_MODE_AUTO )
352+ && mCameraParameters .getMaxNumFocusAreas () > 0 );
353+ }
354+ return false ;
355+ }
356+
357+ boolean isMeteringAreaSupported () {
358+ if (Build .VERSION .SDK_INT >= 14 ) {
359+ return mCameraParameters .getMaxNumMeteringAreas () > 0 ;
360+ }
361+ return false ;
362+ }
363+
282364 /**
283365 * This rewrites {@link #mCameraId} and {@link #mCameraInfo}.
284366 */
@@ -484,12 +566,88 @@ private boolean setAutoFocusInternal(boolean autoFocus) {
484566 } else {
485567 mCameraParameters .setFocusMode (modes .get (0 ));
486568 }
569+
570+ if (Build .VERSION .SDK_INT >= 14 && hasManualFocus ()) {
571+ if (isFocusAreaSupported ()) {
572+ mCameraParameters .setFocusAreas (null );
573+ }
574+ if (isMeteringAreaSupported ()) {
575+ mCameraParameters .setMeteringAreas (null );
576+ }
577+ }
578+
579+ return true ;
580+ } else {
581+ return false ;
582+ }
583+ }
584+
585+ /**
586+ * @return {@code true} if {@link #mCameraParameters} was modified.
587+ */
588+ private boolean setFocusAndMeterInternal (int x , int y ) {
589+ if (Build .VERSION .SDK_INT >= 14 && hasManualFocus () && mCoordinateTransformer != null ) {
590+ if (isFocusAreaSupported ()) {
591+ List <Camera .Area > focusArea = Collections .singletonList (
592+ new Camera .Area (computeCameraRectFromPreviewCoordinates (x , y ,
593+ getAFRegionSizePx ()), 1 ));
594+ mCameraParameters .setFocusAreas (focusArea );
595+ }
596+ if (isMeteringAreaSupported ()) {
597+ List <Camera .Area > meteringArea = Collections .singletonList (
598+ new Camera .Area (computeCameraRectFromPreviewCoordinates (x , y ,
599+ getAERegionSizePx ()), 1 ));
600+ mCameraParameters .setMeteringAreas (meteringArea );
601+ }
602+ mCameraParameters .setFocusMode (Camera .Parameters .FOCUS_MODE_AUTO );
487603 return true ;
488604 } else {
489605 return false ;
490606 }
491607 }
492608
609+ /**
610+ * @return {@code width} of auto focus region in pixels.
611+ */
612+ private int getAFRegionSizePx () {
613+ return (int ) (Math .min (mPreview .getWidth (), mPreview .getHeight ())
614+ * Constants .AF_REGION_BOX );
615+ }
616+
617+ /**
618+ * @return {@code width} of metering region in pixels.
619+ */
620+ private int getAERegionSizePx () {
621+ return (int ) (Math .min (mPreview .getWidth (), mPreview .getHeight ())
622+ * Constants .AE_REGION_BOX );
623+ }
624+
625+ private Rect computeCameraRectFromPreviewCoordinates (int x , int y , int size ) {
626+ int left = CameraUtil .clamp (x - size / 2 , mPreviewRect .left ,
627+ mPreviewRect .right - size );
628+ int top = CameraUtil .clamp (y - size / 2 , mPreviewRect .top ,
629+ mPreviewRect .bottom - size );
630+ RectF rectF = new RectF (left , top , left +size , top + size );
631+ return CameraUtil .rectFToRect (mCoordinateTransformer .toCameraSpace (rectF ));
632+ }
633+
634+ private void resetCoordinateTransformer () {
635+ if (mPreview .getWidth () > 0 && mPreview .getHeight () > 0 ) {
636+ mCoordinateTransformer = new CameraCoordinateTransformer (
637+ mFacing == Constants .FACING_FRONT ,
638+ calcCameraRotation (mDisplayOrientation ),
639+ CameraUtil .rectToRectF (mPreviewRect ));
640+ }
641+ }
642+
643+ /**
644+ * Resume AF_MODE_CONTINUOUS_PICTURE after FOCUS_HOLD_MILLIS.
645+ */
646+ private void resumeContinuousAFAfterDelay (int millis ) {
647+ mCameraHandler .removeCallbacks (mReturnToContinuousAFRunnable );
648+ mCameraHandler .postDelayed (mReturnToContinuousAFRunnable , millis );
649+ }
650+
493651 /**
494652 * @return {@code true} if {@link #mCameraParameters} was modified.
495653 */
0 commit comments