1512001df0211fa8999593717a0f186457a5a9cefPuneet Lall/*
2512001df0211fa8999593717a0f186457a5a9cefPuneet Lall * Copyright (C) 2014 The Android Open Source Project
3512001df0211fa8999593717a0f186457a5a9cefPuneet Lall *
40ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
50ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall * in compliance with the License. You may obtain a copy of the License at
6512001df0211fa8999593717a0f186457a5a9cefPuneet Lall *
70ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall * http://www.apache.org/licenses/LICENSE-2.0
8512001df0211fa8999593717a0f186457a5a9cefPuneet Lall *
90ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall * Unless required by applicable law or agreed to in writing, software distributed under the License
100ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
110ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall * or implied. See the License for the specific language governing permissions and limitations under
120ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall * the License.
13512001df0211fa8999593717a0f186457a5a9cefPuneet Lall */
14512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
15512001df0211fa8999593717a0f186457a5a9cefPuneet Lallpackage com.android.camera.one.v2;
16512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
17512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.annotation.TargetApi;
18512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.content.Context;
19512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.graphics.ImageFormat;
20512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.graphics.Rect;
21512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.hardware.camera2.CameraAccessException;
22512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.hardware.camera2.CameraCaptureSession;
23512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.hardware.camera2.CameraCharacteristics;
24512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.hardware.camera2.CameraDevice;
25512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.hardware.camera2.CameraMetadata;
26512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.hardware.camera2.CaptureRequest;
27512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.hardware.camera2.CaptureResult;
28580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lallimport android.hardware.camera2.CaptureResult.Key;
29512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.hardware.camera2.TotalCaptureResult;
30512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.hardware.camera2.params.MeteringRectangle;
31512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.hardware.camera2.params.StreamConfigurationMap;
32dfef32425e6184d5721bb7af9db823ec46bc2b4fSascha Haeberlingimport android.location.Location;
33512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.media.CameraProfile;
34512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.media.Image;
35512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.media.ImageReader;
3617d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibersimport android.media.MediaActionSound;
37512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.net.Uri;
38512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.os.Build;
39512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.os.Handler;
40512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.os.HandlerThread;
41580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lallimport android.os.SystemClock;
42512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.support.v4.util.Pools;
43512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport android.view.Surface;
44512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
45512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.CaptureModuleUtil;
46512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.debug.Log;
47512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.debug.Log.Tag;
48512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.exif.ExifInterface;
49512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.exif.ExifTag;
50512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.exif.Rational;
51512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.one.AbstractOneCamera;
529ceed0d5535e8453f8b5f77959134760dac01ec5Puneet Lallimport com.android.camera.one.CameraDirectionProvider;
53512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.one.OneCamera;
54512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.one.OneCamera.PhotoCaptureParameters.Flash;
55b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibersimport com.android.camera.one.Settings3A;
56512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.one.v2.ImageCaptureManager.ImageCaptureListener;
57580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lallimport com.android.camera.one.v2.ImageCaptureManager.MetadataChangeListener;
585ca7d2642881f3cf06adb2532e0d5950524a34f4Puneet Lallimport com.android.camera.one.v2.camera2proxy.AndroidCaptureResultProxy;
5930ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Linimport com.android.camera.one.v2.camera2proxy.AndroidImageProxy;
60f6031c016d916db9789026dc0a6c559d8163a088Spike Spragueimport com.android.camera.one.v2.camera2proxy.CaptureResultProxy;
61f6031c016d916db9789026dc0a6c559d8163a088Spike Spragueimport com.android.camera.processing.imagebackend.TaskImageContainer;
62512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.session.CaptureSession;
63aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohdeimport com.android.camera.ui.focus.LensRangeCalculator;
64aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohdeimport com.android.camera.ui.motion.LinearScale;
65512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.util.CameraUtil;
66f6031c016d916db9789026dc0a6c559d8163a088Spike Spragueimport com.android.camera.util.ExifUtil;
67512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.util.JpegUtilNative;
6882d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekharimport com.android.camera.util.ListenerCombiner;
69512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport com.android.camera.util.Size;
70f6031c016d916db9789026dc0a6c559d8163a088Spike Spragueimport com.google.common.base.Optional;
7137036186326fb68c27063f97305405d3667a5eb3Sascha Haeberlingimport com.google.common.util.concurrent.FutureCallback;
7237036186326fb68c27063f97305405d3667a5eb3Sascha Haeberlingimport com.google.common.util.concurrent.Futures;
7337036186326fb68c27063f97305405d3667a5eb3Sascha Haeberlingimport com.google.common.util.concurrent.ListenableFuture;
74512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
75512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport java.nio.ByteBuffer;
760ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lallimport java.security.InvalidParameterException;
77512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport java.util.ArrayList;
78863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lallimport java.util.Collections;
79863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lallimport java.util.HashSet;
80512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport java.util.List;
81863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lallimport java.util.Set;
82512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport java.util.concurrent.LinkedBlockingQueue;
83512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport java.util.concurrent.ThreadPoolExecutor;
84512001df0211fa8999593717a0f186457a5a9cefPuneet Lallimport java.util.concurrent.TimeUnit;
85512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
86512001df0211fa8999593717a0f186457a5a9cefPuneet Lall/**
87512001df0211fa8999593717a0f186457a5a9cefPuneet Lall * {@link OneCamera} implementation directly on top of the Camera2 API with zero
88512001df0211fa8999593717a0f186457a5a9cefPuneet Lall * shutter lag.<br>
89512001df0211fa8999593717a0f186457a5a9cefPuneet Lall * TODO: Determine what the maximum number of full YUV capture frames is.
90512001df0211fa8999593717a0f186457a5a9cefPuneet Lall */
9130ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin@TargetApi(Build.VERSION_CODES.LOLLIPOP)
92386c5b885b99f67f9c0a7380f4be153f28333089Puneet Lall@Deprecated
93512001df0211fa8999593717a0f186457a5a9cefPuneet Lallpublic class OneCameraZslImpl extends AbstractOneCamera {
94512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private static final Tag TAG = new Tag("OneCameraZslImpl2");
95512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
96512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** Default JPEG encoding quality. */
970ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall    private static final int JPEG_QUALITY =
980ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            CameraProfile.getJpegEncodingQualityParameter(CameraProfile.QUALITY_HIGH);
99512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
10082d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar     * The maximum number of images to store in the full-size ZSL ring buffer.
101512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * <br>
102512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * TODO: Determine this number dynamically based on available memory and the
103512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * size of frames.
104512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
10582d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar    private static final int MAX_CAPTURE_IMAGES = 12;
106512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
107512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * True if zero-shutter-lag images should be captured. Some devices produce
108512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * lower-quality images for the high-frequency stream, so we may wish to
109512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * disable ZSL in that case.
110512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
111512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private static final boolean ZSL_ENABLED = true;
112512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
113512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
114580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     * Tags which may be used in CaptureRequests.
115580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     */
116580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private static enum RequestTag {
117580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        /**
118580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall         * Indicates that the request was explicitly sent for a single
119580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall         * high-quality still capture. Unlike other requests, such as the
120580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall         * repeating (ZSL) stream and AF/AE triggers, requests with this tag
121580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall         * should always be saved.
122580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall         */
123580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        EXPLICIT_CAPTURE
124182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall    }
125580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
126580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    /**
127512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * Set to ImageFormat.JPEG to use the hardware encoder, or
128512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * ImageFormat.YUV_420_888 to use the software encoder. No other image
129512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * formats are supported.
130512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
131512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private static final int sCaptureImageFormat = ImageFormat.YUV_420_888;
132580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    /**
133182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall     * Token for callbacks posted to {@link #mCameraHandler} to resume
134182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall     * continuous AF.
135580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     */
136580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private static final String FOCUS_RESUME_CALLBACK_TOKEN = "RESUME_CONTINUOUS_AF";
1379cefdd495332719d987ffb942742ec602793d8d4Jiawen Chen
138512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** Zero weight 3A region, to reset regions per API. */
1399cefdd495332719d987ffb942742ec602793d8d4Jiawen Chen    /*package*/ MeteringRectangle[] ZERO_WEIGHT_3A_REGION = AutoFocusHelper.getZeroWeightRegion();
140512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
141580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    /**
142580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     * Thread on which high-priority camera operations, such as grabbing preview
143580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     * frames for the viewfinder, are running.
144580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     */
145512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private final HandlerThread mCameraThread;
146512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** Handler of the {@link #mCameraThread}. */
147512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private final Handler mCameraHandler;
148512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
149580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    /** Thread on which low-priority camera listeners are running. */
150580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private final HandlerThread mCameraListenerThread;
151580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private final Handler mCameraListenerHandler;
152580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
153512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** The characteristics of this camera. */
154512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private final CameraCharacteristics mCharacteristics;
155aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohde    /** Converts focus distance units into ratio values */
156aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohde    private final LinearScale mLensRange;
157512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** The underlying Camera2 API camera device. */
158512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private final CameraDevice mDevice;
1599ceed0d5535e8453f8b5f77959134760dac01ec5Puneet Lall    private final CameraDirectionProvider mDirection;
160512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
161512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
162512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * The aspect ratio (width/height) of the full resolution for this camera.
163512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * Usually the native aspect ratio of this camera.
164512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
1659cefdd495332719d987ffb942742ec602793d8d4Jiawen Chen    private final float mFullSizeAspectRatio;
166512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** The Camera2 API capture session currently active. */
167512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private CameraCaptureSession mCaptureSession;
168512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** The surface onto which to render the preview. */
169512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private Surface mPreviewSurface;
170512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** Whether closing of this device has been requested. */
171512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private volatile boolean mIsClosed = false;
172512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
173512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** Receives the normal captured images. */
174512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private final ImageReader mCaptureImageReader;
175512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
176512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
177512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * Maintains a buffer of images and their associated {@link CaptureResult}s.
178512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
179512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private ImageCaptureManager mCaptureManager;
180512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
181512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
182863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall     * The sensor timestamps (which may not be relative to the system time) of
183863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall     * the most recently captured images.
184512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
185863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall    private final Set<Long> mCapturedImageTimestamps = Collections.synchronizedSet(
186863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall            new HashSet<Long>());
187512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
188512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** Thread pool for performing slow jpeg encoding and saving tasks. */
189512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private final ThreadPoolExecutor mImageSaverThreadPool;
190512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
191512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** Pool of native byte buffers on which to store jpeg-encoded images. */
1920ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall    private final Pools.SynchronizedPool<ByteBuffer> mJpegByteBufferPool =
1930ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            new Pools.SynchronizedPool<ByteBuffer>(64);
194512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
195512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** Current zoom value. 1.0 is no zoom. */
196512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private float mZoomValue = 1f;
197512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** Current crop region: set from mZoomValue. */
198512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private Rect mCropRegion;
199512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /** Current AE, AF, and AWB regions */
200b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers    private MeteringRectangle[] mAFRegions = ZERO_WEIGHT_3A_REGION;
201b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers    private MeteringRectangle[] mAERegions = ZERO_WEIGHT_3A_REGION;
202512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
20317d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers    private MediaActionSound mMediaActionSound = new MediaActionSound();
20417d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers
205512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
206142b5bf5e10db858c2d2e69fd93d6565ba51363bPuneet Lall     * Ready state (typically displayed by the UI shutter-button) depends on two
207142b5bf5e10db858c2d2e69fd93d6565ba51363bPuneet Lall     * things:<br>
208182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall     * <ol>
209182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall     * <li>{@link #mCaptureManager} must be ready.</li>
210182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall     * <li>We must not be in the process of capturing a single, high-quality,
211182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall     * image.</li>
212182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall     * </ol>
213c2387dc7fa82fafb2dd2eac0e7280ff71dece0f4Puneet Lall     * See {@link ListenerCombiner} and {@link #mReadyStateManager} for
214142b5bf5e10db858c2d2e69fd93d6565ba51363bPuneet Lall     * details of how this is managed.
215182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall     */
21668c25ac5373126670cb6c2324e40537bb47e72d9Puneet Lall    private static enum ReadyStateRequirement {
2170ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        CAPTURE_MANAGER_READY, CAPTURE_NOT_IN_PROGRESS
21868c25ac5373126670cb6c2324e40537bb47e72d9Puneet Lall    }
21968c25ac5373126670cb6c2324e40537bb47e72d9Puneet Lall
22068c25ac5373126670cb6c2324e40537bb47e72d9Puneet Lall    /**
22168c25ac5373126670cb6c2324e40537bb47e72d9Puneet Lall     * Handles the thread-safe logic of dispatching whenever the logical AND of
22268c25ac5373126670cb6c2324e40537bb47e72d9Puneet Lall     * these constraints changes.
22368c25ac5373126670cb6c2324e40537bb47e72d9Puneet Lall     */
224c2387dc7fa82fafb2dd2eac0e7280ff71dece0f4Puneet Lall    private final ListenerCombiner<ReadyStateRequirement>
225c2387dc7fa82fafb2dd2eac0e7280ff71dece0f4Puneet Lall            mReadyStateManager = new ListenerCombiner<ReadyStateRequirement>(
226c2387dc7fa82fafb2dd2eac0e7280ff71dece0f4Puneet Lall                    ReadyStateRequirement.class, new ListenerCombiner.StateChangeListener() {
227142b5bf5e10db858c2d2e69fd93d6565ba51363bPuneet Lall                            @Override
228c2387dc7fa82fafb2dd2eac0e7280ff71dece0f4Puneet Lall                        public void onStateChange(boolean state) {
229142b5bf5e10db858c2d2e69fd93d6565ba51363bPuneet Lall                            broadcastReadyState(state);
230142b5bf5e10db858c2d2e69fd93d6565ba51363bPuneet Lall                        }
231142b5bf5e10db858c2d2e69fd93d6565ba51363bPuneet Lall                    });
232182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall
233182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall    /**
234580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     * An {@link ImageCaptureListener} which will compress and save an image to
235580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     * disk.
236580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     */
237580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private class ImageCaptureTask implements ImageCaptureListener {
238580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        private final PhotoCaptureParameters mParams;
239580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        private final CaptureSession mSession;
240580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
2410ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        public ImageCaptureTask(PhotoCaptureParameters parameters, CaptureSession session) {
242580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            mParams = parameters;
243580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            mSession = session;
244580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        }
245580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
246580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        @Override
2470ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        public void onImageCaptured(Image image, TotalCaptureResult captureResult) {
248580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            long timestamp = captureResult.get(CaptureResult.SENSOR_TIMESTAMP);
249580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
250863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall            // We should only capture the image if it hasn't been captured
251863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall            // before. Synchronization is necessary since
252863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall            // mCapturedImageTimestamps is read & modified elsewhere.
253863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall            synchronized (mCapturedImageTimestamps) {
254863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                if (!mCapturedImageTimestamps.contains(timestamp)) {
255863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                    mCapturedImageTimestamps.add(timestamp);
256580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                } else {
257580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // There was a more recent (or identical) image which has
258580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // begun being saved, so abort.
259580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    return;
260580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                }
261863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall
262863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                // Clear out old timestamps from the set.
263863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                // We must keep old timestamps in the set a little longer (a
264863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                // factor of 2 seems adequate) to ensure they are cleared out of
265863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                // the ring buffer before their timestamp is removed from the
266863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                // set.
267863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                long maxTimestamps = MAX_CAPTURE_IMAGES * 2;
268863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                if (mCapturedImageTimestamps.size() > maxTimestamps) {
269863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                    ArrayList<Long> timestamps = new ArrayList<Long>(mCapturedImageTimestamps);
270863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                    Collections.sort(timestamps);
271863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                    for (int i = 0; i < timestamps.size()
272863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                            && mCapturedImageTimestamps.size() > maxTimestamps; i++) {
273863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                        mCapturedImageTimestamps.remove(timestamps.get(i));
274863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                    }
275863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                }
276580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            }
277580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
2780ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            mReadyStateManager.setInput(ReadyStateRequirement.CAPTURE_NOT_IN_PROGRESS, true);
279182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall
280f6031c016d916db9789026dc0a6c559d8163a088Spike Sprague            savePicture(image, mParams, mSession, captureResult);
281580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            mParams.callback.onPictureTaken(mSession);
282580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            Log.v(TAG, "Image saved.  Frame number = " + captureResult.getFrameNumber());
283580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        }
284580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    }
285580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
286580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    /**
287512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * Instantiates a new camera based on Camera 2 API.
288512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     *
289512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * @param device The underlying Camera 2 device.
290512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * @param characteristics The device's characteristics.
291512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * @param pictureSize the size of the final image to be taken.
292512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
293512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    OneCameraZslImpl(CameraDevice device, CameraCharacteristics characteristics, Size pictureSize) {
294580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        Log.v(TAG, "Creating new OneCameraZslImpl");
295580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
296512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mDevice = device;
297512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mCharacteristics = characteristics;
298aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohde        mLensRange = LensRangeCalculator
299aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohde              .getDiopterToRatioCalculator(characteristics);
3009ceed0d5535e8453f8b5f77959134760dac01ec5Puneet Lall        mDirection = new CameraDirectionProvider(mCharacteristics);
301512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mFullSizeAspectRatio = calculateFullSizeAspectRatio(characteristics);
302512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
303512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mCameraThread = new HandlerThread("OneCamera2");
304512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        // If this thread stalls, it will delay viewfinder frames.
305512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mCameraThread.setPriority(Thread.MAX_PRIORITY);
306512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mCameraThread.start();
307512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mCameraHandler = new Handler(mCameraThread.getLooper());
308512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
309580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        mCameraListenerThread = new HandlerThread("OneCamera2-Listener");
310580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        mCameraListenerThread.start();
311580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        mCameraListenerHandler = new Handler(mCameraListenerThread.getLooper());
312512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
313512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        // TODO: Encoding on multiple cores results in preview jank due to
314512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        // excessive GC.
315512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        int numEncodingCores = CameraUtil.getNumCpuCores();
316512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mImageSaverThreadPool = new ThreadPoolExecutor(numEncodingCores, numEncodingCores, 10,
317512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
318512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
3190ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        mCaptureManager =
3200ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                new ImageCaptureManager(MAX_CAPTURE_IMAGES, mCameraListenerHandler,
3210ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                        mImageSaverThreadPool);
322580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        mCaptureManager.setCaptureReadyListener(new ImageCaptureManager.CaptureReadyListener() {
323512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                @Override
324512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            public void onReadyStateChange(boolean capturePossible) {
32568c25ac5373126670cb6c2324e40537bb47e72d9Puneet Lall                mReadyStateManager.setInput(ReadyStateRequirement.CAPTURE_MANAGER_READY,
326182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall                        capturePossible);
327182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall            }
328182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall        });
329182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall
330580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // Listen for changes to auto focus state and dispatch to
331580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // mFocusStateListener.
332580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        mCaptureManager.addMetadataChangeListener(CaptureResult.CONTROL_AF_STATE,
333580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                new ImageCaptureManager.MetadataChangeListener() {
334580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                @Override
335580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    public void onImageMetadataChange(Key<?> key, Object oldValue, Object newValue,
336580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                            CaptureResult result) {
3370ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                        FocusStateListener listener = mFocusStateListener;
3380ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                        if (listener != null) {
3390ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                            listener.onFocusStatusUpdate(
3400ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                                    AutoFocusHelper.stateFromCamera2State(
3414a748623618f2bae149c8cf385046666c717a7a9Andy Huibers                                            result.get(CaptureResult.CONTROL_AF_STATE)),
342ca3c564536f154b83e380e37382bc7b9f6049302Andy Huibers                                result.getFrameNumber());
3434a748623618f2bae149c8cf385046666c717a7a9Andy Huibers                        }
344580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    }
345580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                });
346580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
347580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // Allocate the image reader to store all images received from the
348580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // camera.
34980f44448e13b5d6d33f4aad63448d7b39b6dda0fPuneet Lall        if (pictureSize == null) {
3504d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall            // TODO The default should be selected by the caller, and
3514d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall            // pictureSize should never be null.
3524d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall            pictureSize = getDefaultPictureSize();
35380f44448e13b5d6d33f4aad63448d7b39b6dda0fPuneet Lall        }
354580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        mCaptureImageReader = ImageReader.newInstance(pictureSize.getWidth(),
355580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                pictureSize.getHeight(),
356580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                sCaptureImageFormat, MAX_CAPTURE_IMAGES);
357512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
358512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mCaptureImageReader.setOnImageAvailableListener(mCaptureManager, mCameraHandler);
35917d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers        mMediaActionSound.load(MediaActionSound.SHUTTER_CLICK);
360512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
361512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
362987ee64612e2510004fdf08536746c87234d01c1Paul Rohde    @Override
363987ee64612e2510004fdf08536746c87234d01c1Paul Rohde    public void setFocusDistanceListener(FocusDistanceListener focusDistanceListener) {
364987ee64612e2510004fdf08536746c87234d01c1Paul Rohde        if(mFocusDistanceListener == null) {
365987ee64612e2510004fdf08536746c87234d01c1Paul Rohde            mCaptureManager.addMetadataChangeListener(CaptureResult.LENS_FOCUS_DISTANCE,
366987ee64612e2510004fdf08536746c87234d01c1Paul Rohde                  new ImageCaptureManager.MetadataChangeListener() {
367987ee64612e2510004fdf08536746c87234d01c1Paul Rohde                      @Override
368987ee64612e2510004fdf08536746c87234d01c1Paul Rohde                      public void onImageMetadataChange(Key<?> key, Object oldValue,
369987ee64612e2510004fdf08536746c87234d01c1Paul Rohde                            Object newValue,
370987ee64612e2510004fdf08536746c87234d01c1Paul Rohde                            CaptureResult result) {
371987ee64612e2510004fdf08536746c87234d01c1Paul Rohde                          Integer state = result.get(CaptureResult.LENS_STATE);
372aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohde
373aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohde                          // Forward changes if we have a new value and the camera
374aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohde                          // A) Doesn't support lens state or B) lens state is
375aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohde                          // reported and it is reported as moving.
376aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohde                          if (newValue != null &&
377aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohde                                (state == null || state == CameraMetadata.LENS_STATE_MOVING)) {
378aca904e29aea542b6e6a4fcc837759a57a270a49Paul Rohde                              mFocusDistanceListener.onFocusDistance((float) newValue, mLensRange);
379987ee64612e2510004fdf08536746c87234d01c1Paul Rohde                          }
380987ee64612e2510004fdf08536746c87234d01c1Paul Rohde                      }
381987ee64612e2510004fdf08536746c87234d01c1Paul Rohde                  });
382987ee64612e2510004fdf08536746c87234d01c1Paul Rohde        }
383987ee64612e2510004fdf08536746c87234d01c1Paul Rohde        mFocusDistanceListener = focusDistanceListener;
384987ee64612e2510004fdf08536746c87234d01c1Paul Rohde    }
385987ee64612e2510004fdf08536746c87234d01c1Paul Rohde
386512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
3874d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall     * @return The largest supported picture size.
3884d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall     */
3894d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall    public Size getDefaultPictureSize() {
3900ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        StreamConfigurationMap configs =
3910ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                mCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
3924d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall        android.util.Size[] supportedSizes = configs.getOutputSizes(sCaptureImageFormat);
3934d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall
3944d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall        // Find the largest supported size.
3954d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall        android.util.Size largestSupportedSize = supportedSizes[0];
3960ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        long largestSupportedSizePixels =
3970ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                largestSupportedSize.getWidth() * largestSupportedSize.getHeight();
3984d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall        for (int i = 0; i < supportedSizes.length; i++) {
3994d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall            long numPixels = supportedSizes[i].getWidth() * supportedSizes[i].getHeight();
4004d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall            if (numPixels > largestSupportedSizePixels) {
4014d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall                largestSupportedSize = supportedSizes[i];
4024d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall                largestSupportedSizePixels = numPixels;
4034d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall            }
4044d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall        }
4054d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall
4060ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        return new Size(largestSupportedSize.getWidth(), largestSupportedSize.getHeight());
4074d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall    }
4084d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall
40917d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers    private void onShutterInvokeUI(final PhotoCaptureParameters params) {
41017d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers        // Tell CaptureModule shutter has occurred so it can flash the screen.
41117d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers        params.callback.onQuickExpose();
41217d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers        // Play shutter click sound.
41317d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers        mMediaActionSound.play(MediaActionSound.SHUTTER_CLICK);
41417d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers    }
41517d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers
4164d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall    /**
417512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * Take a picture.
418512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
419512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    @Override
420512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    public void takePicture(final PhotoCaptureParameters params, final CaptureSession session) {
4210ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        mReadyStateManager.setInput(ReadyStateRequirement.CAPTURE_NOT_IN_PROGRESS, false);
422182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall
423512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        boolean useZSL = ZSL_ENABLED;
424512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
425580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // We will only capture images from the zsl ring-buffer which satisfy
426580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // this constraint.
4270ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        ArrayList<ImageCaptureManager.CapturedImageConstraint> zslConstraints =
4280ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                new ArrayList<ImageCaptureManager.CapturedImageConstraint>();
429580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        zslConstraints.add(new ImageCaptureManager.CapturedImageConstraint() {
430580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                @Override
431580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            public boolean satisfiesConstraint(TotalCaptureResult captureResult) {
432580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                Long timestamp = captureResult.get(CaptureResult.SENSOR_TIMESTAMP);
433580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                Integer lensState = captureResult.get(CaptureResult.LENS_STATE);
434580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                Integer flashState = captureResult.get(CaptureResult.FLASH_STATE);
435580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                Integer flashMode = captureResult.get(CaptureResult.FLASH_MODE);
436580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                Integer aeState = captureResult.get(CaptureResult.CONTROL_AE_STATE);
437580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE);
438580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                Integer awbState = captureResult.get(CaptureResult.CONTROL_AWB_STATE);
439580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
440bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                if (lensState == null) {
441bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                    lensState = CaptureResult.LENS_STATE_STATIONARY;
442bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                }
443bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                if (flashState == null) {
444bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                    flashState = CaptureResult.FLASH_STATE_UNAVAILABLE;
445bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                }
446bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                if (flashMode == null) {
447bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                    flashMode = CaptureResult.FLASH_MODE_OFF;
448bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                }
449bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                if (aeState == null) {
450bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                    aeState = CaptureResult.CONTROL_AE_STATE_INACTIVE;
451bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                }
452bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                if (afState == null) {
453bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                    afState = CaptureResult.CONTROL_AF_STATE_INACTIVE;
454bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                }
455bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                if (awbState == null) {
456bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                    awbState = CaptureResult.CONTROL_AWB_STATE_INACTIVE;
457bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall                }
458bbd6516a5aedf3173954ee0ece85a45ebb9d73aaPuneet Lall
459863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                synchronized (mCapturedImageTimestamps) {
460863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                    if (mCapturedImageTimestamps.contains(timestamp)) {
461863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                        // Don't save frames which we've already saved.
462863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                        return false;
463863a5abf144db5c50c459d1c2f66543598aa26fcPuneet Lall                    }
464580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                }
465512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
466580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                if (lensState == CaptureResult.LENS_STATE_MOVING) {
467580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // If we know the lens was moving, don't use this image.
468580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    return false;
469580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                }
470512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
471580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                if (aeState == CaptureResult.CONTROL_AE_STATE_SEARCHING
472580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                        || aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
473580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    return false;
474580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                }
475512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
476580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                if (afState == CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN
477580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                        || afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN) {
478580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    return false;
479580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                }
480512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
481580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                if (awbState == CaptureResult.CONTROL_AWB_STATE_SEARCHING) {
482580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    return false;
483512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                }
484512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
485580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                return true;
486580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            }
487580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        });
488580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // This constraint lets us capture images which have been explicitly
489580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // requested. See {@link RequestTag.EXPLICIT_CAPTURE}.
4900ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        ArrayList<ImageCaptureManager.CapturedImageConstraint> singleCaptureConstraint =
4910ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                new ArrayList<ImageCaptureManager.CapturedImageConstraint>();
492580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        singleCaptureConstraint.add(new ImageCaptureManager.CapturedImageConstraint() {
493580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                @Override
494580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            public boolean satisfiesConstraint(TotalCaptureResult captureResult) {
495580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                Object tag = captureResult.getRequest().getTag();
496580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                return tag == RequestTag.EXPLICIT_CAPTURE;
497580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            }
498580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        });
499512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
500580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // If we can use ZSL, try to save a previously-captured frame, if an
501580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // acceptable one exists in the buffer.
502580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        if (useZSL) {
503580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            boolean capturedPreviousFrame = mCaptureManager.tryCaptureExistingImage(
504580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    new ImageCaptureTask(params, session), zslConstraints);
505512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            if (capturedPreviousFrame) {
506512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                Log.v(TAG, "Saving previous frame");
50717d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers                onShutterInvokeUI(params);
508512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            } else {
509580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                Log.v(TAG, "No good image Available.  Capturing next available good image.");
510512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                // If there was no good frame available in the ring buffer
511512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                // already, capture the next good image.
512580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                // TODO Disable the shutter button until this image is captured.
513580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
514386c5b885b99f67f9c0a7380f4be153f28333089Puneet Lall                Flash flashMode = Flash.OFF;
515386c5b885b99f67f9c0a7380f4be153f28333089Puneet Lall
516386c5b885b99f67f9c0a7380f4be153f28333089Puneet Lall                if (flashMode == Flash.ON || flashMode == Flash.AUTO) {
517580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // We must issue a request for a single capture using the
518580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // flash, including an AE precapture trigger.
519580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
520580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // The following sets up a sequence of events which will
521580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // occur in reverse order to the associated method
522580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // calls:
523580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // 1. Send a request to trigger the Auto Exposure Precapture
524580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // 2. Wait for the AE_STATE to leave the PRECAPTURE state,
525580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // and then send a request for a single image, with the
526580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // appropriate flash settings.
527580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // 3. Capture the next appropriate image, which should be
528580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // the one we requested in (2).
529580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
530580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    mCaptureManager.captureNextImage(new ImageCaptureTask(params, session),
531580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                            singleCaptureConstraint);
532580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
533580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    mCaptureManager.addMetadataChangeListener(CaptureResult.CONTROL_AE_STATE,
534580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                            new MetadataChangeListener() {
535580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                            @Override
536580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                                public void onImageMetadataChange(Key<?> key, Object oldValue,
5370ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                                        Object newValue,
5380ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                                        CaptureResult result) {
539580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                                    Log.v(TAG, "AE State Changed");
5400ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                                    if (oldValue.equals(Integer.valueOf(
5410ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                                            CaptureResult.CONTROL_AE_STATE_PRECAPTURE))) {
542580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                                        mCaptureManager.removeMetadataChangeListener(key, this);
543580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                                        sendSingleRequest(params);
5440ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                                        // TODO: Delay this until
5450ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                                        // onCaptureStarted().
54617d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers                                        onShutterInvokeUI(params);
547580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                                    }
548580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                                }
549580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                            });
550580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
551386c5b885b99f67f9c0a7380f4be153f28333089Puneet Lall                    sendAutoExposureTriggerRequest(flashMode);
552580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                } else {
553580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // We may get here if, for example, the auto focus is in the
554580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // middle of a scan.
555580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // If the flash is off, we should just wait for the next
556580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // image that arrives. This will have minimal delay since we
557580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    // do not need to send a new capture request.
558580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    mCaptureManager.captureNextImage(new ImageCaptureTask(params, session),
559580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                            zslConstraints);
560580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                }
561512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            }
562580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        } else {
563580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            // TODO If we can't save a previous frame, create a new capture
564580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            // request to do what we need (e.g. flash) and call
565580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            // captureNextImage().
566580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            throw new UnsupportedOperationException("Non-ZSL capture not yet supported");
567512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        }
568512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
569512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
570512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    @Override
571512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    public void startPreview(Surface previewSurface, CaptureReadyCallback listener) {
572512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mPreviewSurface = previewSurface;
573512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        setupAsync(mPreviewSurface, listener);
574512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
575512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
576512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    @Override
577c7251753978f80dc40131e7676f69f7e86208fd1Puneet Lall    public void close() {
578512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        if (mIsClosed) {
579512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            Log.w(TAG, "Camera is already closed.");
580512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            return;
581512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        }
582512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        try {
5839cd94d77bcafad38f15b318ea5c9dbc0849c1ecdPuneet Lall            mCaptureSession.stopRepeating();
584512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        } catch (CameraAccessException e) {
585512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            Log.e(TAG, "Could not abort captures in progress.");
586512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        }
587512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mIsClosed = true;
588512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mCameraThread.quitSafely();
589512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mDevice.close();
590512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mCaptureManager.close();
5919cd94d77bcafad38f15b318ea5c9dbc0849c1ecdPuneet Lall        mCaptureImageReader.close();
592512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
593512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
594c6da1a12fe8b78e2fbebe1af5efee514bc8e25eeSascha Haeberling    public Size[] getSupportedPreviewSizes() {
5950ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        StreamConfigurationMap config =
5960ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                mCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
597512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        return Size.convert(config.getOutputSizes(sCaptureImageFormat));
598512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
599512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
6009cefdd495332719d987ffb942742ec602793d8d4Jiawen Chen    public float getFullSizeAspectRatio() {
601512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        return mFullSizeAspectRatio;
602512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
603512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
604f6031c016d916db9789026dc0a6c559d8163a088Spike Sprague    @Override
6059ceed0d5535e8453f8b5f77959134760dac01ec5Puneet Lall    public Facing getDirection() {
6069ceed0d5535e8453f8b5f77959134760dac01ec5Puneet Lall        return mDirection.getDirection();
6079ceed0d5535e8453f8b5f77959134760dac01ec5Puneet Lall   }
608512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
609512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
610512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private void savePicture(Image image, final PhotoCaptureParameters captureParams,
611f6031c016d916db9789026dc0a6c559d8163a088Spike Sprague            CaptureSession session, CaptureResult result) {
612512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        int heading = captureParams.heading;
6130bdc4b54a18c18d7094b2e4cea1e238005c5c4a2Senpo Hu        int degrees = CameraUtil.getJpegRotation(captureParams.orientation, mCharacteristics);
614512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
615f6031c016d916db9789026dc0a6c559d8163a088Spike Sprague        ExifInterface exif = new ExifInterface();
616512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        // TODO: Add more exif tags here.
617512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
6180ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        Size size = getImageSizeForOrientation(image.getWidth(), image.getHeight(),
6190ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                degrees);
620512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
6210ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        exif.setTag(exif.buildTag(ExifInterface.TAG_PIXEL_X_DIMENSION, size.getWidth()));
6220ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        exif.setTag(exif.buildTag(ExifInterface.TAG_PIXEL_Y_DIMENSION, size.getHeight()));
6230ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall
6240ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        exif.setTag(
6250ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                exif.buildTag(ExifInterface.TAG_ORIENTATION, ExifInterface.Orientation.TOP_LEFT));
626512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
627512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        // Set GPS heading direction based on sensor, if location is on.
628512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        if (heading >= 0) {
6290ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            ExifTag directionRefTag = exif.buildTag(ExifInterface.TAG_GPS_IMG_DIRECTION_REF,
630512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                    ExifInterface.GpsTrackRef.MAGNETIC_DIRECTION);
6310ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            ExifTag directionTag =
6320ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                    exif.buildTag(ExifInterface.TAG_GPS_IMG_DIRECTION, new Rational(heading, 1));
633512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            exif.setTag(directionRefTag);
634512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            exif.setTag(directionTag);
635512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        }
636f6031c016d916db9789026dc0a6c559d8163a088Spike Sprague        new ExifUtil(exif).populateExif(Optional.<TaskImageContainer.TaskImage>absent(),
6375ca7d2642881f3cf06adb2532e0d5950524a34f4Puneet Lall                Optional.of((CaptureResultProxy) new AndroidCaptureResultProxy(result)),
6385ca7d2642881f3cf06adb2532e0d5950524a34f4Puneet Lall                Optional.<Location>absent());
63937036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling        ListenableFuture<Optional<Uri>> futureUri = session.saveAndFinish(
64037036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling                acquireJpegBytes(image, degrees),
64137036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling                size.getWidth(), size.getHeight(), 0, exif);
64237036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling        Futures.addCallback(futureUri, new FutureCallback<Optional<Uri>>() {
64337036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling            @Override
64437036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling            public void onSuccess(Optional<Uri> uriOptional) {
64537036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling                captureParams.callback.onPictureSaved(uriOptional.orNull());
64637036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling            }
64737036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling
64837036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling            @Override
64937036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling            public void onFailure(Throwable throwable) {
65037036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling                captureParams.callback.onPictureSaved(null);
65137036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling            }
65237036186326fb68c27063f97305405d3667a5eb3Sascha Haeberling        });
653512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
654512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
655512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
656512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * Asynchronously sets up the capture session.
657512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     *
658512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * @param previewSurface the surface onto which the preview should be
659512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     *            rendered.
660512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * @param listener called when setup is completed.
661512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
662512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private void setupAsync(final Surface previewSurface, final CaptureReadyCallback listener) {
663512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mCameraHandler.post(new Runnable() {
664512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                @Override
665512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            public void run() {
666512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                setup(previewSurface, listener);
667512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            }
668512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        });
669512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
670512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
671512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
672512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * Configures and attempts to create a capture session.
673512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     *
674512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * @param previewSurface the surface onto which the preview should be
675512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     *            rendered.
676512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * @param listener called when the setup is completed.
677512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
678512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private void setup(Surface previewSurface, final CaptureReadyCallback listener) {
679512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        try {
680512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            if (mCaptureSession != null) {
681512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                mCaptureSession.abortCaptures();
682512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                mCaptureSession = null;
683512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            }
684512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            List<Surface> outputSurfaces = new ArrayList<Surface>(2);
685512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            outputSurfaces.add(previewSurface);
686512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            outputSurfaces.add(mCaptureImageReader.getSurface());
687512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
688f5c62537715e8ab5e586491b75e8ddff9a3d9f6aAlan Newberger            mDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
689512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                    @Override
690512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                public void onConfigureFailed(CameraCaptureSession session) {
691512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                    listener.onSetupFailed();
692512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                }
693512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
694512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                    @Override
695512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                public void onConfigured(CameraCaptureSession session) {
696512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                    mCaptureSession = session;
697b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers                    mAFRegions = ZERO_WEIGHT_3A_REGION;
698b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers                    mAERegions = ZERO_WEIGHT_3A_REGION;
699580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    mZoomValue = 1f;
700580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    mCropRegion = cropRegionForZoom(mZoomValue);
701580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    boolean success = sendRepeatingCaptureRequest();
702580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    if (success) {
703142b5bf5e10db858c2d2e69fd93d6565ba51363bPuneet Lall                        mReadyStateManager.setInput(ReadyStateRequirement.CAPTURE_NOT_IN_PROGRESS,
704142b5bf5e10db858c2d2e69fd93d6565ba51363bPuneet Lall                                true);
705142b5bf5e10db858c2d2e69fd93d6565ba51363bPuneet Lall                        mReadyStateManager.notifyListeners();
706580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                        listener.onReadyForCapture();
707580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    } else {
708580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                        listener.onSetupFailed();
709580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    }
710512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                }
711512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
712512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                    @Override
713512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                public void onClosed(CameraCaptureSession session) {
714512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                    super.onClosed(session);
715512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                }
716512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            }, mCameraHandler);
717512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        } catch (CameraAccessException ex) {
718512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            Log.e(TAG, "Could not set up capture session", ex);
719512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            listener.onSetupFailed();
720512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        }
721512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
722512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
723580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private void addRegionsToCaptureRequestBuilder(CaptureRequest.Builder builder) {
724b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers        builder.set(CaptureRequest.CONTROL_AE_REGIONS, mAERegions);
725b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers        builder.set(CaptureRequest.CONTROL_AF_REGIONS, mAFRegions);
726580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        builder.set(CaptureRequest.SCALER_CROP_REGION, mCropRegion);
727580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    }
728580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
729580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private void addFlashToCaptureRequestBuilder(CaptureRequest.Builder builder, Flash flashMode) {
730580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        switch (flashMode) {
731580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            case ON:
732580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder.set(CaptureRequest.CONTROL_AE_MODE,
733580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                        CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
734580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE);
735580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                break;
736580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            case OFF:
7370ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
738580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
739580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                break;
740580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            case AUTO:
741580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder.set(CaptureRequest.CONTROL_AE_MODE,
742580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                        CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
743580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                break;
744580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        }
745580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    }
746580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
747512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
748580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     * Request a stream of images.
749512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     *
750580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     * @return true if successful, false if there was an error submitting the
751580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     *         capture request.
752512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
753580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private boolean sendRepeatingCaptureRequest() {
754580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        Log.v(TAG, "sendRepeatingCaptureRequest()");
755512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        try {
756580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            CaptureRequest.Builder builder;
757580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            if (ZSL_ENABLED) {
7580ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
759580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            } else {
760580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
761580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            }
762512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
763512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            builder.addTarget(mPreviewSurface);
764512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
765580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            if (ZSL_ENABLED) {
766580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder.addTarget(mCaptureImageReader.getSurface());
767580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            }
768580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
769580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
770512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
771512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            builder.set(CaptureRequest.CONTROL_AF_MODE,
772580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
773580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
774512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
775580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
776580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
777512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
778580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            addRegionsToCaptureRequestBuilder(builder);
779512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
7800ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            mCaptureSession.setRepeatingRequest(builder.build(), mCaptureManager, mCameraHandler);
781580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            return true;
782580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        } catch (CameraAccessException e) {
783580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            if (ZSL_ENABLED) {
784580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                Log.v(TAG, "Could not execute zero-shutter-lag repeating request.", e);
785580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            } else {
786580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                Log.v(TAG, "Could not execute preview request.", e);
787512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            }
788580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            return false;
789580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        }
790580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    }
791580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
792580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    /**
793580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     * Request a single image.
794580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     *
795580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     * @return true if successful, false if there was an error submitting the
796580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     *         capture request.
797580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     */
798580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private boolean sendSingleRequest(OneCamera.PhotoCaptureParameters params) {
799580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        Log.v(TAG, "sendSingleRequest()");
800580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        try {
801580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            CaptureRequest.Builder builder;
802580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
803580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
804580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.addTarget(mPreviewSurface);
805580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
806580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            // Always add this surface for single image capture requests.
807580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.addTarget(mCaptureImageReader.getSurface());
808580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
809580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
810580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
811386c5b885b99f67f9c0a7380f4be153f28333089Puneet Lall            Flash flashMode = Flash.OFF;
812386c5b885b99f67f9c0a7380f4be153f28333089Puneet Lall            addFlashToCaptureRequestBuilder(builder, flashMode);
813580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            addRegionsToCaptureRequestBuilder(builder);
814580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
815580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
816580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
817580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
818580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            // Tag this as a special request which should be saved.
819580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.setTag(RequestTag.EXPLICIT_CAPTURE);
820580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
821580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            if (sCaptureImageFormat == ImageFormat.JPEG) {
822580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder.set(CaptureRequest.JPEG_QUALITY, (byte) (JPEG_QUALITY));
823580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder.set(CaptureRequest.JPEG_ORIENTATION,
824580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                        CameraUtil.getJpegRotation(params.orientation, mCharacteristics));
825580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            }
826580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
8270ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            mCaptureSession.capture(builder.build(), mCaptureManager, mCameraHandler);
828580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            return true;
829580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        } catch (CameraAccessException e) {
830580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            Log.v(TAG, "Could not execute single still capture request.", e);
831580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            return false;
832580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        }
833580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    }
834580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
8351321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang    private boolean sendRepeatingBurstCaptureRequest() {
8361321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang        Log.v(TAG, "sendRepeatingBurstCaptureRequest()");
8371321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang        try {
8381321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            CaptureRequest.Builder builder;
8391321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
8401321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            builder.addTarget(mPreviewSurface);
8411321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang
8421321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            if (ZSL_ENABLED) {
8431321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang                builder.addTarget(mCaptureImageReader.getSurface());
8441321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            }
8451321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang
8461321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
8471321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            builder.set(CaptureRequest.CONTROL_AF_MODE,
8481321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO);
8491321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
8501321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang
8511321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
8521321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
8531321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang
8541321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            addRegionsToCaptureRequestBuilder(builder);
8551321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang
8561321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            mCaptureSession.setRepeatingRequest(builder.build(), mCaptureManager, mCameraHandler);
8571321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            return true;
8581321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang        } catch (CameraAccessException e) {
8591321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            Log.v(TAG, "Could not send repeating burst capture request.", e);
8601321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang            return false;
8611321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang        }
8621321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang    }
8631321823277e30b0be46f4911418b7b64cfc7d1c0Radford Juang
864580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private boolean sendAutoExposureTriggerRequest(Flash flashMode) {
865580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        Log.v(TAG, "sendAutoExposureTriggerRequest()");
866580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        try {
867580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            CaptureRequest.Builder builder;
868580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            if (ZSL_ENABLED) {
8690ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
870580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            } else {
871580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
872580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            }
873580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
874580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.addTarget(mPreviewSurface);
875580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
876580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            if (ZSL_ENABLED) {
877580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder.addTarget(mCaptureImageReader.getSurface());
878580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            }
879580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
880580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
881580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
882580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
883580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                    CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
884580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
885580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            addRegionsToCaptureRequestBuilder(builder);
886580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            addFlashToCaptureRequestBuilder(builder, flashMode);
887580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
8880ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            mCaptureSession.capture(builder.build(), mCaptureManager, mCameraHandler);
889580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
890580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            return true;
891580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        } catch (CameraAccessException e) {
892580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            Log.v(TAG, "Could not execute auto exposure trigger request.", e);
893580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            return false;
894580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        }
895580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    }
896580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
897580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    /**
898580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     */
899580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private boolean sendAutoFocusTriggerRequest() {
900580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        Log.v(TAG, "sendAutoFocusTriggerRequest()");
901580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        try {
902580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            CaptureRequest.Builder builder;
903580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            if (ZSL_ENABLED) {
9040ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
905580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            } else {
906580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
907512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            }
908580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
909580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.addTarget(mPreviewSurface);
910580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
911580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            if (ZSL_ENABLED) {
912580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder.addTarget(mCaptureImageReader.getSurface());
913580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            }
914580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
915580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
916580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
917580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            addRegionsToCaptureRequestBuilder(builder);
918580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
919580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO);
920580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
921580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
9220ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            mCaptureSession.capture(builder.build(), mCaptureManager, mCameraHandler);
923580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
924580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            return true;
925580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        } catch (CameraAccessException e) {
926580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            Log.v(TAG, "Could not execute auto focus trigger request.", e);
927580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            return false;
928580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        }
929580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    }
930580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
931580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    /**
932580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     * Like {@link #sendRepeatingCaptureRequest()}, but with the focus held
933580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     * constant.
934580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     *
935580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     * @return true if successful, false if there was an error submitting the
936580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     *         capture request.
937580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall     */
938580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private boolean sendAutoFocusHoldRequest() {
939580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        Log.v(TAG, "sendAutoFocusHoldRequest()");
940580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        try {
941580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            CaptureRequest.Builder builder;
942580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            if (ZSL_ENABLED) {
9430ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
944580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            } else {
945580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
946580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            }
947580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
948580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.addTarget(mPreviewSurface);
949580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
950580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            if (ZSL_ENABLED) {
951580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                builder.addTarget(mCaptureImageReader.getSurface());
952580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            }
953580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
954580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
955580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
956580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO);
957580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
958580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
959580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            addRegionsToCaptureRequestBuilder(builder);
960580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            // TODO: This should fire the torch, if appropriate.
961580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
962580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            mCaptureSession.setRepeatingRequest(builder.build(), mCaptureManager, mCameraHandler);
963580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
964580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            return true;
965580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        } catch (CameraAccessException e) {
966580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            Log.v(TAG, "Could not execute auto focus hold request.", e);
967580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            return false;
968512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        }
969512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
970512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
971512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
972512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * Calculate the aspect ratio of the full size capture on this device.
973512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     *
974512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * @param characteristics the characteristics of the camera device.
975512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * @return The aspect ration, in terms of width/height of the full capture
976512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     *         size.
977512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
9789cefdd495332719d987ffb942742ec602793d8d4Jiawen Chen    private static float calculateFullSizeAspectRatio(CameraCharacteristics characteristics) {
979512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        Rect activeArraySize =
980512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
9819cefdd495332719d987ffb942742ec602793d8d4Jiawen Chen        return ((float) activeArraySize.width()) / activeArraySize.height();
982512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
983512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
984512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
9850ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall     * @param originalWidth the width of the original image captured from the
9860ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall     *            camera
9870ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall     * @param originalHeight the height of the original image captured from the
9880ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall     *            camera
9890ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall     * @param orientation the rotation to apply, in degrees.
9900ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall     * @return The size of the final rotated image
9910ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall     */
9920ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall    private Size getImageSizeForOrientation(int originalWidth, int originalHeight,
9930ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            int orientation) {
9940ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        if (orientation == 0 || orientation == 180) {
9950ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            return new Size(originalWidth, originalHeight);
9960ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        } else if (orientation == 90 || orientation == 270) {
9970ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            return new Size(originalHeight, originalWidth);
9980ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        } else {
9990ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall            throw new InvalidParameterException("Orientation not supported.");
10000ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall        }
10010ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall    }
10020ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall
10030ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall    /**
1004512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * Given an image reader, extracts the JPEG image bytes and then closes the
1005512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * reader.
1006512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     *
1007182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall     * @param img the image from which to extract jpeg bytes or compress to
1008182ba6f13e9dab9a9c0341efe4c907ff7853352dPuneet Lall     *            jpeg.
10090bdc4b54a18c18d7094b2e4cea1e238005c5c4a2Senpo Hu     * @param degrees the angle to rotate the image clockwise, in degrees. Rotation is
10100ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall     *            only applied to YUV images.
1011512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * @return The bytes of the JPEG image. Newly allocated.
1012512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
10130ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall    private byte[] acquireJpegBytes(Image img, int degrees) {
1014512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        ByteBuffer buffer;
1015512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1016512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        if (img.getFormat() == ImageFormat.JPEG) {
1017512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            Image.Plane plane0 = img.getPlanes()[0];
1018512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            buffer = plane0.getBuffer();
1019512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1020512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            byte[] imageBytes = new byte[buffer.remaining()];
1021512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            buffer.get(imageBytes);
1022512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            buffer.rewind();
1023512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            return imageBytes;
1024512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        } else if (img.getFormat() == ImageFormat.YUV_420_888) {
1025512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            buffer = mJpegByteBufferPool.acquire();
1026512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            if (buffer == null) {
1027512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                buffer = ByteBuffer.allocateDirect(img.getWidth() * img.getHeight() * 3);
1028512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            }
1029512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
103030ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin            int numBytes = JpegUtilNative.compressJpegFromYUV420Image(
103130ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin                    new AndroidImageProxy(img), buffer, JPEG_QUALITY,
10320ad7ab0b0a0d17a96438a503d0c918979b5d6480Puneet Lall                    degrees);
1033512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1034512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            if (numBytes < 0) {
1035512001df0211fa8999593717a0f186457a5a9cefPuneet Lall                throw new RuntimeException("Error compressing jpeg.");
1036512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            }
1037512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1038512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            buffer.limit(numBytes);
1039512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1040512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            byte[] imageBytes = new byte[buffer.remaining()];
1041512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            buffer.get(imageBytes);
1042512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1043512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            buffer.clear();
1044512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            mJpegByteBufferPool.release(buffer);
1045512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1046512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            return imageBytes;
1047512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        } else {
1048512001df0211fa8999593717a0f186457a5a9cefPuneet Lall            throw new RuntimeException("Unsupported image format.");
1049512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        }
1050512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
1051512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1052580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall    private void startAFCycle() {
1053580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // Clean up any existing AF cycle's pending callbacks.
1054580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        mCameraHandler.removeCallbacksAndMessages(FOCUS_RESUME_CALLBACK_TOKEN);
1055580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
1056580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // Send a single CONTROL_AF_TRIGGER_START capture request.
1057580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        sendAutoFocusTriggerRequest();
1058580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
1059580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // Immediately send a request for a regular preview stream, but with
1060580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // CONTROL_AF_MODE_AUTO set so that the focus remains constant after the
1061580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        // AF cycle completes.
1062580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        sendAutoFocusHoldRequest();
1063580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall
1064b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers        // Waits Settings3A.getFocusHoldMillis() milliseconds before sending
1065b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers        // a request for a regular preview stream to resume.
1066580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        mCameraHandler.postAtTime(new Runnable() {
106780f44448e13b5d6d33f4aad63448d7b39b6dda0fPuneet Lall                @Override
1068580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            public void run() {
1069b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers                mAERegions = ZERO_WEIGHT_3A_REGION;
1070b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers                mAFRegions = ZERO_WEIGHT_3A_REGION;
1071580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall                sendRepeatingCaptureRequest();
1072580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall            }
1073b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers        }, FOCUS_RESUME_CALLBACK_TOKEN,
1074b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers                SystemClock.uptimeMillis() + Settings3A.getFocusHoldMillis());
1075512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
1076512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1077512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    /**
1078512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     * @see com.android.camera.one.OneCamera#triggerFocusAndMeterAtPoint(float,
1079512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     *      float)
1080512001df0211fa8999593717a0f186457a5a9cefPuneet Lall     */
1081512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    @Override
1082512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    public void triggerFocusAndMeterAtPoint(float nx, float ny) {
10830971376b0ddf12c8aa886ad9109f6a8929095154Jiawen Chen        int sensorOrientation = mCharacteristics.get(
10840971376b0ddf12c8aa886ad9109f6a8929095154Jiawen Chen            CameraCharacteristics.SENSOR_ORIENTATION);
10850971376b0ddf12c8aa886ad9109f6a8929095154Jiawen Chen        mAERegions = AutoFocusHelper.aeRegionsForNormalizedCoord(nx, ny, mCropRegion, sensorOrientation);
10860971376b0ddf12c8aa886ad9109f6a8929095154Jiawen Chen        mAFRegions = AutoFocusHelper.afRegionsForNormalizedCoord(nx, ny, mCropRegion, sensorOrientation);
1087512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1088580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        startAFCycle();
1089512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
1090512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1091512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    @Override
1092512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    public Size pickPreviewSize(Size pictureSize, Context context) {
10934d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall        if (pictureSize == null) {
10944d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall            // TODO The default should be selected by the caller, and
10954d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall            // pictureSize should never be null.
10964d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall            pictureSize = getDefaultPictureSize();
10974d6d676c368b70e8c0fcf462e51de1d59fe34028Puneet Lall        }
1098512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        float pictureAspectRatio = pictureSize.getWidth() / (float) pictureSize.getHeight();
10996ba8eeea4758e29318c615e978c63599c30438b4Paul Rohde        return CaptureModuleUtil.getOptimalPreviewSize(getSupportedPreviewSizes(),
11006ba8eeea4758e29318c615e978c63599c30438b4Paul Rohde              pictureAspectRatio);
1101512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
1102512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1103512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    @Override
1104512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    public float getMaxZoom() {
1105512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        return mCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
1106512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
1107512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1108512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    @Override
1109512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    public void setZoom(float zoom) {
1110512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mZoomValue = zoom;
1111512001df0211fa8999593717a0f186457a5a9cefPuneet Lall        mCropRegion = cropRegionForZoom(zoom);
1112580f451fc85cc752e71eb730006b90d09aaafb55Puneet Lall        sendRepeatingCaptureRequest();
1113512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
1114512001df0211fa8999593717a0f186457a5a9cefPuneet Lall
1115512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    private Rect cropRegionForZoom(float zoom) {
1116b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers        return AutoFocusHelper.cropRegionForZoom(mCharacteristics, zoom);
1117512001df0211fa8999593717a0f186457a5a9cefPuneet Lall    }
1118512001df0211fa8999593717a0f186457a5a9cefPuneet Lall}
1119