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 ;
2528
2629import java .io .IOException ;
30+ import java .util .Collections ;
2731import java .util .List ;
2832import java .util .Set ;
2933import 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 ();
@@ -103,6 +128,7 @@ void stop() {
103128 }
104129 mShowingPreview = false ;
105130 releaseCamera ();
131+ mCameraHandler .removeCallbacks (mReturnToContinuousAFRunnable );
106132 }
107133
108134 // Suppresses Camera#setPreviewTexture
@@ -141,6 +167,7 @@ void setFacing(int facing) {
141167 stop ();
142168 start ();
143169 }
170+ resetCoordinateTransformer ();
144171 }
145172
146173 @ Override
@@ -223,11 +250,12 @@ void takePicture() {
223250 throw new IllegalStateException (
224251 "Camera is not ready. Call start() before takePicture()." );
225252 }
226- if (getAutoFocus ()) {
253+ if (getAutoFocus () || isAutoFocusInProgress . get () ) {
227254 mCamera .cancelAutoFocus ();
228255 mCamera .autoFocus (new Camera .AutoFocusCallback () {
229256 @ Override
230257 public void onAutoFocus (boolean success , Camera camera ) {
258+ isAutoFocusInProgress .set (false );
231259 takePictureInternal ();
232260 }
233261 });
@@ -238,15 +266,25 @@ public void onAutoFocus(boolean success, Camera camera) {
238266
239267 void takePictureInternal () {
240268 if (!isPictureCaptureInProgress .getAndSet (true )) {
241- mCamera .takePicture (null , null , null , new Camera .PictureCallback () {
269+ mCamera .takePicture (new Camera .ShutterCallback () {
270+ @ Override
271+ public void onShutter () {
272+ if (setAutoFocusInternal (mAutoFocus )) {
273+ mCamera .setParameters (mCameraParameters );
274+ }
275+ }
276+ }, null , null , new Camera .PictureCallback () {
242277 @ Override
243278 public void onPictureTaken (byte [] data , Camera camera ) {
244279 isPictureCaptureInProgress .set (false );
245280 mCallback .onPictureTaken (data );
246- camera .cancelAutoFocus ();
247- camera .startPreview ();
281+ if (mShowingPreview ) {
282+ camera .cancelAutoFocus ();
283+ camera .startPreview ();
284+ }
248285 }
249286 });
287+ mCameraHandler .removeCallbacks (mReturnToContinuousAFRunnable );
250288 }
251289 }
252290
@@ -256,6 +294,7 @@ void setDisplayOrientation(int displayOrientation) {
256294 return ;
257295 }
258296 mDisplayOrientation = displayOrientation ;
297+ resetCoordinateTransformer ();
259298 if (isCameraOpened ()) {
260299 mCameraParameters .setRotation (calcCameraRotation (displayOrientation ));
261300 mCamera .setParameters (mCameraParameters );
@@ -270,6 +309,49 @@ void setDisplayOrientation(int displayOrientation) {
270309 }
271310 }
272311
312+ @ Override
313+ boolean hasManualFocus () {
314+ return isCameraOpened () && getFacing () == Constants .FACING_BACK
315+ && (isFocusAreaSupported () || isMeteringAreaSupported ());
316+ }
317+
318+ @ Override
319+ void setFocusAt (int x , int y ) {
320+ if (isPictureCaptureInProgress .get ()) {
321+ return ;
322+ }
323+ mCallback .onFocusAt (x , y );
324+ if (isAutoFocusInProgress .getAndSet (false )) {
325+ mCamera .cancelAutoFocus ();
326+ }
327+ if (!isAutoFocusInProgress .getAndSet (true ) && setFocusAndMeterInternal (x , y )) {
328+ mCamera .setParameters (mCameraParameters );
329+ mCamera .autoFocus (new Camera .AutoFocusCallback () {
330+ @ Override
331+ public void onAutoFocus (boolean success , Camera camera ) {
332+ isAutoFocusInProgress .set (false );
333+ resumeContinuousAFAfterDelay (Constants .FOCUS_HOLD_MILLIS );
334+ }
335+ });
336+ }
337+ }
338+
339+ boolean isFocusAreaSupported () {
340+ if (Build .VERSION .SDK_INT >= 14 ) {
341+ List <String > supportedFocusModes = mCameraParameters .getSupportedFocusModes ();
342+ return (supportedFocusModes .contains (Camera .Parameters .FOCUS_MODE_AUTO )
343+ && mCameraParameters .getMaxNumFocusAreas () > 0 );
344+ }
345+ return false ;
346+ }
347+
348+ boolean isMeteringAreaSupported () {
349+ if (Build .VERSION .SDK_INT >= 14 ) {
350+ return mCameraParameters .getMaxNumMeteringAreas () > 0 ;
351+ }
352+ return false ;
353+ }
354+
273355 /**
274356 * This rewrites {@link #mCameraId} and {@link #mCameraInfo}.
275357 */
@@ -446,6 +528,14 @@ private boolean setAutoFocusInternal(boolean autoFocus) {
446528 } else {
447529 mCameraParameters .setFocusMode (modes .get (0 ));
448530 }
531+ if (Build .VERSION .SDK_INT >= 14 && hasManualFocus ()) {
532+ if (isFocusAreaSupported ()) {
533+ mCameraParameters .setFocusAreas (null );
534+ }
535+ if (isMeteringAreaSupported ()) {
536+ mCameraParameters .setMeteringAreas (null );
537+ }
538+ }
449539 return true ;
450540 } else {
451541 return false ;
@@ -477,4 +567,69 @@ private boolean setFlashInternal(int flash) {
477567 }
478568 }
479569
570+ /**
571+ * @return {@code true} if {@link #mCameraParameters} was modified.
572+ */
573+ private boolean setFocusAndMeterInternal (int x , int y ) {
574+ if (Build .VERSION .SDK_INT >= 14 && hasManualFocus () && mCoordinateTransformer != null ) {
575+ if (isFocusAreaSupported ()) {
576+ List <Camera .Area > focusArea = Collections .singletonList (
577+ new Camera .Area (computeCameraRectFromPreviewCoordinates (x , y ,
578+ getAFRegionSizePx ()), 1 ));
579+ mCameraParameters .setFocusAreas (focusArea );
580+ }
581+ if (isMeteringAreaSupported ()) {
582+ List <Camera .Area > meteringArea = Collections .singletonList (
583+ new Camera .Area (computeCameraRectFromPreviewCoordinates (x , y ,
584+ getAERegionSizePx ()), 1 ));
585+ mCameraParameters .setMeteringAreas (meteringArea );
586+ }
587+ mCameraParameters .setFocusMode (Camera .Parameters .FOCUS_MODE_AUTO );
588+ return true ;
589+ } else {
590+ return false ;
591+ }
592+ }
593+
594+ /**
595+ * @return {@code width} of auto focus region in pixels.
596+ */
597+ private int getAFRegionSizePx () {
598+ return (int ) (Math .min (mPreview .getWidth (), mPreview .getHeight ())
599+ * Constants .AF_REGION_BOX );
600+ }
601+
602+ /**
603+ * @return {@code width} of metering region in pixels.
604+ */
605+ private int getAERegionSizePx () {
606+ return (int ) (Math .min (mPreview .getWidth (), mPreview .getHeight ())
607+ * Constants .AE_REGION_BOX );
608+ }
609+
610+ private Rect computeCameraRectFromPreviewCoordinates (int x , int y , int size ) {
611+ int left = CameraUtil .clamp (x - size / 2 , mPreviewRect .left ,
612+ mPreviewRect .right - size );
613+ int top = CameraUtil .clamp (y - size / 2 , mPreviewRect .top ,
614+ mPreviewRect .bottom - size );
615+ RectF rectF = new RectF (left , top , left + size , top + size );
616+ return CameraUtil .rectFToRect (mCoordinateTransformer .toCameraSpace (rectF ));
617+ }
618+
619+ private void resetCoordinateTransformer () {
620+ if (mPreview .getWidth () > 0 && mPreview .getHeight () > 0 ) {
621+ mCoordinateTransformer = new CameraCoordinateTransformer (
622+ mFacing == Constants .FACING_FRONT ,
623+ calcCameraRotation (mDisplayOrientation ),
624+ CameraUtil .rectToRectF (mPreviewRect ));
625+ }
626+ }
627+
628+ /**
629+ * Resume AF_MODE_CONTINUOUS_PICTURE after FOCUS_HOLD_MILLIS.
630+ */
631+ private void resumeContinuousAFAfterDelay (int millis ) {
632+ mCameraHandler .removeCallbacks (mReturnToContinuousAFRunnable );
633+ mCameraHandler .postDelayed (mReturnToContinuousAFRunnable , millis );
634+ }
480635}
0 commit comments