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