OneCameraImpl.java revision 34ac0609e30601fe2ce9b2338a173d7740ab3f82
1f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling/* 2f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Copyright (C) 2014 The Android Open Source Project 3f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 4f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Licensed under the Apache License, Version 2.0 (the "License"); 5f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * you may not use this file except in compliance with the License. 6f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * You may obtain a copy of the License at 7f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 8f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * http://www.apache.org/licenses/LICENSE-2.0 9f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 10f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Unless required by applicable law or agreed to in writing, software 11f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * distributed under the License is distributed on an "AS IS" BASIS, 12f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * See the License for the specific language governing permissions and 14f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * limitations under the License. 15f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 16f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 17f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingpackage com.android.camera.one.v2; 18f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 19f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.graphics.ImageFormat; 2030ffce08f511fbed4cf18daa743778b541583351Andy Huibersimport android.graphics.Matrix; 21f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.graphics.Rect; 22f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.CameraAccessException; 23f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.CameraCaptureSession; 24f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.CameraCharacteristics; 25f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.CameraDevice; 26f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.CameraMetadata; 27f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.CaptureRequest; 2830ffce08f511fbed4cf18daa743778b541583351Andy Huibersimport android.hardware.camera2.CaptureResult; 2930ffce08f511fbed4cf18daa743778b541583351Andy Huibersimport android.hardware.camera2.TotalCaptureResult; 3030ffce08f511fbed4cf18daa743778b541583351Andy Huibersimport android.hardware.camera2.params.MeteringRectangle; 31f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.params.StreamConfigurationMap; 32f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.media.Image; 33f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.media.ImageReader; 3457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport android.net.Uri; 35f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.os.Handler; 36f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.os.HandlerThread; 3730ffce08f511fbed4cf18daa743778b541583351Andy Huibersimport android.os.SystemClock; 38f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.view.OrientationEventListener; 39f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.view.Surface; 40f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 4157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport com.android.camera.Exif; 4257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport com.android.camera.app.MediaSaver.OnMediaSavedListener; 4399a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibersimport com.android.camera.debug.DebugPropertyHelper; 44f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport com.android.camera.debug.Log; 45f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport com.android.camera.debug.Log.Tag; 4657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport com.android.camera.exif.ExifInterface; 4757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport com.android.camera.exif.ExifTag; 4857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport com.android.camera.exif.Rational; 49f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport com.android.camera.one.AbstractOneCamera; 50f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport com.android.camera.one.OneCamera; 510cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberlingimport com.android.camera.one.OneCamera.PhotoCaptureParameters.Flash; 52f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport com.android.camera.session.CaptureSession; 5330ffce08f511fbed4cf18daa743778b541583351Andy Huibersimport com.android.camera.util.CameraUtil; 5451163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberlingimport com.android.camera.util.CaptureDataSerializer; 55967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lallimport com.android.camera.util.JpegUtilNative; 56967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lallimport com.android.camera.util.Size; 57f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 5851163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberlingimport java.io.File; 5957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport java.io.IOException; 60f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport java.nio.ByteBuffer; 61f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport java.util.ArrayList; 62f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport java.util.LinkedList; 63f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport java.util.List; 64f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 65f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling/** 66f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * {@link OneCamera} implementation directly on top of the Camera2 API. 67f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 68f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingpublic class OneCameraImpl extends AbstractOneCamera { 69f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 70f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** Captures that are requested but haven't completed yet. */ 71f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private static class InFlightCapture { 7257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling final PhotoCaptureParameters parameters; 73f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling final CaptureSession session; 74f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 7557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling public InFlightCapture(PhotoCaptureParameters parameters, 76f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling CaptureSession session) { 7757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling this.parameters = parameters; 78f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling this.session = session; 79f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 80f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 81f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 82f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private static final Tag TAG = new Tag("OneCameraImpl2"); 8330ffce08f511fbed4cf18daa743778b541583351Andy Huibers 8499a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers /** If true, will write data about each capture request to disk. */ 8599a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers private static final boolean DEBUG_WRITE_CAPTURE_DATA = DebugPropertyHelper.writeCaptureData(); 8699a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers /** If true, will log per-frame AF info. */ 8799a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers private static final boolean DEBUG_FOCUS_LOG = DebugPropertyHelper.showFocusDebugLog(); 8830ffce08f511fbed4cf18daa743778b541583351Andy Huibers 89f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** Default JPEG encoding quality. */ 90f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private static final Byte JPEG_QUALITY = 90; 91f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 92967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall /** 93967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall * Set to ImageFormat.JPEG, to use the hardware encoder, or 9451163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling * ImageFormat.YUV_420_888 to use the software encoder. No other image 9551163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling * formats are supported. 96967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall */ 97967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall private static final int sCaptureImageFormat = ImageFormat.YUV_420_888; 98967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 9930ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Width and height of touch metering region as fraction of longest edge. */ 10030ffce08f511fbed4cf18daa743778b541583351Andy Huibers private static final float METERING_REGION_EDGE = 0.1f; 10130ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Metering region weight between 0 and 1. */ 10230ffce08f511fbed4cf18daa743778b541583351Andy Huibers private static final float METERING_REGION_WEIGHT = 0.25f; 10330ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Duration to hold after manual focus tap. */ 10430ffce08f511fbed4cf18daa743778b541583351Andy Huibers private static final int FOCUS_HOLD_MILLIS = 3000; 10534ac0609e30601fe2ce9b2338a173d7740ab3f82Andy Huibers /** Zero weight 3A region, to reset regions per API. */ 10634ac0609e30601fe2ce9b2338a173d7740ab3f82Andy Huibers MeteringRectangle[] ZERO_WEIGHT_3A_REGION = new MeteringRectangle[]{ 10734ac0609e30601fe2ce9b2338a173d7740ab3f82Andy Huibers new MeteringRectangle(0, 0, 1, 1, 0) 10834ac0609e30601fe2ce9b2338a173d7740ab3f82Andy Huibers }; 10930ffce08f511fbed4cf18daa743778b541583351Andy Huibers 11030ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 11130ffce08f511fbed4cf18daa743778b541583351Andy Huibers * CaptureRequest tags. 11230ffce08f511fbed4cf18daa743778b541583351Andy Huibers * <ul> 11330ffce08f511fbed4cf18daa743778b541583351Andy Huibers * <li>{@link #PRESHOT_TRIGGERED_AF}</li> 11430ffce08f511fbed4cf18daa743778b541583351Andy Huibers * <li>{@link #CAPTURE}</li> 11530ffce08f511fbed4cf18daa743778b541583351Andy Huibers * </ul> 11630ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 11730ffce08f511fbed4cf18daa743778b541583351Andy Huibers public static enum RequestTag { 11830ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Request that is part of a pre shot trigger. */ 11930ffce08f511fbed4cf18daa743778b541583351Andy Huibers PRESHOT_TRIGGERED_AF, 12030ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Capture request (purely for logging). */ 12130ffce08f511fbed4cf18daa743778b541583351Andy Huibers CAPTURE 12230ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 12330ffce08f511fbed4cf18daa743778b541583351Andy Huibers 12430ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Current CONTROL_AF_MODE request to Camera2 API. */ 12530ffce08f511fbed4cf18daa743778b541583351Andy Huibers private int mLastRequestedControlAFMode = CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE; 12630ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Last OneCamera.AutoFocusState reported. */ 12730ffce08f511fbed4cf18daa743778b541583351Andy Huibers private AutoFocusState mLastResultAFState = AutoFocusState.INACTIVE; 12830ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Last OneCamera.AutoFocusMode reported. */ 12930ffce08f511fbed4cf18daa743778b541583351Andy Huibers private AutoFocusMode mLastResultAFMode = AutoFocusMode.CONTINUOUS_PICTURE; 13030ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Flag to take a picture when in AUTO mode and the lens is stopped. */ 13130ffce08f511fbed4cf18daa743778b541583351Andy Huibers private boolean mTakePictureWhenLensStoppedAndAuto = false; 13230ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Flag to take a picture when the lens is stopped. */ 13330ffce08f511fbed4cf18daa743778b541583351Andy Huibers private boolean mTakePictureWhenLensIsStopped = false; 13430ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Takes a (delayed) picture with appropriate parameters. */ 13530ffce08f511fbed4cf18daa743778b541583351Andy Huibers private Runnable mTakePictureRunnable; 13630ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Last time takePicture() was called in uptimeMillis. */ 13730ffce08f511fbed4cf18daa743778b541583351Andy Huibers private long mTakePictureStartMillis; 13830ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Runnable that returns to CONTROL_AF_MODE = AF_CONTINUOUS_PICTURE. */ 13951163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling private final Runnable mReturnToContinuousAFRunnable = new Runnable() { 14030ffce08f511fbed4cf18daa743778b541583351Andy Huibers @Override 14130ffce08f511fbed4cf18daa743778b541583351Andy Huibers public void run() { 14230ffce08f511fbed4cf18daa743778b541583351Andy Huibers repeatingPreviewWithReadyListener(null); 14330ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 14430ffce08f511fbed4cf18daa743778b541583351Andy Huibers }; 14530ffce08f511fbed4cf18daa743778b541583351Andy Huibers 14651163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling /** Current zoom value. 1.0 is no zoom. */ 14751163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling private final float mZoomValue = 1f; 14830ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** If partial results was OK, don't need to process total result. */ 14930ffce08f511fbed4cf18daa743778b541583351Andy Huibers private boolean mAutoFocusStateListenerPartialOK = false; 15030ffce08f511fbed4cf18daa743778b541583351Andy Huibers 15130ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 15230ffce08f511fbed4cf18daa743778b541583351Andy Huibers * Common listener for preview frame metadata. 15330ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 15451163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling private final CameraCaptureSession.CaptureListener mAutoFocusStateListener = new 15530ffce08f511fbed4cf18daa743778b541583351Andy Huibers CameraCaptureSession.CaptureListener() { 15630ffce08f511fbed4cf18daa743778b541583351Andy Huibers // AF state information is sometimes available 1 frame before 15730ffce08f511fbed4cf18daa743778b541583351Andy Huibers // onCaptureCompleted(), so we take advantage of that. 15830ffce08f511fbed4cf18daa743778b541583351Andy Huibers @Override 15951163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling public void onCaptureProgressed(CameraCaptureSession session, 16051163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling CaptureRequest request, 16151163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling CaptureResult partialResult) { 16230ffce08f511fbed4cf18daa743778b541583351Andy Huibers 16330ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (partialResult.get(CaptureResult.CONTROL_AF_STATE) != null) { 16430ffce08f511fbed4cf18daa743778b541583351Andy Huibers mAutoFocusStateListenerPartialOK = true; 16530ffce08f511fbed4cf18daa743778b541583351Andy Huibers autofocusStateChangeDispatcher(partialResult); 16699a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers if (DEBUG_FOCUS_LOG) { 16799a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers //logExtraFocusInfo(partialResult); 16830ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 16930ffce08f511fbed4cf18daa743778b541583351Andy Huibers } else { 17030ffce08f511fbed4cf18daa743778b541583351Andy Huibers mAutoFocusStateListenerPartialOK = false; 17130ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 17230ffce08f511fbed4cf18daa743778b541583351Andy Huibers super.onCaptureProgressed(session, request, partialResult); 17330ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 17451163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling 17530ffce08f511fbed4cf18daa743778b541583351Andy Huibers @Override 17651163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling public void onCaptureCompleted(CameraCaptureSession session, 17751163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling CaptureRequest request, 17851163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling TotalCaptureResult result) { 17930ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (!mAutoFocusStateListenerPartialOK) { 18030ffce08f511fbed4cf18daa743778b541583351Andy Huibers autofocusStateChangeDispatcher(result); 18130ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 18299a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers if (DEBUG_FOCUS_LOG) { 18399a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers logExtraFocusInfo(result); 18499a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers } 18530ffce08f511fbed4cf18daa743778b541583351Andy Huibers super.onCaptureCompleted(session, request, result); 18630ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 18730ffce08f511fbed4cf18daa743778b541583351Andy Huibers }; 188f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** Thread on which the camera operations are running. */ 189f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private final HandlerThread mCameraThread; 190f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** Handler of the {@link #mCameraThread}. */ 191f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private final Handler mCameraHandler; 192f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** The characteristics of this camera. */ 193f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private final CameraCharacteristics mCharacteristics; 194f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** The underlying Camera2 API camera device. */ 195f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private final CameraDevice mDevice; 19657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 197f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 198f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * The aspect ratio (width/height) of the full resolution for this camera. 199f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Usually the native aspect ratio of this camera. 200f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 201f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private final double mFullSizeAspectRatio; 202f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** The Camera2 API capture session currently active. */ 203f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private CameraCaptureSession mCaptureSession; 204f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** The surface onto which to render the preview. */ 205f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private Surface mPreviewSurface; 206f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 207f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * A queue of capture requests that have been requested but are not done 208f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * yet. 209f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 21057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling private final LinkedList<InFlightCapture> mCaptureQueue = 21157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling new LinkedList<InFlightCapture>(); 212f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** Whether closing of this device has been requested. */ 213f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private volatile boolean mIsClosed = false; 214f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** A callback that is called when the device is fully closed. */ 215f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private CloseCallback mCloseCallback = null; 216f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 217967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall /** Receives the normal captured images. */ 218967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall private final ImageReader mCaptureImageReader; 219967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall ImageReader.OnImageAvailableListener mCaptureImageListener = 220f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling new ImageReader.OnImageAvailableListener() { 221f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 222f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void onImageAvailable(ImageReader reader) { 22357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling InFlightCapture capture = mCaptureQueue.remove(); 22457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 22551163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling // Since this is not an HDR+ session, we will just save the 22651163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling // result. 22757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling capture.session.startEmpty(); 228f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling byte[] imageBytes = acquireJpegBytesAndClose(reader); 22930ffce08f511fbed4cf18daa743778b541583351Andy Huibers // TODO: The savePicture call here seems to block UI thread. 23057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling savePicture(imageBytes, capture.parameters, capture.session); 23157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling capture.parameters.callback.onPictureTaken(capture.session); 232f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 233f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling }; 234f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 235f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 236f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Instantiates a new camera based on Camera 2 API. 237f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 238f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param device The underlying Camera 2 device. 239f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param characteristics The device's characteristics. 24057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling * @param pictureSize the size of the final image to be taken. 241f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 242f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling OneCameraImpl(CameraDevice device, CameraCharacteristics characteristics, Size pictureSize) { 243f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mDevice = device; 244f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCharacteristics = characteristics; 245f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mFullSizeAspectRatio = calculateFullSizeAspectRatio(characteristics); 246f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 247f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCameraThread = new HandlerThread("OneCamera2"); 248f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCameraThread.start(); 249f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCameraHandler = new Handler(mCameraThread.getLooper()); 250f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 25151163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling mCaptureImageReader = ImageReader.newInstance(pictureSize.getWidth(), 25251163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling pictureSize.getHeight(), 253967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall sCaptureImageFormat, 2); 254967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall mCaptureImageReader.setOnImageAvailableListener(mCaptureImageListener, mCameraHandler); 255f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling Log.d(TAG, "New Camera2 based OneCameraImpl created."); 256f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 257f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 25830ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 25930ffce08f511fbed4cf18daa743778b541583351Andy Huibers * Take picture, initiating an auto focus scan if needed. 26030ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 261f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 26230ffce08f511fbed4cf18daa743778b541583351Andy Huibers public void takePicture(final PhotoCaptureParameters params, final CaptureSession session) { 26330ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (mTakePictureWhenLensStoppedAndAuto || mTakePictureWhenLensIsStopped) { 26430ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Do not do anything when a picture is already in progress. 26530ffce08f511fbed4cf18daa743778b541583351Andy Huibers return; 26630ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 26730ffce08f511fbed4cf18daa743778b541583351Andy Huibers 26830ffce08f511fbed4cf18daa743778b541583351Andy Huibers mTakePictureRunnable = new Runnable() { 26930ffce08f511fbed4cf18daa743778b541583351Andy Huibers @Override 27030ffce08f511fbed4cf18daa743778b541583351Andy Huibers public void run() { 27130ffce08f511fbed4cf18daa743778b541583351Andy Huibers takePictureNow(params, session); 27230ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 27330ffce08f511fbed4cf18daa743778b541583351Andy Huibers }; 27430ffce08f511fbed4cf18daa743778b541583351Andy Huibers mTakePictureStartMillis = SystemClock.uptimeMillis(); 27530ffce08f511fbed4cf18daa743778b541583351Andy Huibers 27630ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (mLastResultAFMode == AutoFocusMode.CONTINUOUS_PICTURE 27730ffce08f511fbed4cf18daa743778b541583351Andy Huibers && mLastResultAFState == AutoFocusState.STOPPED_UNFOCUSED) { 27830ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, "Unfocused: Triggering auto focus scan."); 27930ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Trigger auto focus scan if in CONTINUOUS_PICTURE + unfocused. 28030ffce08f511fbed4cf18daa743778b541583351Andy Huibers mTakePictureWhenLensStoppedAndAuto = true; 28130ffce08f511fbed4cf18daa743778b541583351Andy Huibers repeatingPreviewWithAFTrigger(null, null, RequestTag.PRESHOT_TRIGGERED_AF); 28230ffce08f511fbed4cf18daa743778b541583351Andy Huibers } else if (mLastResultAFState == AutoFocusState.SCANNING) { 28330ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Delay shot if scanning. 28430ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, "Waiting until scan is done before taking shot."); 28530ffce08f511fbed4cf18daa743778b541583351Andy Huibers mTakePictureWhenLensIsStopped = true; 28630ffce08f511fbed4cf18daa743778b541583351Andy Huibers } else { 28730ffce08f511fbed4cf18daa743778b541583351Andy Huibers takePictureNow(params, session); 28830ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 28930ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 29030ffce08f511fbed4cf18daa743778b541583351Andy Huibers 29130ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 29251163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling * Take picture immediately. Parameters passed through from takePicture(). 29330ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 29430ffce08f511fbed4cf18daa743778b541583351Andy Huibers public void takePictureNow(PhotoCaptureParameters params, CaptureSession session) { 29530ffce08f511fbed4cf18daa743778b541583351Andy Huibers long dt = SystemClock.uptimeMillis() - mTakePictureStartMillis; 29630ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, "Taking shot with extra AF delay of " + dt + " ms."); 29757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling // This will throw a RuntimeException, if parameters are not sane. 29857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling params.checkSanity(); 299f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling try { 30030ffce08f511fbed4cf18daa743778b541583351Andy Huibers // JPEG capture. 301f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling CaptureRequest.Builder builder = mDevice 302f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling .createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 303967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 30430ffce08f511fbed4cf18daa743778b541583351Andy Huibers // TODO: Check that these control modes are correct for AWB, AE. 30530ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (mLastRequestedControlAFMode == CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE) { 30630ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.set(CaptureRequest.CONTROL_AF_MODE, 30730ffce08f511fbed4cf18daa743778b541583351Andy Huibers CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE); 30830ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, "CaptureRequest with CONTROL_AF_MODE_CONTINUOUS_PICTURE."); 30930ffce08f511fbed4cf18daa743778b541583351Andy Huibers } else if (mLastRequestedControlAFMode == CameraMetadata.CONTROL_AF_MODE_AUTO) { 31030ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO); 31130ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.set(CaptureRequest.CONTROL_AF_TRIGGER, 31230ffce08f511fbed4cf18daa743778b541583351Andy Huibers CameraMetadata.CONTROL_AF_TRIGGER_IDLE); 31330ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, "CaptureRequest with AUTO."); 31430ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 31530ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.setTag(RequestTag.CAPTURE); 316967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 317967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall if (sCaptureImageFormat == ImageFormat.JPEG) { 318967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall builder.set(CaptureRequest.JPEG_QUALITY, JPEG_QUALITY); 319967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall builder.set(CaptureRequest.JPEG_ORIENTATION, getJpegRotation(params.orientation)); 320967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall } 321967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 322f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling builder.addTarget(mPreviewSurface); 323967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall builder.addTarget(mCaptureImageReader.getSurface()); 3240cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling applyFlashMode(params.flashMode, builder); 3250cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling CaptureRequest request = builder.build(); 32651163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling 32751163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling if (DEBUG_WRITE_CAPTURE_DATA) { 32851163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling final String debugDataDir = makeDebugDir(params.debugDataFolder, 32951163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling "normal_capture_debug"); 33051163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling Log.i(TAG, "Writing capture data to: " + debugDataDir); 33151163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling CaptureDataSerializer.toFile("Normal Capture", request, new File(debugDataDir, 33251163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling "capture.txt")); 33351163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling } 33451163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling 33530ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCaptureSession.capture(request, mAutoFocusStateListener, mCameraHandler); 336f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } catch (CameraAccessException e) { 337967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall Log.e(TAG, "Could not access camera for still image capture."); 338f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling params.callback.onPictureTakenFailed(); 339f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling return; 340f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 34157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling mCaptureQueue.add(new InFlightCapture(params, session)); 342f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 343f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 344f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 345f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void startPreview(Surface previewSurface, CaptureReadyCallback listener) { 346f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mPreviewSurface = previewSurface; 347f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling setupAsync(mPreviewSurface, listener); 348f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 349f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 350f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 351f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void setViewFinderSize(int width, int height) { 352f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling throw new RuntimeException("Not implemented yet."); 353f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 354f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 355f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 356f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public boolean isFlashSupported(boolean enhanced) { 357f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling throw new RuntimeException("Not implemented yet."); 358f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 359f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 360f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 361f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public boolean isSupportingEnhancedMode() { 362f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling throw new RuntimeException("Not implemented yet."); 363f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 364f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 365f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 366f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void close(CloseCallback closeCallback) { 367f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling if (mIsClosed) { 368f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling Log.w(TAG, "Camera is already closed."); 369f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling return; 370f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 37130ffce08f511fbed4cf18daa743778b541583351Andy Huibers try { 37230ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCaptureSession.abortCaptures(); 37330ffce08f511fbed4cf18daa743778b541583351Andy Huibers } catch (CameraAccessException e) { 37430ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.e(TAG, "Could not abort captures in progress."); 37530ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 376f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mIsClosed = true; 377f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCloseCallback = closeCallback; 378f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCameraThread.quitSafely(); 379f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mDevice.close(); 380f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 381f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 382f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 383f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public Size[] getSupportedSizes() { 384f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling StreamConfigurationMap config = mCharacteristics 385f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 386967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall return Size.convert(config.getOutputSizes(sCaptureImageFormat)); 387f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 388f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 389f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 390f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public double getFullSizeAspectRatio() { 391f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling return mFullSizeAspectRatio; 392f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 393f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 39457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling @Override 39557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling public boolean isFrontFacing() { 39657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling return mCharacteristics.get(CameraCharacteristics.LENS_FACING) 39757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling == CameraMetadata.LENS_FACING_FRONT; 39857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } 39957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 40057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling @Override 40157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling public boolean isBackFacing() { 40257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling return mCharacteristics.get(CameraCharacteristics.LENS_FACING) 40357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling == CameraMetadata.LENS_FACING_BACK; 40457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } 40557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 40657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling private void savePicture(byte[] jpegData, final PhotoCaptureParameters captureParams, 40757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling CaptureSession session) { 40857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling int heading = captureParams.heading; 40957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling int width = 0; 41057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling int height = 0; 41157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling int rotation = 0; 41257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling ExifInterface exif = null; 41357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling try { 41457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling exif = new ExifInterface(); 41557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling exif.readExif(jpegData); 41657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 41757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling Integer w = exif.getTagIntValue(ExifInterface.TAG_PIXEL_X_DIMENSION); 41857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling width = (w == null) ? width : w; 41957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling Integer h = exif.getTagIntValue(ExifInterface.TAG_PIXEL_Y_DIMENSION); 42057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling height = (h == null) ? height : h; 42157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 42257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling // Get image rotation from EXIF. 42357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling rotation = Exif.getOrientation(exif); 42457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 42557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling // Set GPS heading direction based on sensor, if location is on. 42657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling if (heading >= 0) { 42757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling ExifTag directionRefTag = exif.buildTag( 42857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling ExifInterface.TAG_GPS_IMG_DIRECTION_REF, 42957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling ExifInterface.GpsTrackRef.MAGNETIC_DIRECTION); 43057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling ExifTag directionTag = exif.buildTag( 43157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling ExifInterface.TAG_GPS_IMG_DIRECTION, 43257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling new Rational(heading, 1)); 43357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling exif.setTag(directionRefTag); 43457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling exif.setTag(directionTag); 43557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } 43657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } catch (IOException e) { 43757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling Log.w(TAG, "Could not read exif from gcam jpeg", e); 43857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling exif = null; 43957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } 44057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling session.saveAndFinish(jpegData, width, height, rotation, exif, new OnMediaSavedListener() { 44157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling @Override 44257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling public void onMediaSaved(Uri uri) { 44357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling captureParams.callback.onPictureSaved(uri); 44457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } 44557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling }); 44657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } 44757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 448f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 449f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Asynchronously sets up the capture session. 450f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 451f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param previewSurface the surface onto which the preview should be 452f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * rendered. 453f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param listener called when setup is completed. 454f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 455f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private void setupAsync(final Surface previewSurface, final CaptureReadyCallback listener) { 456f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCameraHandler.post(new Runnable() { 457f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 458f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void run() { 459f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling setup(previewSurface, listener); 460f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 461f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling }); 462f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 463f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 464f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 465f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Configures and attempts to create a capture session. 466f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 467f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param previewSurface the surface onto which the preview should be 468f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * rendered. 469f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param listener called when the setup is completed. 470f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 471f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private void setup(Surface previewSurface, final CaptureReadyCallback listener) { 472f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling try { 473f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling if (mCaptureSession != null) { 474f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCaptureSession.abortCaptures(); 475f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCaptureSession = null; 476f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 477f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling List<Surface> outputSurfaces = new ArrayList<Surface>(2); 478f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling outputSurfaces.add(previewSurface); 479967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall outputSurfaces.add(mCaptureImageReader.getSurface()); 480f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 481f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateListener() { 482f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 483f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 484f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void onConfigureFailed(CameraCaptureSession session) { 485f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling listener.onSetupFailed(); 486f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 487f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 488f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 489f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void onConfigured(CameraCaptureSession session) { 490f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCaptureSession = session; 49130ffce08f511fbed4cf18daa743778b541583351Andy Huibers repeatingPreviewWithReadyListener(listener); 492f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 493f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 494f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 495f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void onClosed(CameraCaptureSession session) { 496f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling super.onClosed(session); 497f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling if (mCloseCallback != null) { 498f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCloseCallback.onCameraClosed(); 499f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 500f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 501f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling }, mCameraHandler); 502f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } catch (CameraAccessException ex) { 503f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling Log.e(TAG, "Could not set up capture session", ex); 504f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling listener.onSetupFailed(); 505f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 506f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 507f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 508f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 50930ffce08f511fbed4cf18daa743778b541583351Andy Huibers * Request preview capture stream with AF_MODE_CONTINUOUS_PICTURE. 510f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 51130ffce08f511fbed4cf18daa743778b541583351Andy Huibers * @param readyListener called when request was build and sent, or if 51251163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling * setting up the request failed. 513f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 51430ffce08f511fbed4cf18daa743778b541583351Andy Huibers private void repeatingPreviewWithReadyListener(CaptureReadyCallback readyListener) { 515f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling try { 51630ffce08f511fbed4cf18daa743778b541583351Andy Huibers CaptureRequest.Builder builder = mDevice. 51730ffce08f511fbed4cf18daa743778b541583351Andy Huibers createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 51830ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.addTarget(mPreviewSurface); 519f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 52030ffce08f511fbed4cf18daa743778b541583351Andy Huibers mLastRequestedControlAFMode = CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE; 521f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling builder.set(CaptureRequest.CONTROL_AF_MODE, 522f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE); 52334ac0609e30601fe2ce9b2338a173d7740ab3f82Andy Huibers // TODO: Move to apply3ARegions(CaptureRequest.Builder builder). 52434ac0609e30601fe2ce9b2338a173d7740ab3f82Andy Huibers // Reset 3A regions. 52534ac0609e30601fe2ce9b2338a173d7740ab3f82Andy Huibers builder.set(CaptureRequest.CONTROL_AF_REGIONS, ZERO_WEIGHT_3A_REGION); 52634ac0609e30601fe2ce9b2338a173d7740ab3f82Andy Huibers builder.set(CaptureRequest.CONTROL_AE_REGIONS, ZERO_WEIGHT_3A_REGION); 52730ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_IDLE); 52830ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCaptureSession.setRepeatingRequest(builder.build(), mAutoFocusStateListener, 52930ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCameraHandler); 53030ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, "Sent preview request with AF_MODE_CONTINUOUS_PICTURE."); 53130ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (readyListener != null) { 53230ffce08f511fbed4cf18daa743778b541583351Andy Huibers readyListener.onReadyForCapture(); 53330ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 53430ffce08f511fbed4cf18daa743778b541583351Andy Huibers } catch (CameraAccessException ex) { 53530ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.e(TAG, "Could not access camera setting up preview.", ex); 53630ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (readyListener != null) { 53730ffce08f511fbed4cf18daa743778b541583351Andy Huibers readyListener.onSetupFailed(); 53830ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 53930ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 54030ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 54130ffce08f511fbed4cf18daa743778b541583351Andy Huibers 54230ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 54330ffce08f511fbed4cf18daa743778b541583351Andy Huibers * Request preview capture stream with auto focus cycle. 54430ffce08f511fbed4cf18daa743778b541583351Andy Huibers * 54530ffce08f511fbed4cf18daa743778b541583351Andy Huibers * @param focusRegions focus regions, for tap to focus/expose. 54630ffce08f511fbed4cf18daa743778b541583351Andy Huibers * @param meteringRegions metering regions, for tap to focus/expose. 54730ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 54830ffce08f511fbed4cf18daa743778b541583351Andy Huibers private void repeatingPreviewWithAFTrigger(MeteringRectangle[] focusRegions, 54951163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling MeteringRectangle[] meteringRegions, Object tag) { 55030ffce08f511fbed4cf18daa743778b541583351Andy Huibers try { 55130ffce08f511fbed4cf18daa743778b541583351Andy Huibers CaptureRequest.Builder builder; 55230ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 553f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling builder.addTarget(mPreviewSurface); 55430ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 55530ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (focusRegions != null) { 55630ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.set(CaptureRequest.CONTROL_AF_REGIONS, focusRegions); 55730ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 55830ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (meteringRegions != null) { 55930ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.set(CaptureRequest.CONTROL_AE_REGIONS, meteringRegions); 56030ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 56130ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO); 56230ffce08f511fbed4cf18daa743778b541583351Andy Huibers mLastRequestedControlAFMode = CameraMetadata.CONTROL_AF_MODE_AUTO; 56330ffce08f511fbed4cf18daa743778b541583351Andy Huibers 56430ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Step 1: Request single frame CONTROL_AF_TRIGGER_START. 56530ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START); 56630ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCaptureSession.capture(builder.build(), mAutoFocusStateListener, mCameraHandler); 56730ffce08f511fbed4cf18daa743778b541583351Andy Huibers 56830ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Step 2: Request continuous frames CONTROL_AF_TRIGGER_IDLE. 56930ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE); 57030ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.setTag(tag); 57130ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCaptureSession.setRepeatingRequest(builder.build(), mAutoFocusStateListener, 57230ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCameraHandler); 57330ffce08f511fbed4cf18daa743778b541583351Andy Huibers resumeContinuousAFAfterDelay(FOCUS_HOLD_MILLIS); 57430ffce08f511fbed4cf18daa743778b541583351Andy Huibers } catch (CameraAccessException ex) { 57530ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.e(TAG, "Could not execute preview request.", ex); 57630ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 57730ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 57830ffce08f511fbed4cf18daa743778b541583351Andy Huibers 57930ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 58030ffce08f511fbed4cf18daa743778b541583351Andy Huibers * Resume AF_MODE_CONTINUOUS_PICTURE after FOCUS_HOLD_MILLIS. 58130ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 58230ffce08f511fbed4cf18daa743778b541583351Andy Huibers private void resumeContinuousAFAfterDelay(int millis) { 58330ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCameraHandler.removeCallbacks(mReturnToContinuousAFRunnable); 58430ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCameraHandler.postDelayed(mReturnToContinuousAFRunnable, millis); 58530ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 58630ffce08f511fbed4cf18daa743778b541583351Andy Huibers 58730ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 58830ffce08f511fbed4cf18daa743778b541583351Andy Huibers * This method takes appropriate action if camera2 AF state changes. 58930ffce08f511fbed4cf18daa743778b541583351Andy Huibers * <ol> 59030ffce08f511fbed4cf18daa743778b541583351Andy Huibers * <li>Reports changes in camera2 AF state to OneCamera.FocusStateListener.</li> 59130ffce08f511fbed4cf18daa743778b541583351Andy Huibers * <li>Take picture after AF scan.</li> 59230ffce08f511fbed4cf18daa743778b541583351Andy Huibers * <li>TODO: Take picture after AE_PRECAPTURE sequence for flash.</li> 59330ffce08f511fbed4cf18daa743778b541583351Andy Huibers * </ol> 59430ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 59530ffce08f511fbed4cf18daa743778b541583351Andy Huibers private void autofocusStateChangeDispatcher(CaptureResult result) { 59630ffce08f511fbed4cf18daa743778b541583351Andy Huibers Integer nativeAFControlState = result.get(CaptureResult.CONTROL_AF_STATE); 59730ffce08f511fbed4cf18daa743778b541583351Andy Huibers Integer nativeAFControlMode = result.get(CaptureResult.CONTROL_AF_MODE); 59830ffce08f511fbed4cf18daa743778b541583351Andy Huibers Object tag = result.getRequest().getTag(); 59930ffce08f511fbed4cf18daa743778b541583351Andy Huibers 60030ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Convert to OneCamera mode and state. 60130ffce08f511fbed4cf18daa743778b541583351Andy Huibers AutoFocusMode resultAFMode = modeFromCamera2Mode(nativeAFControlMode); 60230ffce08f511fbed4cf18daa743778b541583351Andy Huibers AutoFocusState resultAFState = stateFromCamera2State(nativeAFControlState); 60330ffce08f511fbed4cf18daa743778b541583351Andy Huibers 60430ffce08f511fbed4cf18daa743778b541583351Andy Huibers boolean lensIsStopped = (resultAFState == AutoFocusState.STOPPED_FOCUSED || 60530ffce08f511fbed4cf18daa743778b541583351Andy Huibers resultAFState == AutoFocusState.STOPPED_UNFOCUSED); 60630ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (tag == RequestTag.PRESHOT_TRIGGERED_AF && lensIsStopped && 60730ffce08f511fbed4cf18daa743778b541583351Andy Huibers mTakePictureWhenLensStoppedAndAuto) { 60830ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Take the shot. 60930ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCameraHandler.post(mTakePictureRunnable); 61030ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Return to passive scanning. 61130ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCameraHandler.post(new Runnable() { 61230ffce08f511fbed4cf18daa743778b541583351Andy Huibers @Override 61330ffce08f511fbed4cf18daa743778b541583351Andy Huibers public void run() { 61430ffce08f511fbed4cf18daa743778b541583351Andy Huibers repeatingPreviewWithReadyListener(null); 61530ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 61630ffce08f511fbed4cf18daa743778b541583351Andy Huibers }); 61730ffce08f511fbed4cf18daa743778b541583351Andy Huibers mTakePictureWhenLensStoppedAndAuto = false; 61830ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 61930ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (mTakePictureWhenLensIsStopped && lensIsStopped) { 62030ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Take the shot. 62130ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCameraHandler.post(mTakePictureRunnable); 62230ffce08f511fbed4cf18daa743778b541583351Andy Huibers mTakePictureWhenLensIsStopped = false; 62330ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 62430ffce08f511fbed4cf18daa743778b541583351Andy Huibers 62530ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Report state change when mode or state has changed. 62630ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (resultAFState != mLastResultAFState || resultAFMode != mLastResultAFMode 62730ffce08f511fbed4cf18daa743778b541583351Andy Huibers && mFocusStateListener != null) { 62830ffce08f511fbed4cf18daa743778b541583351Andy Huibers mFocusStateListener.onFocusStatusUpdate(resultAFMode, resultAFState); 62930ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 63030ffce08f511fbed4cf18daa743778b541583351Andy Huibers mLastResultAFState = resultAFState; 63130ffce08f511fbed4cf18daa743778b541583351Andy Huibers mLastResultAFMode = resultAFMode; 63230ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 63330ffce08f511fbed4cf18daa743778b541583351Andy Huibers 63430ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 63530ffce08f511fbed4cf18daa743778b541583351Andy Huibers * Convert reported camera2 AF state to OneCamera AutoFocusState. 63630ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 63730ffce08f511fbed4cf18daa743778b541583351Andy Huibers private static AutoFocusState stateFromCamera2State(int state) { 63830ffce08f511fbed4cf18daa743778b541583351Andy Huibers switch (state) { 63930ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN: 64030ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN: 64130ffce08f511fbed4cf18daa743778b541583351Andy Huibers return AutoFocusState.SCANNING; 64230ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED: 64330ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED: 64430ffce08f511fbed4cf18daa743778b541583351Andy Huibers return AutoFocusState.STOPPED_FOCUSED; 64530ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: 64630ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: 64730ffce08f511fbed4cf18daa743778b541583351Andy Huibers return AutoFocusState.STOPPED_UNFOCUSED; 64830ffce08f511fbed4cf18daa743778b541583351Andy Huibers default: 64930ffce08f511fbed4cf18daa743778b541583351Andy Huibers return AutoFocusState.INACTIVE; 650f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 651f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 652f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 653f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 65430ffce08f511fbed4cf18daa743778b541583351Andy Huibers * Convert reported camera2 AF state to OneCamera AutoFocusMode. 65530ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 65630ffce08f511fbed4cf18daa743778b541583351Andy Huibers private static AutoFocusMode modeFromCamera2Mode(int mode) { 65730ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (mode == CaptureResult.CONTROL_AF_MODE_AUTO) { 65830ffce08f511fbed4cf18daa743778b541583351Andy Huibers return AutoFocusMode.AUTO; 65930ffce08f511fbed4cf18daa743778b541583351Andy Huibers } else { 66030ffce08f511fbed4cf18daa743778b541583351Andy Huibers // CONTROL_AF_MODE_CONTINUOUS_PICTURE is the other mode used. 66130ffce08f511fbed4cf18daa743778b541583351Andy Huibers return AutoFocusMode.CONTINUOUS_PICTURE; 66230ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 66330ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 66430ffce08f511fbed4cf18daa743778b541583351Andy Huibers 66530ffce08f511fbed4cf18daa743778b541583351Andy Huibers @Override 66630ffce08f511fbed4cf18daa743778b541583351Andy Huibers public void triggerAutoFocus() { 66730ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, "triggerAutoFocus()"); 66830ffce08f511fbed4cf18daa743778b541583351Andy Huibers repeatingPreviewWithAFTrigger(null, null, null); 66930ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 67030ffce08f511fbed4cf18daa743778b541583351Andy Huibers 67130ffce08f511fbed4cf18daa743778b541583351Andy Huibers @Override 67230ffce08f511fbed4cf18daa743778b541583351Andy Huibers public void triggerFocusAndMeterAtPoint(float nx, float ny) { 67330ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, "triggerFocusAndMeterAtPoint(" + nx + "," + ny + ")"); 67451163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling float points[] = new float[] { 67551163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling nx, ny 67651163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling }; 67730ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Make sure the points are in [0,1] range. 67830ffce08f511fbed4cf18daa743778b541583351Andy Huibers points[0] = CameraUtil.clamp(points[0], 0f, 1f); 67930ffce08f511fbed4cf18daa743778b541583351Andy Huibers points[1] = CameraUtil.clamp(points[1], 0f, 1f); 68030ffce08f511fbed4cf18daa743778b541583351Andy Huibers 68130ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Shrink points towards center if zoomed. 68230ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (mZoomValue > 1f) { 68330ffce08f511fbed4cf18daa743778b541583351Andy Huibers Matrix zoomMatrix = new Matrix(); 68430ffce08f511fbed4cf18daa743778b541583351Andy Huibers zoomMatrix.postScale(1f / mZoomValue, 1f / mZoomValue, 0.5f, 0.5f); 68530ffce08f511fbed4cf18daa743778b541583351Andy Huibers zoomMatrix.mapPoints(points); 68630ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 68730ffce08f511fbed4cf18daa743778b541583351Andy Huibers 68851163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling // TODO: Make this work when preview aspect ratio != sensor aspect 68951163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling // ratio. 69030ffce08f511fbed4cf18daa743778b541583351Andy Huibers Rect sensor = mCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); 69130ffce08f511fbed4cf18daa743778b541583351Andy Huibers int edge = (int) (METERING_REGION_EDGE * Math.max(sensor.width(), sensor.height())); 69251163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling // x0 and y0 in sensor coordinate system, rotated 90 degrees from 69351163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling // portrait. 69430ffce08f511fbed4cf18daa743778b541583351Andy Huibers int x0 = (int) (sensor.width() * points[1]); 69530ffce08f511fbed4cf18daa743778b541583351Andy Huibers int y0 = (int) (sensor.height() * (1f - points[0])); 69630ffce08f511fbed4cf18daa743778b541583351Andy Huibers int x1 = x0 + edge; 69730ffce08f511fbed4cf18daa743778b541583351Andy Huibers int y1 = y0 + edge; 69830ffce08f511fbed4cf18daa743778b541583351Andy Huibers 69930ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Make sure regions are inside the sensor area. 70030ffce08f511fbed4cf18daa743778b541583351Andy Huibers x0 = CameraUtil.clamp(x0, 0, sensor.width() - 1); 70130ffce08f511fbed4cf18daa743778b541583351Andy Huibers x1 = CameraUtil.clamp(x1, 0, sensor.width() - 1); 70230ffce08f511fbed4cf18daa743778b541583351Andy Huibers y0 = CameraUtil.clamp(y0, 0, sensor.height() - 1); 70330ffce08f511fbed4cf18daa743778b541583351Andy Huibers y1 = CameraUtil.clamp(y1, 0, sensor.height() - 1); 704967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall int wt = (int) ((1 - METERING_REGION_WEIGHT) * MeteringRectangle.METERING_WEIGHT_MIN 705967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall + METERING_REGION_WEIGHT * MeteringRectangle.METERING_WEIGHT_MAX); 70630ffce08f511fbed4cf18daa743778b541583351Andy Huibers 70730ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, "sensor 3A @ x0=" + x0 + " y0=" + y0 + " dx=" + (x1 - x0) + " dy=" + (y1 - y0)); 70851163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling MeteringRectangle[] regions = new MeteringRectangle[] { 70951163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling new MeteringRectangle(x0, y0, x1 - x0, y1 - y0, wt) 71051163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling }; 71130ffce08f511fbed4cf18daa743778b541583351Andy Huibers repeatingPreviewWithAFTrigger(regions, regions, null); 71230ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 71330ffce08f511fbed4cf18daa743778b541583351Andy Huibers 71430ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 715f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Calculate the aspect ratio of the full size capture on this device. 716f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 717f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param characteristics the characteristics of the camera device. 718f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @return The aspect ration, in terms of width/height of the full capture 719f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * size. 720f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 721f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private static double calculateFullSizeAspectRatio(CameraCharacteristics characteristics) { 722f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling Rect activeArraySize = 723f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); 724f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling return (double) activeArraySize.width() / activeArraySize.height(); 725f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 726f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 727f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 728f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Given an image reader, extracts the JPEG image bytes and then closes the 729f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * reader. 730f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 731f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param reader the reader to read the JPEG data from. 732f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @return The bytes of the JPEG image. Newly allocated. 733f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 734f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private static byte[] acquireJpegBytesAndClose(ImageReader reader) { 735f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling Image img = reader.acquireLatestImage(); 736967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 737967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall ByteBuffer buffer; 738967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 739967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall if (img.getFormat() == ImageFormat.JPEG) { 740967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall Image.Plane plane0 = img.getPlanes()[0]; 741967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall buffer = plane0.getBuffer(); 742967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall } else if (img.getFormat() == ImageFormat.YUV_420_888) { 743967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall buffer = ByteBuffer.allocateDirect(img.getWidth() * img.getHeight() * 3); 744967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 745967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall Log.v(TAG, "Compressing JPEG with software encoder."); 746967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall int numBytes = JpegUtilNative.compressJpegFromYUV420Image(img, buffer, JPEG_QUALITY); 747967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 748967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall if (numBytes < 0) { 749967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall throw new RuntimeException("Error compressing jpeg."); 750967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall } 751967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 752967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall buffer.limit(numBytes); 753967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall } else { 754967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall throw new RuntimeException("Unsupported image format."); 755967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall } 756f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 757f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling byte[] imageBytes = new byte[buffer.remaining()]; 758f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling buffer.get(imageBytes); 759f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling buffer.rewind(); 760f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling img.close(); 761f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling return imageBytes; 762f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 763f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 764f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 765f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Given the device orientation, this returns the required JPEG rotation for 766f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * this camera. 767f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 768f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param deviceOrientationDegrees the device orientation in degrees. 769f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @return The JPEG orientation in degrees. 770f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 771f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private int getJpegRotation(int deviceOrientationDegrees) { 772f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling if (deviceOrientationDegrees == OrientationEventListener.ORIENTATION_UNKNOWN) { 773f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling return 0; 774f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 775f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling int facing = mCharacteristics.get(CameraCharacteristics.LENS_FACING); 776f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling int sensorOrientation = mCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); 777f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling if (facing == CameraMetadata.LENS_FACING_FRONT) { 778f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling return (sensorOrientation - deviceOrientationDegrees + 360) % 360; 779f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } else { 780f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling return (sensorOrientation + deviceOrientationDegrees) % 360; 781f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 782f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 7830cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling 7840cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling private void applyFlashMode(Flash flashMode, CaptureRequest.Builder requestBuilder) { 7850cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling switch (flashMode) { 7860cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling case ON: 7870cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling Log.d(TAG, "Flash mode ON"); 7880cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, 7890cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH); 7900cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE); 7910cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling break; 7920cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling case OFF: 7930cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling Log.d(TAG, "Flash mode OFF"); 7940cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, 7950cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling CaptureRequest.CONTROL_AE_MODE_ON); 7960cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF); 7970cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling break; 7980cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling case AUTO: 7990cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling default: 8000cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling Log.d(TAG, "Flash mode AUTO"); 8010cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, 8020cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); 8030cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling break; 8040cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling } 8050cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling } 80630ffce08f511fbed4cf18daa743778b541583351Andy Huibers 80730ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 80830ffce08f511fbed4cf18daa743778b541583351Andy Huibers * Utility function: converts CaptureResult.CONTROL_AF_STATE* to String. 80930ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 81030ffce08f511fbed4cf18daa743778b541583351Andy Huibers private static String camera2ControlAFStateDesc(int aFState) { 81130ffce08f511fbed4cf18daa743778b541583351Andy Huibers switch (aFState) { 81230ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_INACTIVE: 81330ffce08f511fbed4cf18daa743778b541583351Andy Huibers return "inactive"; 81430ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN: 81530ffce08f511fbed4cf18daa743778b541583351Andy Huibers return "passive_scan"; 81630ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED: 81730ffce08f511fbed4cf18daa743778b541583351Andy Huibers return "passive_focused"; 81830ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN: 81930ffce08f511fbed4cf18daa743778b541583351Andy Huibers return "active_scan"; 82030ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED: 82130ffce08f511fbed4cf18daa743778b541583351Andy Huibers return "focus_locked"; 82230ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: 82330ffce08f511fbed4cf18daa743778b541583351Andy Huibers return "not_focus_locked"; 82430ffce08f511fbed4cf18daa743778b541583351Andy Huibers case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: 82530ffce08f511fbed4cf18daa743778b541583351Andy Huibers return "passive_unfocused"; 82630ffce08f511fbed4cf18daa743778b541583351Andy Huibers default: 82730ffce08f511fbed4cf18daa743778b541583351Andy Huibers return "unknown"; 82830ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 82930ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 83030ffce08f511fbed4cf18daa743778b541583351Andy Huibers 83130ffce08f511fbed4cf18daa743778b541583351Andy Huibers private void logExtraFocusInfo(CaptureResult result) { 83230ffce08f511fbed4cf18daa743778b541583351Andy Huibers Object tag = result.getRequest().getTag(); 83330ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Nexus 5 has a bug where CONTROL_AF_STATE is missing sometimes. 83430ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (result.get(CaptureResult.CONTROL_AF_STATE) == null) { 83551163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling // throw new 83651163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling // IllegalStateException("CaptureResult missing CONTROL_AF_STATE."); 83730ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.e(TAG, "\n!!!! TotalCaptureResult missing CONTROL_AF_STATE. !!!!\n "); 83830ffce08f511fbed4cf18daa743778b541583351Andy Huibers return; 83930ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 84030ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, "camera2 AF state: " + camera2ControlAFStateDesc(result. 84130ffce08f511fbed4cf18daa743778b541583351Andy Huibers get(CaptureResult.CONTROL_AF_STATE)) + 84230ffce08f511fbed4cf18daa743778b541583351Andy Huibers (tag == null ? "" : (" tag: " + tag))); 84330ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (result.get(CaptureResult.LENS_FOCUS_DISTANCE) != null) { 84430ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, " lens @ " + result.get(CaptureResult.LENS_FOCUS_DISTANCE)); 84530ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 84630ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 847f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling} 848