1a0842b40441db5332a5290f941021636b1182761Sol Boucher/*
2a0842b40441db5332a5290f941021636b1182761Sol Boucher * Copyright (C) 2014 The Android Open Source Project
3a0842b40441db5332a5290f941021636b1182761Sol Boucher *
4a0842b40441db5332a5290f941021636b1182761Sol Boucher * Licensed under the Apache License, Version 2.0 (the "License");
5a0842b40441db5332a5290f941021636b1182761Sol Boucher * you may not use this file except in compliance with the License.
6a0842b40441db5332a5290f941021636b1182761Sol Boucher * You may obtain a copy of the License at
7a0842b40441db5332a5290f941021636b1182761Sol Boucher *
8a0842b40441db5332a5290f941021636b1182761Sol Boucher *      http://www.apache.org/licenses/LICENSE-2.0
9a0842b40441db5332a5290f941021636b1182761Sol Boucher *
10a0842b40441db5332a5290f941021636b1182761Sol Boucher * Unless required by applicable law or agreed to in writing, software
11a0842b40441db5332a5290f941021636b1182761Sol Boucher * distributed under the License is distributed on an "AS IS" BASIS,
12a0842b40441db5332a5290f941021636b1182761Sol Boucher * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a0842b40441db5332a5290f941021636b1182761Sol Boucher * See the License for the specific language governing permissions and
14a0842b40441db5332a5290f941021636b1182761Sol Boucher * limitations under the License.
15a0842b40441db5332a5290f941021636b1182761Sol Boucher */
16a0842b40441db5332a5290f941021636b1182761Sol Boucher
17a0842b40441db5332a5290f941021636b1182761Sol Boucherpackage com.android.ex.camera2.portability;
18a0842b40441db5332a5290f941021636b1182761Sol Boucher
19a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.annotation.TargetApi;
20a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.content.Context;
21de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport android.graphics.ImageFormat;
22f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucherimport android.graphics.Matrix;
23a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.graphics.Rect;
24f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucherimport android.graphics.RectF;
25a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.graphics.SurfaceTexture;
26a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.hardware.camera2.CameraAccessException;
27a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.hardware.camera2.CameraCaptureSession;
28a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.hardware.camera2.CameraCharacteristics;
29a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.hardware.camera2.CameraDevice;
30a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.hardware.camera2.CameraManager;
31a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.hardware.camera2.CaptureFailure;
32a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.hardware.camera2.CaptureRequest;
33a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.hardware.camera2.CaptureResult;
34a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.hardware.camera2.TotalCaptureResult;
35a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.hardware.camera2.params.MeteringRectangle;
36de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport android.media.Image;
37de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport android.media.ImageReader;
38aa907a3b6637b4f95dbf572d0cf790a70ba3aeb0Sol Boucherimport android.media.MediaActionSound;
39a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.os.Build;
40a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.os.Handler;
41a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.os.HandlerThread;
42a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.os.Looper;
43a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.os.Message;
44a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.view.Surface;
45a0842b40441db5332a5290f941021636b1182761Sol Boucher
46a0842b40441db5332a5290f941021636b1182761Sol Boucherimport com.android.ex.camera2.portability.debug.Log;
47de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport com.android.ex.camera2.utils.Camera2RequestSettingsSet;
48a0842b40441db5332a5290f941021636b1182761Sol Boucher
49de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport java.nio.ByteBuffer;
50a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.ArrayList;
51a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.Arrays;
52a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.HashSet;
53a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.List;
54a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.Set;
55a0842b40441db5332a5290f941021636b1182761Sol Boucher
56a0842b40441db5332a5290f941021636b1182761Sol Boucher/**
57a0842b40441db5332a5290f941021636b1182761Sol Boucher * A class to implement {@link CameraAgent} of the Android camera2 framework.
58a0842b40441db5332a5290f941021636b1182761Sol Boucher */
59a0842b40441db5332a5290f941021636b1182761Sol Boucherclass AndroidCamera2AgentImpl extends CameraAgent {
60a0842b40441db5332a5290f941021636b1182761Sol Boucher    private static final Log.Tag TAG = new Log.Tag("AndCam2AgntImp");
61a0842b40441db5332a5290f941021636b1182761Sol Boucher
62a0842b40441db5332a5290f941021636b1182761Sol Boucher    private final Camera2Handler mCameraHandler;
63a0842b40441db5332a5290f941021636b1182761Sol Boucher    private final HandlerThread mCameraHandlerThread;
64a0842b40441db5332a5290f941021636b1182761Sol Boucher    private final CameraStateHolder mCameraState;
65a0842b40441db5332a5290f941021636b1182761Sol Boucher    private final DispatchThread mDispatchThread;
66a0842b40441db5332a5290f941021636b1182761Sol Boucher    private final CameraManager mCameraManager;
67aa907a3b6637b4f95dbf572d0cf790a70ba3aeb0Sol Boucher    private final MediaActionSound mNoisemaker;
682d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    private CameraExceptionHandler mExceptionHandler;
69a0842b40441db5332a5290f941021636b1182761Sol Boucher
70a0842b40441db5332a5290f941021636b1182761Sol Boucher    /**
71a0842b40441db5332a5290f941021636b1182761Sol Boucher     * Number of camera devices.  The length of {@code mCameraDevices} does not reveal this
72a0842b40441db5332a5290f941021636b1182761Sol Boucher     * information because that list may contain since-invalidated indices.
73a0842b40441db5332a5290f941021636b1182761Sol Boucher     */
74a0842b40441db5332a5290f941021636b1182761Sol Boucher    private int mNumCameraDevices;
75a0842b40441db5332a5290f941021636b1182761Sol Boucher
76a0842b40441db5332a5290f941021636b1182761Sol Boucher    /**
77a0842b40441db5332a5290f941021636b1182761Sol Boucher     * Transformation between integral camera indices and the {@link java.lang.String} indices used
78a0842b40441db5332a5290f941021636b1182761Sol Boucher     * by the underlying API.  Note that devices may disappear because they've been disconnected or
79a0842b40441db5332a5290f941021636b1182761Sol Boucher     * have otherwise gone offline.  Because we need to keep the meanings of whatever indices we
80a0842b40441db5332a5290f941021636b1182761Sol Boucher     * expose stable, we cannot simply remove them in such a case; instead, we insert {@code null}s
81a0842b40441db5332a5290f941021636b1182761Sol Boucher     * to invalidate any such indices.  Whenever new devices appear, they are appended to the end of
82a0842b40441db5332a5290f941021636b1182761Sol Boucher     * the list, and thereby assigned the lowest index that has never yet been used.
83a0842b40441db5332a5290f941021636b1182761Sol Boucher     */
84a0842b40441db5332a5290f941021636b1182761Sol Boucher    private final List<String> mCameraDevices;
85a0842b40441db5332a5290f941021636b1182761Sol Boucher
86a0842b40441db5332a5290f941021636b1182761Sol Boucher    AndroidCamera2AgentImpl(Context context) {
87a0842b40441db5332a5290f941021636b1182761Sol Boucher        mCameraHandlerThread = new HandlerThread("Camera2 Handler Thread");
88a0842b40441db5332a5290f941021636b1182761Sol Boucher        mCameraHandlerThread.start();
89a0842b40441db5332a5290f941021636b1182761Sol Boucher        mCameraHandler = new Camera2Handler(mCameraHandlerThread.getLooper());
902d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        mExceptionHandler = new CameraExceptionHandler(mCameraHandler);
91a0842b40441db5332a5290f941021636b1182761Sol Boucher        mCameraState = new AndroidCamera2StateHolder();
92a0842b40441db5332a5290f941021636b1182761Sol Boucher        mDispatchThread = new DispatchThread(mCameraHandler, mCameraHandlerThread);
93a0842b40441db5332a5290f941021636b1182761Sol Boucher        mDispatchThread.start();
94a0842b40441db5332a5290f941021636b1182761Sol Boucher        mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
95aa907a3b6637b4f95dbf572d0cf790a70ba3aeb0Sol Boucher        mNoisemaker = new MediaActionSound();
96aa907a3b6637b4f95dbf572d0cf790a70ba3aeb0Sol Boucher        mNoisemaker.load(MediaActionSound.SHUTTER_CLICK);
97a0842b40441db5332a5290f941021636b1182761Sol Boucher
98a0842b40441db5332a5290f941021636b1182761Sol Boucher        mNumCameraDevices = 0;
99a0842b40441db5332a5290f941021636b1182761Sol Boucher        mCameraDevices = new ArrayList<String>();
100a0842b40441db5332a5290f941021636b1182761Sol Boucher        updateCameraDevices();
101a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
102a0842b40441db5332a5290f941021636b1182761Sol Boucher
103a0842b40441db5332a5290f941021636b1182761Sol Boucher    /**
104a0842b40441db5332a5290f941021636b1182761Sol Boucher     * Updates the camera device index assignments stored in {@link mCameraDevices}, without
105a0842b40441db5332a5290f941021636b1182761Sol Boucher     * reappropriating any currently-assigned index.
106a0842b40441db5332a5290f941021636b1182761Sol Boucher     * @return Whether the operation was successful
107a0842b40441db5332a5290f941021636b1182761Sol Boucher     */
108a0842b40441db5332a5290f941021636b1182761Sol Boucher    private boolean updateCameraDevices() {
109a0842b40441db5332a5290f941021636b1182761Sol Boucher        try {
110a0842b40441db5332a5290f941021636b1182761Sol Boucher            String[] currentCameraDevices = mCameraManager.getCameraIdList();
111a0842b40441db5332a5290f941021636b1182761Sol Boucher            Set<String> currentSet = new HashSet<String>(Arrays.asList(currentCameraDevices));
112a0842b40441db5332a5290f941021636b1182761Sol Boucher
113a0842b40441db5332a5290f941021636b1182761Sol Boucher            // Invalidate the indices assigned to any camera devices that are no longer present
114a0842b40441db5332a5290f941021636b1182761Sol Boucher            for (int index = 0; index < mCameraDevices.size(); ++index) {
115a0842b40441db5332a5290f941021636b1182761Sol Boucher                if (!currentSet.contains(mCameraDevices.get(index))) {
116a0842b40441db5332a5290f941021636b1182761Sol Boucher                    mCameraDevices.set(index, null);
117a0842b40441db5332a5290f941021636b1182761Sol Boucher                    --mNumCameraDevices;
118a0842b40441db5332a5290f941021636b1182761Sol Boucher                }
119a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
120a0842b40441db5332a5290f941021636b1182761Sol Boucher
121a0842b40441db5332a5290f941021636b1182761Sol Boucher            // Assign fresh indices to any new camera devices
122a0842b40441db5332a5290f941021636b1182761Sol Boucher            currentSet.removeAll(mCameraDevices); // The devices we didn't know about
123a0842b40441db5332a5290f941021636b1182761Sol Boucher            for (String device : currentCameraDevices) {
124a0842b40441db5332a5290f941021636b1182761Sol Boucher                if (currentSet.contains(device)) {
125a0842b40441db5332a5290f941021636b1182761Sol Boucher                    mCameraDevices.add(device);
126a0842b40441db5332a5290f941021636b1182761Sol Boucher                    ++mNumCameraDevices;
127a0842b40441db5332a5290f941021636b1182761Sol Boucher                }
128a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
129a0842b40441db5332a5290f941021636b1182761Sol Boucher
130a0842b40441db5332a5290f941021636b1182761Sol Boucher            return true;
131a0842b40441db5332a5290f941021636b1182761Sol Boucher        } catch (CameraAccessException ex) {
132a0842b40441db5332a5290f941021636b1182761Sol Boucher            Log.e(TAG, "Could not get device listing from camera subsystem", ex);
133a0842b40441db5332a5290f941021636b1182761Sol Boucher            return false;
134a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
135a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
136a0842b40441db5332a5290f941021636b1182761Sol Boucher
137a0842b40441db5332a5290f941021636b1182761Sol Boucher    // TODO: Implement
138a0842b40441db5332a5290f941021636b1182761Sol Boucher    @Override
139a0842b40441db5332a5290f941021636b1182761Sol Boucher    public void recycle() {}
140a0842b40441db5332a5290f941021636b1182761Sol Boucher
141a0842b40441db5332a5290f941021636b1182761Sol Boucher    // TODO: Some indices may now be invalid; ensure everyone can handle that and update the docs
142a0842b40441db5332a5290f941021636b1182761Sol Boucher    @Override
143a0842b40441db5332a5290f941021636b1182761Sol Boucher    public CameraDeviceInfo getCameraDeviceInfo() {
144a0842b40441db5332a5290f941021636b1182761Sol Boucher        updateCameraDevices();
145a0842b40441db5332a5290f941021636b1182761Sol Boucher        return new AndroidCamera2DeviceInfo(mCameraManager, mCameraDevices.toArray(new String[0]),
146a0842b40441db5332a5290f941021636b1182761Sol Boucher                mNumCameraDevices);
147a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
148a0842b40441db5332a5290f941021636b1182761Sol Boucher
149a0842b40441db5332a5290f941021636b1182761Sol Boucher    @Override
150a0842b40441db5332a5290f941021636b1182761Sol Boucher    protected Handler getCameraHandler() {
151a0842b40441db5332a5290f941021636b1182761Sol Boucher        return mCameraHandler;
152a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
153a0842b40441db5332a5290f941021636b1182761Sol Boucher
154a0842b40441db5332a5290f941021636b1182761Sol Boucher    @Override
155a0842b40441db5332a5290f941021636b1182761Sol Boucher    protected DispatchThread getDispatchThread() {
156a0842b40441db5332a5290f941021636b1182761Sol Boucher        return mDispatchThread;
157a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
158a0842b40441db5332a5290f941021636b1182761Sol Boucher
1592d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    @Override
1602d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    protected CameraStateHolder getCameraState() {
1612d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        return mCameraState;
1622d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    }
1632d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
1642d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    @Override
1652d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    protected CameraExceptionHandler getCameraExceptionHandler() {
1662d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        return mExceptionHandler;
1672d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    }
1682d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
1692d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    @Override
1702d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    public void setCameraExceptionHandler(CameraExceptionHandler exceptionHandler) {
1712d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        mExceptionHandler = exceptionHandler;
1722d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    }
1732d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
174de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher    private static abstract class CaptureAvailableListener
175bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala            extends CameraCaptureSession.CaptureCallback
176de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            implements ImageReader.OnImageAvailableListener {};
177de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
178a0842b40441db5332a5290f941021636b1182761Sol Boucher    private class Camera2Handler extends HistoryHandler {
179a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        // Caller-provided when leaving CAMERA_UNOPENED state:
180a0842b40441db5332a5290f941021636b1182761Sol Boucher        private CameraOpenCallback mOpenCallback;
181a0842b40441db5332a5290f941021636b1182761Sol Boucher        private int mCameraIndex;
182a0842b40441db5332a5290f941021636b1182761Sol Boucher        private String mCameraId;
1836a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin        private int mCancelAfPending = 0;
184a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
185a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        // Available in CAMERA_UNCONFIGURED state and above:
186a0842b40441db5332a5290f941021636b1182761Sol Boucher        private CameraDevice mCamera;
187a0842b40441db5332a5290f941021636b1182761Sol Boucher        private AndroidCamera2ProxyImpl mCameraProxy;
188de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        private Camera2RequestSettingsSet mPersistentSettings;
189a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        private Rect mActiveArray;
190de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        private boolean mLegacyDevice;
191a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
192a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        // Available in CAMERA_CONFIGURED state and above:
193a0842b40441db5332a5290f941021636b1182761Sol Boucher        private Size mPreviewSize;
194a0842b40441db5332a5290f941021636b1182761Sol Boucher        private Size mPhotoSize;
195a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
196a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        // Available in PREVIEW_READY state and above:
197a0842b40441db5332a5290f941021636b1182761Sol Boucher        private SurfaceTexture mPreviewTexture;
198a0842b40441db5332a5290f941021636b1182761Sol Boucher        private Surface mPreviewSurface;
199a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        private CameraCaptureSession mSession;
200de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        private ImageReader mCaptureReader;
201a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
202a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        // Available from the beginning of PREVIEW_ACTIVE until the first preview frame arrives:
203a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        private CameraStartPreviewCallback mOneshotPreviewingCallback;
204a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
205a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        // Available in FOCUS_LOCKED between AF trigger receipt and whenever the lens stops moving:
206a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        private CameraAFCallback mOneshotAfCallback;
207a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
208de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        // Available when taking picture between AE trigger receipt and autoexposure convergence
209de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        private CaptureAvailableListener mOneshotCaptureCallback;
210de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
211a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        // Available whenever setAutoFocusMoveCallback() was last invoked with a non-null argument:
212a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        private CameraAFMoveCallback mPassiveAfCallback;
213a0842b40441db5332a5290f941021636b1182761Sol Boucher
214984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher        // Gets reset on every state change
215984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher        private int mCurrentAeState = CaptureResult.CONTROL_AE_STATE_INACTIVE;
216984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
217a0842b40441db5332a5290f941021636b1182761Sol Boucher        Camera2Handler(Looper looper) {
218a0842b40441db5332a5290f941021636b1182761Sol Boucher            super(looper);
219a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
220a0842b40441db5332a5290f941021636b1182761Sol Boucher
221a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
222a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void handleMessage(final Message msg) {
223a0842b40441db5332a5290f941021636b1182761Sol Boucher            super.handleMessage(msg);
2246a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin            Log.v(TAG, "handleMessage - action = '" + CameraActions.stringify(msg.what) + "'");
225733ca8dfa76ac34d1f9caff8798d01a4a8f44002Senpo Hu            int cameraAction = msg.what;
226a0842b40441db5332a5290f941021636b1182761Sol Boucher            try {
227733ca8dfa76ac34d1f9caff8798d01a4a8f44002Senpo Hu                switch (cameraAction) {
228a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.OPEN_CAMERA:
229a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.RECONNECT: {
230a0842b40441db5332a5290f941021636b1182761Sol Boucher                        CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;
231a0842b40441db5332a5290f941021636b1182761Sol Boucher                        int cameraIndex = msg.arg1;
232a0842b40441db5332a5290f941021636b1182761Sol Boucher
233772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher                        if (mCameraState.getState() > AndroidCamera2StateHolder.CAMERA_UNOPENED) {
234a0842b40441db5332a5290f941021636b1182761Sol Boucher                            openCallback.onDeviceOpenedAlready(cameraIndex,
235a0842b40441db5332a5290f941021636b1182761Sol Boucher                                    generateHistoryString(cameraIndex));
236a0842b40441db5332a5290f941021636b1182761Sol Boucher                            break;
237a0842b40441db5332a5290f941021636b1182761Sol Boucher                        }
238a0842b40441db5332a5290f941021636b1182761Sol Boucher
239a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mOpenCallback = openCallback;
240a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraIndex = cameraIndex;
241a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraId = mCameraDevices.get(mCameraIndex);
24250f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher                        Log.i(TAG, String.format("Opening camera index %d (id %s) with camera2 API",
24350f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher                                cameraIndex, mCameraId));
244a0842b40441db5332a5290f941021636b1182761Sol Boucher
245a0842b40441db5332a5290f941021636b1182761Sol Boucher                        if (mCameraId == null) {
246a0842b40441db5332a5290f941021636b1182761Sol Boucher                            mOpenCallback.onCameraDisabled(msg.arg1);
247a0842b40441db5332a5290f941021636b1182761Sol Boucher                            break;
248a0842b40441db5332a5290f941021636b1182761Sol Boucher                        }
249bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                        mCameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, this);
250a0842b40441db5332a5290f941021636b1182761Sol Boucher
251a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
252a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
253a0842b40441db5332a5290f941021636b1182761Sol Boucher
254a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.RELEASE: {
255a0842b40441db5332a5290f941021636b1182761Sol Boucher                        if (mCameraState.getState() == AndroidCamera2StateHolder.CAMERA_UNOPENED) {
256a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            Log.w(TAG, "Ignoring release at inappropriate time");
257a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            break;
258a0842b40441db5332a5290f941021636b1182761Sol Boucher                        }
259a0842b40441db5332a5290f941021636b1182761Sol Boucher
260a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        if (mSession != null) {
261a0842b40441db5332a5290f941021636b1182761Sol Boucher                            closePreviewSession();
262a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            mSession = null;
263a0842b40441db5332a5290f941021636b1182761Sol Boucher                        }
264a0842b40441db5332a5290f941021636b1182761Sol Boucher                        if (mCamera != null) {
265a0842b40441db5332a5290f941021636b1182761Sol Boucher                            mCamera.close();
266a0842b40441db5332a5290f941021636b1182761Sol Boucher                            mCamera = null;
267a0842b40441db5332a5290f941021636b1182761Sol Boucher                        }
268a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraProxy = null;
269de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        mPersistentSettings = null;
270a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        mActiveArray = null;
271a0842b40441db5332a5290f941021636b1182761Sol Boucher                        if (mPreviewSurface != null) {
272a0842b40441db5332a5290f941021636b1182761Sol Boucher                            mPreviewSurface.release();
273a0842b40441db5332a5290f941021636b1182761Sol Boucher                            mPreviewSurface = null;
274a0842b40441db5332a5290f941021636b1182761Sol Boucher                        }
275a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mPreviewTexture = null;
276de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        if (mCaptureReader != null) {
277de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            mCaptureReader.close();
278de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            mCaptureReader = null;
279de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        }
280a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mPreviewSize = null;
281a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mPhotoSize = null;
282a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraIndex = 0;
283a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraId = null;
284984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        changeState(AndroidCamera2StateHolder.CAMERA_UNOPENED);
285a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
286a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
287a0842b40441db5332a5290f941021636b1182761Sol Boucher
288a0842b40441db5332a5290f941021636b1182761Sol Boucher                    /*case CameraActions.UNLOCK: {
289a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
290a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
291a0842b40441db5332a5290f941021636b1182761Sol Boucher
292a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.LOCK: {
293a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
294a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }*/
295a0842b40441db5332a5290f941021636b1182761Sol Boucher
296a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.SET_PREVIEW_TEXTURE_ASYNC: {
297a0842b40441db5332a5290f941021636b1182761Sol Boucher                        setPreviewTexture((SurfaceTexture) msg.obj);
298a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
299a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
300a0842b40441db5332a5290f941021636b1182761Sol Boucher
301a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.START_PREVIEW_ASYNC: {
302a0842b40441db5332a5290f941021636b1182761Sol Boucher                        if (mCameraState.getState() !=
303a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                        AndroidCamera2StateHolder.CAMERA_PREVIEW_READY) {
304a0842b40441db5332a5290f941021636b1182761Sol Boucher                            // TODO: Provide better feedback here?
305a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            Log.w(TAG, "Refusing to start preview at inappropriate time");
306a0842b40441db5332a5290f941021636b1182761Sol Boucher                            break;
307a0842b40441db5332a5290f941021636b1182761Sol Boucher                        }
308a0842b40441db5332a5290f941021636b1182761Sol Boucher
309a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        mOneshotPreviewingCallback = (CameraStartPreviewCallback) msg.obj;
310984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
311a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        try {
312de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            mSession.setRepeatingRequest(
313de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                    mPersistentSettings.createRequest(mCamera,
314de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                            CameraDevice.TEMPLATE_PREVIEW, mPreviewSurface),
315bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                                    /*listener*/mCameraResultStateCallback, /*handler*/this);
316a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        } catch(CameraAccessException ex) {
317a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            Log.w(TAG, "Unable to start preview", ex);
318984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
319a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        }
320a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
321a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
322a0842b40441db5332a5290f941021636b1182761Sol Boucher
3232569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher                    // FIXME: We need to tear down the CameraCaptureSession here
3242569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher                    // (and unlock the CameraSettings object from our
3252569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher                    // CameraProxy) so that the preview/photo sizes can be
3262569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher                    // changed again while no preview is running.
327a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.STOP_PREVIEW: {
328a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        if (mCameraState.getState() <
329a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                        AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) {
330a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            Log.w(TAG, "Refusing to stop preview at inappropriate time");
331a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            break;
332a0842b40441db5332a5290f941021636b1182761Sol Boucher                        }
333a0842b40441db5332a5290f941021636b1182761Sol Boucher
334a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        mSession.stopRepeating();
335984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
336a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
337a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
338a0842b40441db5332a5290f941021636b1182761Sol Boucher
339a0842b40441db5332a5290f941021636b1182761Sol Boucher                    /*case CameraActions.SET_PREVIEW_CALLBACK_WITH_BUFFER: {
340a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
341a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
342a0842b40441db5332a5290f941021636b1182761Sol Boucher
343a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.ADD_CALLBACK_BUFFER: {
344a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
345a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
346a0842b40441db5332a5290f941021636b1182761Sol Boucher
347a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.SET_PREVIEW_DISPLAY_ASYNC: {
348a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
349a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
350a0842b40441db5332a5290f941021636b1182761Sol Boucher
351a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.SET_PREVIEW_CALLBACK: {
352a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
353a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
354a0842b40441db5332a5290f941021636b1182761Sol Boucher
355a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.SET_ONE_SHOT_PREVIEW_CALLBACK: {
356a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
357a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
358a0842b40441db5332a5290f941021636b1182761Sol Boucher
359a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.SET_PARAMETERS: {
360a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
361a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
362a0842b40441db5332a5290f941021636b1182761Sol Boucher
363a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.GET_PARAMETERS: {
364a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
365a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
366a0842b40441db5332a5290f941021636b1182761Sol Boucher
367a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.REFRESH_PARAMETERS: {
368a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
369a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }*/
370a0842b40441db5332a5290f941021636b1182761Sol Boucher
371a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.APPLY_SETTINGS: {
372de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        AndroidCamera2Settings settings = (AndroidCamera2Settings) msg.obj;
373a0842b40441db5332a5290f941021636b1182761Sol Boucher                        applyToRequest(settings);
374a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
375a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
376a0842b40441db5332a5290f941021636b1182761Sol Boucher
377a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                    case CameraActions.AUTO_FOCUS: {
3786a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        if (mCancelAfPending > 0) {
3796a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                            Log.v(TAG, "handleMessage - Ignored AUTO_FOCUS because there was "
3806a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                                    + mCancelAfPending + " pending CANCEL_AUTO_FOCUS messages");
3816a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                            break; // ignore AF because a CANCEL_AF is queued after this
3826a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        }
383a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // We only support locking the focus while a preview is being displayed.
384a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // However, it can be requested multiple times in succession; the effect of
385a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // the subsequent invocations is determined by the focus mode defined in the
386a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // provided CameraSettings object. In passive (CONTINUOUS_*) mode, the
387a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // duplicate requests are no-ops and leave the lens locked at its current
388a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // position, but in active (AUTO) mode, they perform another scan and lock
389a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // once that is finished. In any manual focus mode, this call is a no-op,
390a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // and most notably, this is the only case where the callback isn't invoked.
391a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        if (mCameraState.getState() <
392a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                        AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) {
393a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            Log.w(TAG, "Ignoring attempt to autofocus without preview");
394a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            break;
395a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        }
396a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
397a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // The earliest we can reliably tell whether the autofocus has locked in
398984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        // response to our latest request is when our one-time capture progresses.
399a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // However, it will probably take longer than that, so once that happens,
400a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // just start checking the repeating preview requests as they complete.
401a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        final CameraAFCallback callback = (CameraAFCallback) msg.obj;
402bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                        CameraCaptureSession.CaptureCallback deferredCallbackSetter =
403bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                                new CameraCaptureSession.CaptureCallback() {
404984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            private boolean mAlreadyDispatched = false;
405984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
406984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            @Override
407984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            public void onCaptureProgressed(CameraCaptureSession session,
408984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                                            CaptureRequest request,
409984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                                            CaptureResult result) {
410984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                checkAfState(result);
411984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            }
412984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
413a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            @Override
414a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            public void onCaptureCompleted(CameraCaptureSession session,
415a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                                           CaptureRequest request,
416a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                                           TotalCaptureResult result) {
417984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                checkAfState(result);
418984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            }
419984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
420984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            private void checkAfState(CaptureResult result) {
421984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                if (result.get(CaptureResult.CONTROL_AF_STATE) != null &&
422984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                        !mAlreadyDispatched) {
423bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                                    // Now our mCameraResultStateCallback will invoke the callback
424984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    // the first time it finds the focus motor to be locked.
425984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    mAlreadyDispatched = true;
426984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    mOneshotAfCallback = callback;
427984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    // This is an optimization: check the AF state of this frame
428984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    // instead of simply waiting for the next.
429bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                                    mCameraResultStateCallback.monitorControlStates(result);
430984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                }
431a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            }
432a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
433a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            @Override
434a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            public void onCaptureFailed(CameraCaptureSession session,
435a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                                        CaptureRequest request,
436a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                                        CaptureFailure failure) {
437a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                Log.e(TAG, "Focusing failed with reason " + failure.getReason());
438a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                callback.onAutoFocus(false, mCameraProxy);
439a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            }};
440a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
441a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // Send a one-time capture to trigger the camera driver to lock focus.
442984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        changeState(AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED);
443de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        Camera2RequestSettingsSet trigger =
444de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                new Camera2RequestSettingsSet(mPersistentSettings);
445de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        trigger.set(CaptureRequest.CONTROL_AF_TRIGGER,
446a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                CaptureRequest.CONTROL_AF_TRIGGER_START);
447a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        try {
448de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            mSession.capture(
449de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                    trigger.createRequest(mCamera, CameraDevice.TEMPLATE_PREVIEW,
450de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                            mPreviewSurface),
451a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                    /*listener*/deferredCallbackSetter, /*handler*/ this);
452a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        } catch(CameraAccessException ex) {
453a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            Log.e(TAG, "Unable to lock autofocus", ex);
454984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
455a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        }
456a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
457a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
458a0842b40441db5332a5290f941021636b1182761Sol Boucher
459a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.CANCEL_AUTO_FOCUS: {
4606a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        // Ignore all AFs that were already queued until we see
4616a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        // a CANCEL_AUTO_FOCUS_FINISH
4626a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        mCancelAfPending++;
463a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // Why would you want to unlock the lens if it isn't already locked?
464a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        if (mCameraState.getState() <
465a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) {
466a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            Log.w(TAG, "Ignoring attempt to release focus lock without preview");
467a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            break;
468a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        }
469a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
470a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        // Send a one-time capture to trigger the camera driver to resume scanning.
471984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
472de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        Camera2RequestSettingsSet cancel =
473de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                new Camera2RequestSettingsSet(mPersistentSettings);
474de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        cancel.set(CaptureRequest.CONTROL_AF_TRIGGER,
475a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
476a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        try {
477de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            mSession.capture(
478de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                    cancel.createRequest(mCamera, CameraDevice.TEMPLATE_PREVIEW,
479de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                            mPreviewSurface),
480a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                    /*listener*/null, /*handler*/this);
481a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        } catch(CameraAccessException ex) {
482a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            Log.e(TAG, "Unable to cancel autofocus", ex);
483984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            changeState(AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED);
484a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        }
485a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
486a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
487a0842b40441db5332a5290f941021636b1182761Sol Boucher
4886a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                    case CameraActions.CANCEL_AUTO_FOCUS_FINISH: {
4896a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        // Stop ignoring AUTO_FOCUS messages unless there are additional
4906a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        // CANCEL_AUTO_FOCUSes that were added
4916a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        mCancelAfPending--;
4926a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        break;
4936a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                    }
4946a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin
495a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK: {
496a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        mPassiveAfCallback = (CameraAFMoveCallback) msg.obj;
497a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
498a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
499a0842b40441db5332a5290f941021636b1182761Sol Boucher
500a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                    /*case CameraActions.SET_ZOOM_CHANGE_LISTENER: {
501a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
502a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
503a0842b40441db5332a5290f941021636b1182761Sol Boucher
504a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.SET_FACE_DETECTION_LISTENER: {
505a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
506a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
507a0842b40441db5332a5290f941021636b1182761Sol Boucher
508a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.START_FACE_DETECTION: {
509a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
510a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
511a0842b40441db5332a5290f941021636b1182761Sol Boucher
512a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.STOP_FACE_DETECTION: {
513a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
514a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
515a0842b40441db5332a5290f941021636b1182761Sol Boucher
516a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.SET_ERROR_CALLBACK: {
517a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
518a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
519a0842b40441db5332a5290f941021636b1182761Sol Boucher
520a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.ENABLE_SHUTTER_SOUND: {
521a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
522de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    }*/
523a0842b40441db5332a5290f941021636b1182761Sol Boucher
524a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.SET_DISPLAY_ORIENTATION: {
525de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        // Only set the JPEG capture orientation if requested to do so; otherwise,
52625ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                        // capture in the sensor's physical orientation. (e.g., JPEG rotation is
52725ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                        // necessary in auto-rotate mode.
528de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        mPersistentSettings.set(CaptureRequest.JPEG_ORIENTATION, msg.arg2 > 0 ?
529de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                mCameraProxy.getCharacteristics().getJpegOrientation(msg.arg1) : 0);
530a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
531a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
532a0842b40441db5332a5290f941021636b1182761Sol Boucher
53325ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                    case CameraActions.SET_JPEG_ORIENTATION: {
53425ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                        mPersistentSettings.set(CaptureRequest.JPEG_ORIENTATION, msg.arg1);
53525ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                        break;
53625ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                    }
53725ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu
538a0842b40441db5332a5290f941021636b1182761Sol Boucher                    case CameraActions.CAPTURE_PHOTO: {
539de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        if (mCameraState.getState() <
540de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                        AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) {
541de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            Log.e(TAG, "Photos may only be taken when a preview is active");
542de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            break;
543de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        }
544de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        if (mCameraState.getState() !=
545de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED) {
546de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            Log.w(TAG, "Taking a (likely blurry) photo without the lens locked");
547de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        }
548de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
549de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        final CaptureAvailableListener listener =
550de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                (CaptureAvailableListener) msg.obj;
551984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        if (mLegacyDevice ||
552984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                (mCurrentAeState == CaptureResult.CONTROL_AE_STATE_CONVERGED &&
553984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                !mPersistentSettings.matches(CaptureRequest.CONTROL_AE_MODE,
554984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                        CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH) &&
555984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                !mPersistentSettings.matches(CaptureRequest.FLASH_MODE,
556984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                        CaptureRequest.FLASH_MODE_SINGLE)))
557984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                {
558984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            // Legacy devices don't support the precapture state keys and instead
559984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            // perform autoexposure convergence automatically upon capture.
560984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
561984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            // On other devices, as long as it has already converged, it determined
562984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            // that flash was not required, and we're not going to invalidate the
563984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            // current exposure levels by forcing the force on, we can save
564984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            // significant capture time by not forcing a recalculation.
565984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            Log.i(TAG, "Skipping pre-capture autoexposure convergence");
566de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            mCaptureReader.setOnImageAvailableListener(listener, /*handler*/this);
567de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            try {
568de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                mSession.capture(
569de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                        mPersistentSettings.createRequest(mCamera,
570de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                                CameraDevice.TEMPLATE_STILL_CAPTURE,
571de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                                mCaptureReader.getSurface()),
572de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                        listener, /*handler*/this);
573de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            } catch (CameraAccessException ex) {
574984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                Log.e(TAG, "Unable to initiate immediate capture", ex);
575de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            }
576de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        } else {
577984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            // We need to let AE converge before capturing. Once our one-time
578984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            // trigger capture has made it into the pipeline, we'll start checking
579984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            // for the completion of that convergence, capturing when that happens.
580984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            Log.i(TAG, "Forcing pre-capture autoexposure convergence");
581bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                            CameraCaptureSession.CaptureCallback deferredCallbackSetter =
582bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                                    new CameraCaptureSession.CaptureCallback() {
583984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                private boolean mAlreadyDispatched = false;
584984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
585984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                @Override
586984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                public void onCaptureProgressed(CameraCaptureSession session,
587984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                                                CaptureRequest request,
588984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                                                CaptureResult result) {
589984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    checkAeState(result);
590984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                }
591984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
592de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                @Override
593de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                public void onCaptureCompleted(CameraCaptureSession session,
594de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                                               CaptureRequest request,
595de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                                               TotalCaptureResult result) {
596984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    checkAeState(result);
597984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                }
598984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
599984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                private void checkAeState(CaptureResult result) {
600984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    if (result.get(CaptureResult.CONTROL_AE_STATE) != null &&
601984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                            !mAlreadyDispatched) {
602bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                                        // Now our mCameraResultStateCallback will invoke the
603984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                        // callback once the autoexposure routine has converged.
604984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                        mAlreadyDispatched = true;
605984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                        mOneshotCaptureCallback = listener;
606984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                        // This is an optimization: check the AE state of this frame
607984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                        // instead of simply waiting for the next.
608bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                                        mCameraResultStateCallback.monitorControlStates(result);
609984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    }
610de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                }
611de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
612de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                @Override
613de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                public void onCaptureFailed(CameraCaptureSession session,
614de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                                            CaptureRequest request,
615de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                                            CaptureFailure failure) {
616de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                    Log.e(TAG, "Autoexposure and capture failed with reason " +
617de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                            failure.getReason());
618de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                    // TODO: Make an error callback?
619de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                }};
620de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
621de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            // Set a one-time capture to trigger the camera driver's autoexposure:
622de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            Camera2RequestSettingsSet expose =
623de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                    new Camera2RequestSettingsSet(mPersistentSettings);
624de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            expose.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
625de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                    CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
626de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            try {
627de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                mSession.capture(
628de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                        expose.createRequest(mCamera, CameraDevice.TEMPLATE_PREVIEW,
629de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                                mPreviewSurface),
630de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                        /*listener*/deferredCallbackSetter, /*handler*/this);
631de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            } catch (CameraAccessException ex) {
632de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                Log.e(TAG, "Unable to run autoexposure and perform capture", ex);
633de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            }
634de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        }
635a0842b40441db5332a5290f941021636b1182761Sol Boucher                        break;
636de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    }
637a0842b40441db5332a5290f941021636b1182761Sol Boucher
638a0842b40441db5332a5290f941021636b1182761Sol Boucher                    default: {
639a0842b40441db5332a5290f941021636b1182761Sol Boucher                        // TODO: Rephrase once everything has been implemented
640a0842b40441db5332a5290f941021636b1182761Sol Boucher                        throw new RuntimeException("Unimplemented CameraProxy message=" + msg.what);
641a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
642a0842b40441db5332a5290f941021636b1182761Sol Boucher                }
643a0842b40441db5332a5290f941021636b1182761Sol Boucher            } catch (final Exception ex) {
644733ca8dfa76ac34d1f9caff8798d01a4a8f44002Senpo Hu                if (cameraAction != CameraActions.RELEASE && mCamera != null) {
645a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                    // TODO: Handle this better
646a0842b40441db5332a5290f941021636b1182761Sol Boucher                    mCamera.close();
647a0842b40441db5332a5290f941021636b1182761Sol Boucher                    mCamera = null;
648a0842b40441db5332a5290f941021636b1182761Sol Boucher                } else if (mCamera == null) {
649733ca8dfa76ac34d1f9caff8798d01a4a8f44002Senpo Hu                    if (cameraAction == CameraActions.OPEN_CAMERA) {
650a0842b40441db5332a5290f941021636b1182761Sol Boucher                        if (mOpenCallback != null) {
651a0842b40441db5332a5290f941021636b1182761Sol Boucher                            mOpenCallback.onDeviceOpenFailure(mCameraIndex,
652a0842b40441db5332a5290f941021636b1182761Sol Boucher                                    generateHistoryString(mCameraIndex));
653a0842b40441db5332a5290f941021636b1182761Sol Boucher                        }
654a0842b40441db5332a5290f941021636b1182761Sol Boucher                    } else {
655a0842b40441db5332a5290f941021636b1182761Sol Boucher                        Log.w(TAG, "Cannot handle message " + msg.what + ", mCamera is null");
656a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
657a0842b40441db5332a5290f941021636b1182761Sol Boucher                    return;
658a0842b40441db5332a5290f941021636b1182761Sol Boucher                }
659a0842b40441db5332a5290f941021636b1182761Sol Boucher
660a0842b40441db5332a5290f941021636b1182761Sol Boucher                if (ex instanceof RuntimeException) {
661733ca8dfa76ac34d1f9caff8798d01a4a8f44002Senpo Hu                    String commandHistory = generateHistoryString(Integer.parseInt(mCameraId));
662733ca8dfa76ac34d1f9caff8798d01a4a8f44002Senpo Hu                    mExceptionHandler.onCameraException((RuntimeException) ex, commandHistory,
663733ca8dfa76ac34d1f9caff8798d01a4a8f44002Senpo Hu                            cameraAction, mCameraState.getState());
664a0842b40441db5332a5290f941021636b1182761Sol Boucher                }
6656a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin            } finally {
6666a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                WaitDoneBundle.unblockSyncWaiters(msg);
667a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
668a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
669a0842b40441db5332a5290f941021636b1182761Sol Boucher
670a0842b40441db5332a5290f941021636b1182761Sol Boucher        public CameraSettings buildSettings(AndroidCamera2Capabilities caps) {
671de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            try {
672de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                return new AndroidCamera2Settings(mCamera, CameraDevice.TEMPLATE_PREVIEW,
673de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        mActiveArray, mPreviewSize, mPhotoSize);
674de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            } catch (CameraAccessException ex) {
675de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                Log.e(TAG, "Unable to query camera device to build settings representation");
676de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                return null;
677de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            }
678a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
679a0842b40441db5332a5290f941021636b1182761Sol Boucher
680a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        /**
681a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher         * Simply propagates settings from provided {@link CameraSettings}
682a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher         * object to our {@link CaptureRequest.Builder} for use in captures.
683a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher         * <p>Most conversions to match the API 2 formats are performed by
684a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher         * {@link AndroidCamera2Capabilities.IntegralStringifier}; otherwise
685a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher         * any final adjustments are done here before updating the builder.</p>
686a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher         *
687a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher         * @param settings The new/updated settings
688a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher         */
689de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        private void applyToRequest(AndroidCamera2Settings settings) {
690a0842b40441db5332a5290f941021636b1182761Sol Boucher            // TODO: If invoked when in PREVIEW_READY state, a new preview size will not take effect
691de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
692de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            mPersistentSettings.union(settings.getRequestSettings());
693a0842b40441db5332a5290f941021636b1182761Sol Boucher            mPreviewSize = settings.getCurrentPreviewSize();
694a0842b40441db5332a5290f941021636b1182761Sol Boucher            mPhotoSize = settings.getCurrentPhotoSize();
695a0842b40441db5332a5290f941021636b1182761Sol Boucher
696a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            if (mCameraState.getState() >= AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) {
697a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                // If we're already previewing, reflect most settings immediately
698a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                try {
699de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mSession.setRepeatingRequest(
700de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            mPersistentSettings.createRequest(mCamera,
701de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                    CameraDevice.TEMPLATE_PREVIEW, mPreviewSurface),
702bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                            /*listener*/mCameraResultStateCallback, /*handler*/this);
703a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                } catch (CameraAccessException ex) {
704a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                    Log.e(TAG, "Failed to apply updated request settings", ex);
705a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                }
706a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            } else if (mCameraState.getState() < AndroidCamera2StateHolder.CAMERA_PREVIEW_READY) {
707a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                // If we're already ready to preview, this doesn't regress our state
708984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                changeState(AndroidCamera2StateHolder.CAMERA_CONFIGURED);
709a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
710a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
711a0842b40441db5332a5290f941021636b1182761Sol Boucher
712a0842b40441db5332a5290f941021636b1182761Sol Boucher        private void setPreviewTexture(SurfaceTexture surfaceTexture) {
713a0842b40441db5332a5290f941021636b1182761Sol Boucher            // TODO: Must be called after providing a .*Settings populated with sizes
714a0842b40441db5332a5290f941021636b1182761Sol Boucher            // TODO: We don't technically offer a selection of sizes tailored to SurfaceTextures!
715a0842b40441db5332a5290f941021636b1182761Sol Boucher
716a0842b40441db5332a5290f941021636b1182761Sol Boucher            // TODO: Handle this error condition with a callback or exception
717a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            if (mCameraState.getState() < AndroidCamera2StateHolder.CAMERA_CONFIGURED) {
718a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                Log.w(TAG, "Ignoring texture setting at inappropriate time");
719a0842b40441db5332a5290f941021636b1182761Sol Boucher                return;
720a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
721a0842b40441db5332a5290f941021636b1182761Sol Boucher
722a0842b40441db5332a5290f941021636b1182761Sol Boucher            // Avoid initializing another capture session unless we absolutely have to
723a0842b40441db5332a5290f941021636b1182761Sol Boucher            if (surfaceTexture == mPreviewTexture) {
724a0842b40441db5332a5290f941021636b1182761Sol Boucher                Log.i(TAG, "Optimizing out redundant preview texture setting");
725a0842b40441db5332a5290f941021636b1182761Sol Boucher                return;
726a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
727a0842b40441db5332a5290f941021636b1182761Sol Boucher
728a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            if (mSession != null) {
729a0842b40441db5332a5290f941021636b1182761Sol Boucher                closePreviewSession();
730a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
731a0842b40441db5332a5290f941021636b1182761Sol Boucher
732a0842b40441db5332a5290f941021636b1182761Sol Boucher            mPreviewTexture = surfaceTexture;
733a0842b40441db5332a5290f941021636b1182761Sol Boucher            surfaceTexture.setDefaultBufferSize(mPreviewSize.width(), mPreviewSize.height());
734a0842b40441db5332a5290f941021636b1182761Sol Boucher
735a0842b40441db5332a5290f941021636b1182761Sol Boucher            if (mPreviewSurface != null) {
736a0842b40441db5332a5290f941021636b1182761Sol Boucher                mPreviewSurface.release();
737a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
738a0842b40441db5332a5290f941021636b1182761Sol Boucher            mPreviewSurface = new Surface(surfaceTexture);
739de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
740de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            if (mCaptureReader != null) {
741de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                mCaptureReader.close();
742de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            }
743de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            mCaptureReader = ImageReader.newInstance(
744de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    mPhotoSize.width(), mPhotoSize.height(), ImageFormat.JPEG, 1);
745a0842b40441db5332a5290f941021636b1182761Sol Boucher
746a0842b40441db5332a5290f941021636b1182761Sol Boucher            try {
747de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                mCamera.createCaptureSession(
748de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        Arrays.asList(mPreviewSurface, mCaptureReader.getSurface()),
749bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                        mCameraPreviewStateCallback, this);
750a0842b40441db5332a5290f941021636b1182761Sol Boucher            } catch (CameraAccessException ex) {
751a0842b40441db5332a5290f941021636b1182761Sol Boucher                Log.e(TAG, "Failed to create camera capture session", ex);
752a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
753a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
754a0842b40441db5332a5290f941021636b1182761Sol Boucher
755a0842b40441db5332a5290f941021636b1182761Sol Boucher        private void closePreviewSession() {
756a0842b40441db5332a5290f941021636b1182761Sol Boucher            try {
757a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                mSession.abortCaptures();
758a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                mSession = null;
759a0842b40441db5332a5290f941021636b1182761Sol Boucher            } catch (CameraAccessException ex) {
760a0842b40441db5332a5290f941021636b1182761Sol Boucher                Log.e(TAG, "Failed to close existing camera capture session", ex);
761a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
762984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            changeState(AndroidCamera2StateHolder.CAMERA_CONFIGURED);
763984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher        }
764984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
765984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher        private void changeState(int newState) {
766984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            if (mCameraState.getState() != newState) {
767984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                mCameraState.setState(newState);
768984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                if (newState < AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) {
769984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                    mCurrentAeState = CaptureResult.CONTROL_AE_STATE_INACTIVE;
770bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                    mCameraResultStateCallback.resetState();
771984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                }
772984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            }
773a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
774a0842b40441db5332a5290f941021636b1182761Sol Boucher
775bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala        // This callback monitors our connection to and disconnection from camera devices.
776bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala        private CameraDevice.StateCallback mCameraDeviceStateCallback =
777bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                new CameraDevice.StateCallback() {
778a0842b40441db5332a5290f941021636b1182761Sol Boucher            @Override
779a0842b40441db5332a5290f941021636b1182761Sol Boucher            public void onOpened(CameraDevice camera) {
780a0842b40441db5332a5290f941021636b1182761Sol Boucher                mCamera = camera;
781a0842b40441db5332a5290f941021636b1182761Sol Boucher                if (mOpenCallback != null) {
782a0842b40441db5332a5290f941021636b1182761Sol Boucher                    try {
783a0842b40441db5332a5290f941021636b1182761Sol Boucher                        CameraCharacteristics props =
784a0842b40441db5332a5290f941021636b1182761Sol Boucher                                mCameraManager.getCameraCharacteristics(mCameraId);
7852d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        CameraDeviceInfo.Characteristics characteristics =
7862d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                getCameraDeviceInfo().getCharacteristics(mCameraIndex);
7872d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraProxy = new AndroidCamera2ProxyImpl(AndroidCamera2AgentImpl.this,
7882d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                mCameraIndex, mCamera, characteristics, props);
789de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        mPersistentSettings = new Camera2RequestSettingsSet();
790a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        mActiveArray =
791a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                props.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
792de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        mLegacyDevice =
793de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                props.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) ==
794de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                        CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
795984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        changeState(AndroidCamera2StateHolder.CAMERA_UNCONFIGURED);
796a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mOpenCallback.onCameraOpened(mCameraProxy);
797a0842b40441db5332a5290f941021636b1182761Sol Boucher                    } catch (CameraAccessException ex) {
798a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mOpenCallback.onDeviceOpenFailure(mCameraIndex,
799a0842b40441db5332a5290f941021636b1182761Sol Boucher                                generateHistoryString(mCameraIndex));
800a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
801a0842b40441db5332a5290f941021636b1182761Sol Boucher                }
802a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
803a0842b40441db5332a5290f941021636b1182761Sol Boucher
804a0842b40441db5332a5290f941021636b1182761Sol Boucher            @Override
805a0842b40441db5332a5290f941021636b1182761Sol Boucher            public void onDisconnected(CameraDevice camera) {
806a0842b40441db5332a5290f941021636b1182761Sol Boucher                Log.w(TAG, "Camera device '" + mCameraIndex + "' was disconnected");
807a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
808a0842b40441db5332a5290f941021636b1182761Sol Boucher
809a0842b40441db5332a5290f941021636b1182761Sol Boucher            @Override
810a0842b40441db5332a5290f941021636b1182761Sol Boucher            public void onError(CameraDevice camera, int error) {
811a0842b40441db5332a5290f941021636b1182761Sol Boucher                Log.e(TAG, "Camera device '" + mCameraIndex + "' encountered error code '" +
812a0842b40441db5332a5290f941021636b1182761Sol Boucher                        error + '\'');
813a0842b40441db5332a5290f941021636b1182761Sol Boucher                if (mOpenCallback != null) {
814a0842b40441db5332a5290f941021636b1182761Sol Boucher                    mOpenCallback.onDeviceOpenFailure(mCameraIndex,
815a0842b40441db5332a5290f941021636b1182761Sol Boucher                            generateHistoryString(mCameraIndex));
816a0842b40441db5332a5290f941021636b1182761Sol Boucher                }
817a0842b40441db5332a5290f941021636b1182761Sol Boucher            }};
818a0842b40441db5332a5290f941021636b1182761Sol Boucher
819bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala        // This callback monitors our camera session (i.e. our transition into and out of preview).
820bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala        private CameraCaptureSession.StateCallback mCameraPreviewStateCallback =
821bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                new CameraCaptureSession.StateCallback() {
822a0842b40441db5332a5290f941021636b1182761Sol Boucher            @Override
823a0842b40441db5332a5290f941021636b1182761Sol Boucher            public void onConfigured(CameraCaptureSession session) {
824a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                mSession = session;
825984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
826a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
827a0842b40441db5332a5290f941021636b1182761Sol Boucher
828a0842b40441db5332a5290f941021636b1182761Sol Boucher            @Override
829a0842b40441db5332a5290f941021636b1182761Sol Boucher            public void onConfigureFailed(CameraCaptureSession session) {
830a0842b40441db5332a5290f941021636b1182761Sol Boucher                // TODO: Invoke a callback
831a0842b40441db5332a5290f941021636b1182761Sol Boucher                Log.e(TAG, "Failed to configure the camera for capture");
832a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            }
833a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
834a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            @Override
835a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            public void onActive(CameraCaptureSession session) {
836a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                if (mOneshotPreviewingCallback != null) {
837a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                    // The session is up and processing preview requests. Inform the caller.
838a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                    mOneshotPreviewingCallback.onPreviewStarted();
839a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                    mOneshotPreviewingCallback = null;
840a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                }
841a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            }};
842a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
843bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala        private abstract class CameraResultStateCallback
844bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                extends CameraCaptureSession.CaptureCallback {
845984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            public abstract void monitorControlStates(CaptureResult result);
846984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
847984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            public abstract void resetState();
848984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher        }
849984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
850bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala        // This callback monitors requested captures and notifies any relevant callbacks.
851bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala        private CameraResultStateCallback mCameraResultStateCallback =
852bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                new CameraResultStateCallback() {
853a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            private int mLastAfState = -1;
854984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            private long mLastAfFrameNumber = -1;
855984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            private long mLastAeFrameNumber = -1;
856984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
857984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            @Override
858984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
859984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                            CaptureResult result) {
860984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                monitorControlStates(result);
861984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            }
862a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
863a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            @Override
864a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
865a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                           TotalCaptureResult result) {
866984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                monitorControlStates(result);
867984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            }
868984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
869984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            @Override
870984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            public void monitorControlStates(CaptureResult result) {
871a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                Integer afStateMaybe = result.get(CaptureResult.CONTROL_AF_STATE);
872a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                if (afStateMaybe != null) {
873a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                    int afState = afStateMaybe;
874984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                    // Since we handle both partial and total results for multiple frames here, we
875984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                    // might get the final callbacks for an earlier frame after receiving one or
876984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                    // more that correspond to the next one. To prevent our data from oscillating,
877984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                    // we never consider AF states that are older than the last one we've seen.
878984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                    if (result.getFrameNumber() > mLastAfFrameNumber) {
879984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        boolean afStateChanged = afState != mLastAfState;
880a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        mLastAfState = afState;
881984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        mLastAfFrameNumber = result.getFrameNumber();
882984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
883984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        switch (afState) {
884984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
885984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
886984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: {
887984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                if (afStateChanged && mPassiveAfCallback != null) {
888984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    // A CameraAFMoveCallback is attached. If we just started to
889984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    // scan, the motor is moving; otherwise, it has settled.
890984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    mPassiveAfCallback.onAutoFocusMoving(
891984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                            afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN,
892984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                            mCameraProxy);
893984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                }
894984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                break;
895a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            }
896a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
897984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
898984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: {
8997d71703202c2fba36653293eba2772745db46c00Sol Boucher                                // This check must be made regardless of whether the focus state has
9007d71703202c2fba36653293eba2772745db46c00Sol Boucher                                // changed recently to avoid infinite waiting during autoFocus()
9017d71703202c2fba36653293eba2772745db46c00Sol Boucher                                // when the algorithm has already either converged or failed to.
902984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                if (mOneshotAfCallback != null) {
903984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    // A call to autoFocus() was just made to request a focus lock.
904984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    // Notify the caller that the lens is now indefinitely fixed,
905984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    // and report whether the image we're stuck with is in focus.
906984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    mOneshotAfCallback.onAutoFocus(
907984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                            afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED,
908984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                            mCameraProxy);
909984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    mOneshotAfCallback = null;
910984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                }
911984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                break;
912a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                            }
913a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                        }
914a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                    }
915a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                }
916de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
917de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                Integer aeStateMaybe = result.get(CaptureResult.CONTROL_AE_STATE);
918de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                if (aeStateMaybe != null) {
919de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    int aeState = aeStateMaybe;
920984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                    // Since we handle both partial and total results for multiple frames here, we
921984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                    // might get the final callbacks for an earlier frame after receiving one or
922984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                    // more that correspond to the next one. To prevent our data from oscillating,
923984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                    // we never consider AE states that are older than the last one we've seen.
9247d71703202c2fba36653293eba2772745db46c00Sol Boucher                    if (result.getFrameNumber() > mLastAeFrameNumber) {
925984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        mCurrentAeState = aeStateMaybe;
926984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        mLastAeFrameNumber = result.getFrameNumber();
927984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
928984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                        switch (aeState) {
929984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            case CaptureResult.CONTROL_AE_STATE_CONVERGED:
930984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            case CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED:
931984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                            case CaptureResult.CONTROL_AE_STATE_LOCKED: {
9327d71703202c2fba36653293eba2772745db46c00Sol Boucher                                // This check must be made regardless of whether the exposure state
9337d71703202c2fba36653293eba2772745db46c00Sol Boucher                                // has changed recently to avoid infinite waiting during
9347d71703202c2fba36653293eba2772745db46c00Sol Boucher                                // takePicture() when the algorithm has already converged.
935984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                if (mOneshotCaptureCallback != null) {
936984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    // A call to takePicture() was just made, and autoexposure
937984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    // converged so it's time to initiate the capture!
938984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    mCaptureReader.setOnImageAvailableListener(
939de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                            /*listener*/mOneshotCaptureCallback,
940de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                            /*handler*/Camera2Handler.this);
941984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    try {
942984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                        mSession.capture(
943984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                                mPersistentSettings.createRequest(mCamera,
944984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                                        CameraDevice.TEMPLATE_STILL_CAPTURE,
945984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                                        mCaptureReader.getSurface()),
946bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala                                                /*callback*/mOneshotCaptureCallback,
947984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                                /*handler*/Camera2Handler.this);
948984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    } catch (CameraAccessException ex) {
949984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                        Log.e(TAG, "Unable to initiate capture", ex);
950984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    } finally {
951984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                        mOneshotCaptureCallback = null;
952984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                    }
953de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                }
954984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                                break;
955de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            }
956de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        }
957de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    }
958de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
959a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            }
960a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
961a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            @Override
962984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            public void resetState() {
963984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                mLastAfState = -1;
964984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                mLastAfFrameNumber = -1;
965984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher                mLastAeFrameNumber = -1;
966984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            }
967984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher
968984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher            @Override
969a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher            public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
970a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                                        CaptureFailure failure) {
971a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher                Log.e(TAG, "Capture attempt failed with reason " + failure.getReason());
972a0842b40441db5332a5290f941021636b1182761Sol Boucher            }};
973a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
974a0842b40441db5332a5290f941021636b1182761Sol Boucher
975a0842b40441db5332a5290f941021636b1182761Sol Boucher    private class AndroidCamera2ProxyImpl extends CameraAgent.CameraProxy {
9762d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        private final AndroidCamera2AgentImpl mCameraAgent;
977a0842b40441db5332a5290f941021636b1182761Sol Boucher        private final int mCameraIndex;
978a0842b40441db5332a5290f941021636b1182761Sol Boucher        private final CameraDevice mCamera;
979a0842b40441db5332a5290f941021636b1182761Sol Boucher        private final CameraDeviceInfo.Characteristics mCharacteristics;
980a0842b40441db5332a5290f941021636b1182761Sol Boucher        private final AndroidCamera2Capabilities mCapabilities;
98180cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher        private CameraSettings mLastSettings;
982415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher        private boolean mShutterSoundEnabled;
983a0842b40441db5332a5290f941021636b1182761Sol Boucher
9842d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        public AndroidCamera2ProxyImpl(
9852d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                AndroidCamera2AgentImpl agent,
9862d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                int cameraIndex,
9872d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                CameraDevice camera,
988a0842b40441db5332a5290f941021636b1182761Sol Boucher                CameraDeviceInfo.Characteristics characteristics,
989a0842b40441db5332a5290f941021636b1182761Sol Boucher                CameraCharacteristics properties) {
9902d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            mCameraAgent = agent;
991a0842b40441db5332a5290f941021636b1182761Sol Boucher            mCameraIndex = cameraIndex;
992a0842b40441db5332a5290f941021636b1182761Sol Boucher            mCamera = camera;
993a0842b40441db5332a5290f941021636b1182761Sol Boucher            mCharacteristics = characteristics;
994a0842b40441db5332a5290f941021636b1182761Sol Boucher            mCapabilities = new AndroidCamera2Capabilities(properties);
99580cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher            mLastSettings = null;
996415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher            mShutterSoundEnabled = true;
997a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
998a0842b40441db5332a5290f941021636b1182761Sol Boucher
999a0842b40441db5332a5290f941021636b1182761Sol Boucher        // TODO: Implement
1000a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1001a0842b40441db5332a5290f941021636b1182761Sol Boucher        public android.hardware.Camera getCamera() { return null; }
1002a0842b40441db5332a5290f941021636b1182761Sol Boucher
1003a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1004a0842b40441db5332a5290f941021636b1182761Sol Boucher        public int getCameraId() {
1005a0842b40441db5332a5290f941021636b1182761Sol Boucher            return mCameraIndex;
1006a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1007a0842b40441db5332a5290f941021636b1182761Sol Boucher
1008a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1009a0842b40441db5332a5290f941021636b1182761Sol Boucher        public CameraDeviceInfo.Characteristics getCharacteristics() {
1010a0842b40441db5332a5290f941021636b1182761Sol Boucher            return mCharacteristics;
1011a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1012a0842b40441db5332a5290f941021636b1182761Sol Boucher
1013a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1014a0842b40441db5332a5290f941021636b1182761Sol Boucher        public CameraCapabilities getCapabilities() {
1015a0842b40441db5332a5290f941021636b1182761Sol Boucher            return mCapabilities;
1016a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1017a0842b40441db5332a5290f941021636b1182761Sol Boucher
10182d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        public CameraAgent getAgent() {
10192d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            return mCameraAgent;
10202d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        }
10212d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
1022a0842b40441db5332a5290f941021636b1182761Sol Boucher        private AndroidCamera2Capabilities getSpecializedCapabilities() {
1023a0842b40441db5332a5290f941021636b1182761Sol Boucher            return mCapabilities;
1024a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1025a0842b40441db5332a5290f941021636b1182761Sol Boucher
10262569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // FIXME: Unlock the sizes in stopPreview(), as per the corresponding
10272569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // explanation on the STOP_PREVIEW case in the handler.
10282569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        @Override
10292569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        public void setPreviewTexture(SurfaceTexture surfaceTexture) {
10302569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            // Once the Surface has been selected, we configure the session and
10312569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            // are no longer able to change the sizes.
10322569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            getSettings().setSizesLocked(true);
10332569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            super.setPreviewTexture(surfaceTexture);
10342569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        }
10352569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher
10362569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // FIXME: Unlock the sizes in stopPreview(), as per the corresponding
10372569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        // explanation on the STOP_PREVIEW case in the handler.
10382569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        @Override
10392569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        public void setPreviewTextureSync(SurfaceTexture surfaceTexture) {
10402569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            // Once the Surface has been selected, we configure the session and
10412569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            // are no longer able to change the sizes.
10422569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            getSettings().setSizesLocked(true);
10432569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher            super.setPreviewTexture(surfaceTexture);
10442569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher        }
10452569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher
1046a0842b40441db5332a5290f941021636b1182761Sol Boucher        // TODO: Implement
1047a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1048a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void setPreviewDataCallback(Handler handler, CameraPreviewDataCallback cb) {}
1049a0842b40441db5332a5290f941021636b1182761Sol Boucher
1050a0842b40441db5332a5290f941021636b1182761Sol Boucher        // TODO: Implement
1051a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1052a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void setOneShotPreviewCallback(Handler handler, CameraPreviewDataCallback cb) {}
1053a0842b40441db5332a5290f941021636b1182761Sol Boucher
1054a0842b40441db5332a5290f941021636b1182761Sol Boucher        // TODO: Implement
1055a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1056a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void setPreviewDataCallbackWithBuffer(Handler handler, CameraPreviewDataCallback cb)
1057a0842b40441db5332a5290f941021636b1182761Sol Boucher                {}
1058a0842b40441db5332a5290f941021636b1182761Sol Boucher
105950f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher        // TODO: Implement
106050f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher        public void addCallbackBuffer(final byte[] callbackBuffer) {}
106150f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher
1062a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1063a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        public void autoFocus(final Handler handler, final CameraAFCallback cb) {
10642d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
10652d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mDispatchThread.runJob(new Runnable() {
10662d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
10672d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
10682d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        CameraAFCallback cbForward = null;
10692d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        if (cb != null) {
10702d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                            cbForward = new CameraAFCallback() {
10712d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                @Override
10722d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                public void onAutoFocus(final boolean focused,
10732d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                                        final CameraProxy camera) {
10742d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                    handler.post(new Runnable() {
10752d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        @Override
10762d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        public void run() {
10772d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                            cb.onAutoFocus(focused, camera);
10782d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        }
10792d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                    });
10802d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                }
10812d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                            };
10822d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        }
1083a0842b40441db5332a5290f941021636b1182761Sol Boucher
10842d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraState.waitForStates(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE |
10852d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED);
10862d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraHandler.obtainMessage(CameraActions.AUTO_FOCUS, cbForward)
10872d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
10882d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
10892d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                });
10902d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (RuntimeException ex) {
10912d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mCameraAgent.getCameraExceptionHandler().onDispatchThreadException(ex);
10922d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
1093a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        }
1094a0842b40441db5332a5290f941021636b1182761Sol Boucher
1095a0842b40441db5332a5290f941021636b1182761Sol Boucher        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
1096a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1097a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        public void setAutoFocusMoveCallback(final Handler handler, final CameraAFMoveCallback cb) {
10982d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
10992d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mDispatchThread.runJob(new Runnable() {
11002d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
11012d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
11022d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        CameraAFMoveCallback cbForward = null;
11032d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        if (cb != null) {
11042d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                            cbForward = new CameraAFMoveCallback() {
11052d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                @Override
11062d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                public void onAutoFocusMoving(final boolean moving,
11072d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                                              final CameraProxy camera) {
11082d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                    handler.post(new Runnable() {
11092d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        @Override
11102d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        public void run() {
11112d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                            cb.onAutoFocusMoving(moving, camera);
11122d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        }
11132d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                    });
11142d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                }
11152d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                            };
11162d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        }
1117a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
11182d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraHandler.obtainMessage(CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK,
11192d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                cbForward).sendToTarget();
11202d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
11212d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                });
11222d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (RuntimeException ex) {
11232d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mCameraAgent.getCameraExceptionHandler().onDispatchThreadException(ex);
11242d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
1125a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        }
1126a0842b40441db5332a5290f941021636b1182761Sol Boucher
1127a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1128de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        public void takePicture(final Handler handler,
1129de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                final CameraShutterCallback shutter,
1130a0842b40441db5332a5290f941021636b1182761Sol Boucher                                CameraPictureCallback raw,
1131a0842b40441db5332a5290f941021636b1182761Sol Boucher                                CameraPictureCallback postview,
1132de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                final CameraPictureCallback jpeg) {
1133de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            // TODO: We never call raw or postview
1134de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            final CaptureAvailableListener picListener =
1135de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    new CaptureAvailableListener() {
1136de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                @Override
1137de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
1138171362f843c1e7623f29db1781176f85b1f74815Eino-Ville Talvala                                             long timestamp, long frameNumber) {
1139de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    if (shutter != null) {
1140de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        handler.post(new Runnable() {
1141de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            @Override
1142de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            public void run() {
1143415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher                                if (mShutterSoundEnabled) {
1144415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher                                    mNoisemaker.play(MediaActionSound.SHUTTER_CLICK);
1145415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher                                }
1146de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                shutter.onShutter(AndroidCamera2ProxyImpl.this);
1147de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            }});
1148de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    }
1149de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }
1150a0842b40441db5332a5290f941021636b1182761Sol Boucher
1151de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                @Override
1152de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                public void onImageAvailable(ImageReader reader) {
1153de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    try (Image image = reader.acquireNextImage()) {
1154de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        if (jpeg != null) {
1155de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            ByteBuffer buffer = image.getPlanes()[0].getBuffer();
1156de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            final byte[] pixels = new byte[buffer.remaining()];
1157de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            buffer.get(pixels);
1158de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                            handler.post(new Runnable() {
1159de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                @Override
1160de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                public void run() {
1161de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                    jpeg.onPictureTaken(pixels, AndroidCamera2ProxyImpl.this);
1162de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                }});
1163de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        }
1164de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                    }
1165de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                }};
11662d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
11672d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mDispatchThread.runJob(new Runnable() {
11682d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
11692d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
11702d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        // Wait until PREVIEW_ACTIVE or better
11712d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraState.waitForStates(
11722d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                ~(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE - 1));
11732d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraHandler.obtainMessage(CameraActions.CAPTURE_PHOTO, picListener)
11742d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
11752d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
11762d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                });
11772d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (RuntimeException ex) {
11782d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mCameraAgent.getCameraExceptionHandler().onDispatchThreadException(ex);
11792d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
1180de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        }
1181a0842b40441db5332a5290f941021636b1182761Sol Boucher
1182a0842b40441db5332a5290f941021636b1182761Sol Boucher        // TODO: Implement
1183a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1184a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void setZoomChangeListener(android.hardware.Camera.OnZoomChangeListener listener) {}
1185a0842b40441db5332a5290f941021636b1182761Sol Boucher
1186a0842b40441db5332a5290f941021636b1182761Sol Boucher        // TODO: Implement
1187a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1188a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void setFaceDetectionCallback(Handler handler, CameraFaceDetectionCallback callback)
1189a0842b40441db5332a5290f941021636b1182761Sol Boucher                {}
1190a0842b40441db5332a5290f941021636b1182761Sol Boucher
1191a0842b40441db5332a5290f941021636b1182761Sol Boucher        // TODO: Remove this method override once we handle this message
1192a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1193a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void startFaceDetection() {}
1194a0842b40441db5332a5290f941021636b1182761Sol Boucher
1195a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        // TODO: Remove this method override once we handle this message
1196a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        @Override
1197a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        public void stopFaceDetection() {}
1198a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher
1199a0842b40441db5332a5290f941021636b1182761Sol Boucher        // TODO: Implement
1200a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1201a0842b40441db5332a5290f941021636b1182761Sol Boucher        public void setParameters(android.hardware.Camera.Parameters params) {}
1202a0842b40441db5332a5290f941021636b1182761Sol Boucher
1203a0842b40441db5332a5290f941021636b1182761Sol Boucher        // TODO: Implement
1204a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1205a0842b40441db5332a5290f941021636b1182761Sol Boucher        public android.hardware.Camera.Parameters getParameters() { return null; }
1206a0842b40441db5332a5290f941021636b1182761Sol Boucher
1207a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1208a0842b40441db5332a5290f941021636b1182761Sol Boucher        public CameraSettings getSettings() {
120980cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher            if (mLastSettings == null) {
121080cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher                mLastSettings = mCameraHandler.buildSettings(mCapabilities);
121180cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher            }
121280cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher            return mLastSettings;
1213a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1214a0842b40441db5332a5290f941021636b1182761Sol Boucher
1215a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1216a0842b40441db5332a5290f941021636b1182761Sol Boucher        public boolean applySettings(CameraSettings settings) {
1217de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            if (settings == null) {
1218de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                Log.w(TAG, "null parameters in applySettings()");
1219de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                return false;
1220de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            }
1221de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            if (!(settings instanceof AndroidCamera2Settings)) {
1222de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                Log.e(TAG, "Provided settings not compatible with the backing framework API");
1223de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                return false;
1224de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher            }
1225de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher
1226772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher            // Wait for any state that isn't OPENED
1227772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher            if (applySettingsHelper(settings, ~AndroidCamera2StateHolder.CAMERA_UNOPENED)) {
122880cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher                mLastSettings = settings;
122980cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher                return true;
123080cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher            }
123180cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher            return false;
1232a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1233a0842b40441db5332a5290f941021636b1182761Sol Boucher
1234415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher        @Override
1235415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher        public void enableShutterSound(boolean enable) {
1236415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher            mShutterSoundEnabled = enable;
1237415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher        }
1238415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher
1239a0842b40441db5332a5290f941021636b1182761Sol Boucher        // TODO: Implement
1240a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1241a0842b40441db5332a5290f941021636b1182761Sol Boucher        public String dumpDeviceSettings() { return null; }
1242a0842b40441db5332a5290f941021636b1182761Sol Boucher
1243a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1244a0842b40441db5332a5290f941021636b1182761Sol Boucher        public Handler getCameraHandler() {
1245a0842b40441db5332a5290f941021636b1182761Sol Boucher            return AndroidCamera2AgentImpl.this.getCameraHandler();
1246a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1247a0842b40441db5332a5290f941021636b1182761Sol Boucher
1248a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1249a0842b40441db5332a5290f941021636b1182761Sol Boucher        public DispatchThread getDispatchThread() {
1250a0842b40441db5332a5290f941021636b1182761Sol Boucher            return AndroidCamera2AgentImpl.this.getDispatchThread();
1251a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1252a0842b40441db5332a5290f941021636b1182761Sol Boucher
1253a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1254a0842b40441db5332a5290f941021636b1182761Sol Boucher        public CameraStateHolder getCameraState() {
1255a0842b40441db5332a5290f941021636b1182761Sol Boucher            return mCameraState;
1256a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1257a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
1258a0842b40441db5332a5290f941021636b1182761Sol Boucher
1259a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher    /** A linear state machine: each state entails all the states below it. */
1260a0842b40441db5332a5290f941021636b1182761Sol Boucher    private static class AndroidCamera2StateHolder extends CameraStateHolder {
1261a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        // Usage flow: openCamera() -> applySettings() -> setPreviewTexture() -> startPreview() ->
1262a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        //             autoFocus() -> takePicture()
1263772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher        // States are mutually exclusive, but must be separate bits so that they can be used with
1264772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher        // the StateHolder#waitForStates() and StateHolder#waitToAvoidStates() methods.
1265772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher        // Do not set the state to be a combination of these values!
1266a0842b40441db5332a5290f941021636b1182761Sol Boucher        /* Camera states */
1267a0842b40441db5332a5290f941021636b1182761Sol Boucher        /** No camera device is opened. */
1268772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher        public static final int CAMERA_UNOPENED = 1 << 0;
1269a0842b40441db5332a5290f941021636b1182761Sol Boucher        /** A camera is opened, but no settings have been provided. */
1270772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher        public static final int CAMERA_UNCONFIGURED = 1 << 1;
1271a0842b40441db5332a5290f941021636b1182761Sol Boucher        /** The open camera has been configured by providing it with settings. */
1272772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher        public static final int CAMERA_CONFIGURED = 1 << 2;
1273a0842b40441db5332a5290f941021636b1182761Sol Boucher        /** A capture session is ready to stream a preview, but still has no repeating request. */
1274772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher        public static final int CAMERA_PREVIEW_READY = 1 << 3;
1275a0842b40441db5332a5290f941021636b1182761Sol Boucher        /** A preview is currently being streamed. */
1276772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher        public static final int CAMERA_PREVIEW_ACTIVE = 1 << 4;
1277a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher        /** The lens is locked on a particular region. */
1278772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher        public static final int CAMERA_FOCUS_LOCKED = 1 << 5;
1279a0842b40441db5332a5290f941021636b1182761Sol Boucher
1280a0842b40441db5332a5290f941021636b1182761Sol Boucher        public AndroidCamera2StateHolder() {
1281a0842b40441db5332a5290f941021636b1182761Sol Boucher            this(CAMERA_UNOPENED);
1282a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1283a0842b40441db5332a5290f941021636b1182761Sol Boucher
1284a0842b40441db5332a5290f941021636b1182761Sol Boucher        public AndroidCamera2StateHolder(int state) {
12857e0d39bf7b6e0f0df606e3f6c15f673f70fed3f7Sol Boucher            super(state);
1286a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1287a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
1288a0842b40441db5332a5290f941021636b1182761Sol Boucher
1289a0842b40441db5332a5290f941021636b1182761Sol Boucher    private static class AndroidCamera2DeviceInfo implements CameraDeviceInfo {
1290a0842b40441db5332a5290f941021636b1182761Sol Boucher        private final CameraManager mCameraManager;
1291a0842b40441db5332a5290f941021636b1182761Sol Boucher        private final String[] mCameraIds;
1292a0842b40441db5332a5290f941021636b1182761Sol Boucher        private final int mNumberOfCameras;
1293a0842b40441db5332a5290f941021636b1182761Sol Boucher        private final int mFirstBackCameraId;
1294a0842b40441db5332a5290f941021636b1182761Sol Boucher        private final int mFirstFrontCameraId;
1295a0842b40441db5332a5290f941021636b1182761Sol Boucher
1296a0842b40441db5332a5290f941021636b1182761Sol Boucher        public AndroidCamera2DeviceInfo(CameraManager cameraManager,
1297a0842b40441db5332a5290f941021636b1182761Sol Boucher                                        String[] cameraIds, int numberOfCameras) {
1298a0842b40441db5332a5290f941021636b1182761Sol Boucher            mCameraManager = cameraManager;
1299a0842b40441db5332a5290f941021636b1182761Sol Boucher            mCameraIds = cameraIds;
1300a0842b40441db5332a5290f941021636b1182761Sol Boucher            mNumberOfCameras = numberOfCameras;
1301a0842b40441db5332a5290f941021636b1182761Sol Boucher
1302a0842b40441db5332a5290f941021636b1182761Sol Boucher            int firstBackId = NO_DEVICE;
1303a0842b40441db5332a5290f941021636b1182761Sol Boucher            int firstFrontId = NO_DEVICE;
1304a0842b40441db5332a5290f941021636b1182761Sol Boucher            for (int id = 0; id < cameraIds.length; ++id) {
1305a0842b40441db5332a5290f941021636b1182761Sol Boucher                try {
1306a0842b40441db5332a5290f941021636b1182761Sol Boucher                    int lensDirection = cameraManager.getCameraCharacteristics(cameraIds[id])
1307a0842b40441db5332a5290f941021636b1182761Sol Boucher                            .get(CameraCharacteristics.LENS_FACING);
1308a0842b40441db5332a5290f941021636b1182761Sol Boucher                    if (firstBackId == NO_DEVICE &&
1309a0842b40441db5332a5290f941021636b1182761Sol Boucher                            lensDirection == CameraCharacteristics.LENS_FACING_BACK) {
1310a0842b40441db5332a5290f941021636b1182761Sol Boucher                        firstBackId = id;
1311a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
1312a0842b40441db5332a5290f941021636b1182761Sol Boucher                    if (firstFrontId == NO_DEVICE &&
1313a0842b40441db5332a5290f941021636b1182761Sol Boucher                            lensDirection == CameraCharacteristics.LENS_FACING_FRONT) {
1314a0842b40441db5332a5290f941021636b1182761Sol Boucher                        firstFrontId = id;
1315a0842b40441db5332a5290f941021636b1182761Sol Boucher                    }
1316a0842b40441db5332a5290f941021636b1182761Sol Boucher                } catch (CameraAccessException ex) {
1317a0842b40441db5332a5290f941021636b1182761Sol Boucher                    Log.w(TAG, "Couldn't get characteristics of camera '" + id + "'", ex);
1318a0842b40441db5332a5290f941021636b1182761Sol Boucher                }
1319a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
1320a0842b40441db5332a5290f941021636b1182761Sol Boucher            mFirstBackCameraId = firstBackId;
1321a0842b40441db5332a5290f941021636b1182761Sol Boucher            mFirstFrontCameraId = firstFrontId;
1322a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1323a0842b40441db5332a5290f941021636b1182761Sol Boucher
1324a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1325a0842b40441db5332a5290f941021636b1182761Sol Boucher        public Characteristics getCharacteristics(int cameraId) {
1326a0842b40441db5332a5290f941021636b1182761Sol Boucher            String actualId = mCameraIds[cameraId];
1327a0842b40441db5332a5290f941021636b1182761Sol Boucher            try {
1328a0842b40441db5332a5290f941021636b1182761Sol Boucher                CameraCharacteristics info = mCameraManager.getCameraCharacteristics(actualId);
1329a0842b40441db5332a5290f941021636b1182761Sol Boucher                return new AndroidCharacteristics2(info);
1330a0842b40441db5332a5290f941021636b1182761Sol Boucher            } catch (CameraAccessException ex) {
1331a0842b40441db5332a5290f941021636b1182761Sol Boucher                return null;
1332a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
1333a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1334a0842b40441db5332a5290f941021636b1182761Sol Boucher
1335a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1336a0842b40441db5332a5290f941021636b1182761Sol Boucher        public int getNumberOfCameras() {
1337a0842b40441db5332a5290f941021636b1182761Sol Boucher            return mNumberOfCameras;
1338a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1339a0842b40441db5332a5290f941021636b1182761Sol Boucher
1340a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1341a0842b40441db5332a5290f941021636b1182761Sol Boucher        public int getFirstBackCameraId() {
1342a0842b40441db5332a5290f941021636b1182761Sol Boucher            return mFirstBackCameraId;
1343a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1344a0842b40441db5332a5290f941021636b1182761Sol Boucher
1345a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1346a0842b40441db5332a5290f941021636b1182761Sol Boucher        public int getFirstFrontCameraId() {
1347a0842b40441db5332a5290f941021636b1182761Sol Boucher            return mFirstFrontCameraId;
1348a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1349a0842b40441db5332a5290f941021636b1182761Sol Boucher
1350de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        private static class AndroidCharacteristics2 extends Characteristics {
1351a0842b40441db5332a5290f941021636b1182761Sol Boucher            private CameraCharacteristics mCameraInfo;
1352a0842b40441db5332a5290f941021636b1182761Sol Boucher
1353a0842b40441db5332a5290f941021636b1182761Sol Boucher            AndroidCharacteristics2(CameraCharacteristics cameraInfo) {
1354a0842b40441db5332a5290f941021636b1182761Sol Boucher                mCameraInfo = cameraInfo;
1355a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
1356a0842b40441db5332a5290f941021636b1182761Sol Boucher
1357a0842b40441db5332a5290f941021636b1182761Sol Boucher            @Override
1358a0842b40441db5332a5290f941021636b1182761Sol Boucher            public boolean isFacingBack() {
1359a0842b40441db5332a5290f941021636b1182761Sol Boucher                return mCameraInfo.get(CameraCharacteristics.LENS_FACING)
1360a0842b40441db5332a5290f941021636b1182761Sol Boucher                        .equals(CameraCharacteristics.LENS_FACING_BACK);
1361a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
1362a0842b40441db5332a5290f941021636b1182761Sol Boucher
1363a0842b40441db5332a5290f941021636b1182761Sol Boucher            @Override
1364a0842b40441db5332a5290f941021636b1182761Sol Boucher            public boolean isFacingFront() {
1365a0842b40441db5332a5290f941021636b1182761Sol Boucher                return mCameraInfo.get(CameraCharacteristics.LENS_FACING)
1366a0842b40441db5332a5290f941021636b1182761Sol Boucher                        .equals(CameraCharacteristics.LENS_FACING_FRONT);
1367a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
1368a0842b40441db5332a5290f941021636b1182761Sol Boucher
1369a0842b40441db5332a5290f941021636b1182761Sol Boucher            @Override
1370a0842b40441db5332a5290f941021636b1182761Sol Boucher            public int getSensorOrientation() {
1371a0842b40441db5332a5290f941021636b1182761Sol Boucher                return mCameraInfo.get(CameraCharacteristics.SENSOR_ORIENTATION);
1372a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
1373a0842b40441db5332a5290f941021636b1182761Sol Boucher
1374a0842b40441db5332a5290f941021636b1182761Sol Boucher            @Override
1375f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher            public Matrix getPreviewTransform(int currentDisplayOrientation,
1376f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                                              RectF surfaceDimensions,
1377f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                                              RectF desiredBounds) {
1378f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                if (!orientationIsValid(currentDisplayOrientation)) {
1379f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                    return new Matrix();
1380f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                }
1381f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher
1382f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                // The system transparently transforms the image to fill the surface
1383f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                // when the device is in its natural orientation. We rotate the
1384f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                // coordinates of the rectangle's corners to be relative to the
1385f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                // original image, instead of to the current screen orientation.
1386f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                float[] surfacePolygon = rotate(convertRectToPoly(surfaceDimensions),
1387f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                        2 * currentDisplayOrientation / 90);
1388f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                float[] desiredPolygon = convertRectToPoly(desiredBounds);
1389f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher
1390f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                Matrix transform = new Matrix();
1391f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                // Use polygons instead of rectangles so that rotation will be
1392f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                // calculated, since that is not done by the new camera API.
1393f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                transform.setPolyToPoly(surfacePolygon, 0, desiredPolygon, 0, 4);
1394f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                return transform;
1395f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher            }
1396f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher
1397f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher            @Override
1398a0842b40441db5332a5290f941021636b1182761Sol Boucher            public boolean canDisableShutterSound() {
1399415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher                return true;
1400a0842b40441db5332a5290f941021636b1182761Sol Boucher            }
1401f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher
1402f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher            private static float[] convertRectToPoly(RectF rf) {
1403f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                return new float[] {rf.left, rf.top, rf.right, rf.top,
1404f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                        rf.right, rf.bottom, rf.left, rf.bottom};
1405f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher            }
1406f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher
1407f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher            private static float[] rotate(float[] arr, int times) {
1408f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                if (times < 0) {
1409f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                    times = times % arr.length + arr.length;
1410f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                }
1411f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher
1412f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                float[] res = new float[arr.length];
1413f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                for (int offset = 0; offset < arr.length; ++offset) {
1414f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                    res[offset] = arr[(times + offset) % arr.length];
1415f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                }
1416f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher                return res;
1417f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher            }
1418a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1419a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
1420a0842b40441db5332a5290f941021636b1182761Sol Boucher}
1421