AndroidCamera2AgentImpl.java revision 171362f843c1e7623f29db1781176f85b1f74815
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; 68a0842b40441db5332a5290f941021636b1182761Sol Boucher 69a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 70a0842b40441db5332a5290f941021636b1182761Sol Boucher * Number of camera devices. The length of {@code mCameraDevices} does not reveal this 71a0842b40441db5332a5290f941021636b1182761Sol Boucher * information because that list may contain since-invalidated indices. 72a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 73a0842b40441db5332a5290f941021636b1182761Sol Boucher private int mNumCameraDevices; 74a0842b40441db5332a5290f941021636b1182761Sol Boucher 75a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 76a0842b40441db5332a5290f941021636b1182761Sol Boucher * Transformation between integral camera indices and the {@link java.lang.String} indices used 77a0842b40441db5332a5290f941021636b1182761Sol Boucher * by the underlying API. Note that devices may disappear because they've been disconnected or 78a0842b40441db5332a5290f941021636b1182761Sol Boucher * have otherwise gone offline. Because we need to keep the meanings of whatever indices we 79a0842b40441db5332a5290f941021636b1182761Sol Boucher * expose stable, we cannot simply remove them in such a case; instead, we insert {@code null}s 80a0842b40441db5332a5290f941021636b1182761Sol Boucher * to invalidate any such indices. Whenever new devices appear, they are appended to the end of 81a0842b40441db5332a5290f941021636b1182761Sol Boucher * the list, and thereby assigned the lowest index that has never yet been used. 82a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 83a0842b40441db5332a5290f941021636b1182761Sol Boucher private final List<String> mCameraDevices; 84a0842b40441db5332a5290f941021636b1182761Sol Boucher 85a0842b40441db5332a5290f941021636b1182761Sol Boucher AndroidCamera2AgentImpl(Context context) { 86a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraHandlerThread = new HandlerThread("Camera2 Handler Thread"); 87a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraHandlerThread.start(); 88a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraHandler = new Camera2Handler(mCameraHandlerThread.getLooper()); 89a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraState = new AndroidCamera2StateHolder(); 90a0842b40441db5332a5290f941021636b1182761Sol Boucher mDispatchThread = new DispatchThread(mCameraHandler, mCameraHandlerThread); 91a0842b40441db5332a5290f941021636b1182761Sol Boucher mDispatchThread.start(); 92a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); 93aa907a3b6637b4f95dbf572d0cf790a70ba3aeb0Sol Boucher mNoisemaker = new MediaActionSound(); 94aa907a3b6637b4f95dbf572d0cf790a70ba3aeb0Sol Boucher mNoisemaker.load(MediaActionSound.SHUTTER_CLICK); 95a0842b40441db5332a5290f941021636b1182761Sol Boucher 96a0842b40441db5332a5290f941021636b1182761Sol Boucher mNumCameraDevices = 0; 97a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraDevices = new ArrayList<String>(); 98a0842b40441db5332a5290f941021636b1182761Sol Boucher updateCameraDevices(); 99a0842b40441db5332a5290f941021636b1182761Sol Boucher } 100a0842b40441db5332a5290f941021636b1182761Sol Boucher 101a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 102a0842b40441db5332a5290f941021636b1182761Sol Boucher * Updates the camera device index assignments stored in {@link mCameraDevices}, without 103a0842b40441db5332a5290f941021636b1182761Sol Boucher * reappropriating any currently-assigned index. 104a0842b40441db5332a5290f941021636b1182761Sol Boucher * @return Whether the operation was successful 105a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 106a0842b40441db5332a5290f941021636b1182761Sol Boucher private boolean updateCameraDevices() { 107a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 108a0842b40441db5332a5290f941021636b1182761Sol Boucher String[] currentCameraDevices = mCameraManager.getCameraIdList(); 109a0842b40441db5332a5290f941021636b1182761Sol Boucher Set<String> currentSet = new HashSet<String>(Arrays.asList(currentCameraDevices)); 110a0842b40441db5332a5290f941021636b1182761Sol Boucher 111a0842b40441db5332a5290f941021636b1182761Sol Boucher // Invalidate the indices assigned to any camera devices that are no longer present 112a0842b40441db5332a5290f941021636b1182761Sol Boucher for (int index = 0; index < mCameraDevices.size(); ++index) { 113a0842b40441db5332a5290f941021636b1182761Sol Boucher if (!currentSet.contains(mCameraDevices.get(index))) { 114a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraDevices.set(index, null); 115a0842b40441db5332a5290f941021636b1182761Sol Boucher --mNumCameraDevices; 116a0842b40441db5332a5290f941021636b1182761Sol Boucher } 117a0842b40441db5332a5290f941021636b1182761Sol Boucher } 118a0842b40441db5332a5290f941021636b1182761Sol Boucher 119a0842b40441db5332a5290f941021636b1182761Sol Boucher // Assign fresh indices to any new camera devices 120a0842b40441db5332a5290f941021636b1182761Sol Boucher currentSet.removeAll(mCameraDevices); // The devices we didn't know about 121a0842b40441db5332a5290f941021636b1182761Sol Boucher for (String device : currentCameraDevices) { 122a0842b40441db5332a5290f941021636b1182761Sol Boucher if (currentSet.contains(device)) { 123a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraDevices.add(device); 124a0842b40441db5332a5290f941021636b1182761Sol Boucher ++mNumCameraDevices; 125a0842b40441db5332a5290f941021636b1182761Sol Boucher } 126a0842b40441db5332a5290f941021636b1182761Sol Boucher } 127a0842b40441db5332a5290f941021636b1182761Sol Boucher 128a0842b40441db5332a5290f941021636b1182761Sol Boucher return true; 129a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (CameraAccessException ex) { 130a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "Could not get device listing from camera subsystem", ex); 131a0842b40441db5332a5290f941021636b1182761Sol Boucher return false; 132a0842b40441db5332a5290f941021636b1182761Sol Boucher } 133a0842b40441db5332a5290f941021636b1182761Sol Boucher } 134a0842b40441db5332a5290f941021636b1182761Sol Boucher 135a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 136a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 137a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setCameraDefaultExceptionCallback(CameraExceptionCallback callback, 138a0842b40441db5332a5290f941021636b1182761Sol Boucher Handler handler) {} 139a0842b40441db5332a5290f941021636b1182761Sol Boucher 140a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 141a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 142a0842b40441db5332a5290f941021636b1182761Sol Boucher public void recycle() {} 143a0842b40441db5332a5290f941021636b1182761Sol Boucher 144a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Some indices may now be invalid; ensure everyone can handle that and update the docs 145a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 146a0842b40441db5332a5290f941021636b1182761Sol Boucher public CameraDeviceInfo getCameraDeviceInfo() { 147a0842b40441db5332a5290f941021636b1182761Sol Boucher updateCameraDevices(); 148a0842b40441db5332a5290f941021636b1182761Sol Boucher return new AndroidCamera2DeviceInfo(mCameraManager, mCameraDevices.toArray(new String[0]), 149a0842b40441db5332a5290f941021636b1182761Sol Boucher mNumCameraDevices); 150a0842b40441db5332a5290f941021636b1182761Sol Boucher } 151a0842b40441db5332a5290f941021636b1182761Sol Boucher 152a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 153a0842b40441db5332a5290f941021636b1182761Sol Boucher protected Handler getCameraHandler() { 154a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraHandler; 155a0842b40441db5332a5290f941021636b1182761Sol Boucher } 156a0842b40441db5332a5290f941021636b1182761Sol Boucher 157a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 158a0842b40441db5332a5290f941021636b1182761Sol Boucher protected DispatchThread getDispatchThread() { 159a0842b40441db5332a5290f941021636b1182761Sol Boucher return mDispatchThread; 160a0842b40441db5332a5290f941021636b1182761Sol Boucher } 161a0842b40441db5332a5290f941021636b1182761Sol Boucher 162de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher private static abstract class CaptureAvailableListener 163bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala extends CameraCaptureSession.CaptureCallback 164de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher implements ImageReader.OnImageAvailableListener {}; 165de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 166a0842b40441db5332a5290f941021636b1182761Sol Boucher private class Camera2Handler extends HistoryHandler { 167a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Caller-provided when leaving CAMERA_UNOPENED state: 168a0842b40441db5332a5290f941021636b1182761Sol Boucher private CameraOpenCallback mOpenCallback; 169a0842b40441db5332a5290f941021636b1182761Sol Boucher private int mCameraIndex; 170a0842b40441db5332a5290f941021636b1182761Sol Boucher private String mCameraId; 171a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 172a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Available in CAMERA_UNCONFIGURED state and above: 173a0842b40441db5332a5290f941021636b1182761Sol Boucher private CameraDevice mCamera; 174a0842b40441db5332a5290f941021636b1182761Sol Boucher private AndroidCamera2ProxyImpl mCameraProxy; 175de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher private Camera2RequestSettingsSet mPersistentSettings; 176a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private Rect mActiveArray; 177de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher private boolean mLegacyDevice; 178a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 179a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Available in CAMERA_CONFIGURED state and above: 180a0842b40441db5332a5290f941021636b1182761Sol Boucher private Size mPreviewSize; 181a0842b40441db5332a5290f941021636b1182761Sol Boucher private Size mPhotoSize; 182a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 183a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Available in PREVIEW_READY state and above: 184a0842b40441db5332a5290f941021636b1182761Sol Boucher private SurfaceTexture mPreviewTexture; 185a0842b40441db5332a5290f941021636b1182761Sol Boucher private Surface mPreviewSurface; 186a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private CameraCaptureSession mSession; 187de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher private ImageReader mCaptureReader; 188a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 189a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Available from the beginning of PREVIEW_ACTIVE until the first preview frame arrives: 190a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private CameraStartPreviewCallback mOneshotPreviewingCallback; 191a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 192a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Available in FOCUS_LOCKED between AF trigger receipt and whenever the lens stops moving: 193a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private CameraAFCallback mOneshotAfCallback; 194a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 195de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // Available when taking picture between AE trigger receipt and autoexposure convergence 196de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher private CaptureAvailableListener mOneshotCaptureCallback; 197de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 198a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Available whenever setAutoFocusMoveCallback() was last invoked with a non-null argument: 199a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private CameraAFMoveCallback mPassiveAfCallback; 200a0842b40441db5332a5290f941021636b1182761Sol Boucher 201984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // Gets reset on every state change 202984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private int mCurrentAeState = CaptureResult.CONTROL_AE_STATE_INACTIVE; 203984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 204a0842b40441db5332a5290f941021636b1182761Sol Boucher Camera2Handler(Looper looper) { 205a0842b40441db5332a5290f941021636b1182761Sol Boucher super(looper); 206a0842b40441db5332a5290f941021636b1182761Sol Boucher } 207a0842b40441db5332a5290f941021636b1182761Sol Boucher 208a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 209a0842b40441db5332a5290f941021636b1182761Sol Boucher public void handleMessage(final Message msg) { 210a0842b40441db5332a5290f941021636b1182761Sol Boucher super.handleMessage(msg); 211a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 212a0842b40441db5332a5290f941021636b1182761Sol Boucher switch(msg.what) { 213a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.OPEN_CAMERA: 214a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.RECONNECT: { 215a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj; 216a0842b40441db5332a5290f941021636b1182761Sol Boucher int cameraIndex = msg.arg1; 217a0842b40441db5332a5290f941021636b1182761Sol Boucher 218772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher if (mCameraState.getState() > AndroidCamera2StateHolder.CAMERA_UNOPENED) { 219a0842b40441db5332a5290f941021636b1182761Sol Boucher openCallback.onDeviceOpenedAlready(cameraIndex, 220a0842b40441db5332a5290f941021636b1182761Sol Boucher generateHistoryString(cameraIndex)); 221a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 222a0842b40441db5332a5290f941021636b1182761Sol Boucher } 223a0842b40441db5332a5290f941021636b1182761Sol Boucher 224a0842b40441db5332a5290f941021636b1182761Sol Boucher mOpenCallback = openCallback; 225a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraIndex = cameraIndex; 226a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraId = mCameraDevices.get(mCameraIndex); 22750f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher Log.i(TAG, String.format("Opening camera index %d (id %s) with camera2 API", 22850f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher cameraIndex, mCameraId)); 229a0842b40441db5332a5290f941021636b1182761Sol Boucher 230a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mCameraId == null) { 231a0842b40441db5332a5290f941021636b1182761Sol Boucher mOpenCallback.onCameraDisabled(msg.arg1); 232a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 233a0842b40441db5332a5290f941021636b1182761Sol Boucher } 234bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala mCameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, this); 235a0842b40441db5332a5290f941021636b1182761Sol Boucher 236a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 237a0842b40441db5332a5290f941021636b1182761Sol Boucher } 238a0842b40441db5332a5290f941021636b1182761Sol Boucher 239a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.RELEASE: { 240a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mCameraState.getState() == AndroidCamera2StateHolder.CAMERA_UNOPENED) { 241a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Ignoring release at inappropriate time"); 242a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher break; 243a0842b40441db5332a5290f941021636b1182761Sol Boucher } 244a0842b40441db5332a5290f941021636b1182761Sol Boucher 245a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mSession != null) { 246a0842b40441db5332a5290f941021636b1182761Sol Boucher closePreviewSession(); 247a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession = null; 248a0842b40441db5332a5290f941021636b1182761Sol Boucher } 249a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mCamera != null) { 250a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera.close(); 251a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera = null; 252a0842b40441db5332a5290f941021636b1182761Sol Boucher } 253a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraProxy = null; 254de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mPersistentSettings = null; 255a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mActiveArray = null; 256a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mPreviewSurface != null) { 257a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewSurface.release(); 258a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewSurface = null; 259a0842b40441db5332a5290f941021636b1182761Sol Boucher } 260a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewTexture = null; 261de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (mCaptureReader != null) { 262de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mCaptureReader.close(); 263de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mCaptureReader = null; 264de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 265a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewSize = null; 266a0842b40441db5332a5290f941021636b1182761Sol Boucher mPhotoSize = null; 267a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraIndex = 0; 268a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraId = null; 269984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher changeState(AndroidCamera2StateHolder.CAMERA_UNOPENED); 270a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 271a0842b40441db5332a5290f941021636b1182761Sol Boucher } 272a0842b40441db5332a5290f941021636b1182761Sol Boucher 273a0842b40441db5332a5290f941021636b1182761Sol Boucher /*case CameraActions.UNLOCK: { 274a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 275a0842b40441db5332a5290f941021636b1182761Sol Boucher } 276a0842b40441db5332a5290f941021636b1182761Sol Boucher 277a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.LOCK: { 278a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 279a0842b40441db5332a5290f941021636b1182761Sol Boucher }*/ 280a0842b40441db5332a5290f941021636b1182761Sol Boucher 281a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_PREVIEW_TEXTURE_ASYNC: { 282a0842b40441db5332a5290f941021636b1182761Sol Boucher setPreviewTexture((SurfaceTexture) msg.obj); 283a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 284a0842b40441db5332a5290f941021636b1182761Sol Boucher } 285a0842b40441db5332a5290f941021636b1182761Sol Boucher 286a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.START_PREVIEW_ASYNC: { 287a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mCameraState.getState() != 288a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher AndroidCamera2StateHolder.CAMERA_PREVIEW_READY) { 289a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Provide better feedback here? 290a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Refusing to start preview at inappropriate time"); 291a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 292a0842b40441db5332a5290f941021636b1182761Sol Boucher } 293a0842b40441db5332a5290f941021636b1182761Sol Boucher 294a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mOneshotPreviewingCallback = (CameraStartPreviewCallback) msg.obj; 295984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE); 296a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher try { 297de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mSession.setRepeatingRequest( 298de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mPersistentSettings.createRequest(mCamera, 299de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher CameraDevice.TEMPLATE_PREVIEW, mPreviewSurface), 300bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala /*listener*/mCameraResultStateCallback, /*handler*/this); 301a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } catch(CameraAccessException ex) { 302a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Unable to start preview", ex); 303984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY); 304a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 305a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 306a0842b40441db5332a5290f941021636b1182761Sol Boucher } 307a0842b40441db5332a5290f941021636b1182761Sol Boucher 3082569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // FIXME: We need to tear down the CameraCaptureSession here 3092569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // (and unlock the CameraSettings object from our 3102569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // CameraProxy) so that the preview/photo sizes can be 3112569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // changed again while no preview is running. 312a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.STOP_PREVIEW: { 313a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mCameraState.getState() < 314a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) { 315a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Refusing to stop preview at inappropriate time"); 316a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher break; 317a0842b40441db5332a5290f941021636b1182761Sol Boucher } 318a0842b40441db5332a5290f941021636b1182761Sol Boucher 319a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession.stopRepeating(); 320984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY); 321a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 322a0842b40441db5332a5290f941021636b1182761Sol Boucher } 323a0842b40441db5332a5290f941021636b1182761Sol Boucher 324a0842b40441db5332a5290f941021636b1182761Sol Boucher /*case CameraActions.SET_PREVIEW_CALLBACK_WITH_BUFFER: { 325a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 326a0842b40441db5332a5290f941021636b1182761Sol Boucher } 327a0842b40441db5332a5290f941021636b1182761Sol Boucher 328a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.ADD_CALLBACK_BUFFER: { 329a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 330a0842b40441db5332a5290f941021636b1182761Sol Boucher } 331a0842b40441db5332a5290f941021636b1182761Sol Boucher 332a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_PREVIEW_DISPLAY_ASYNC: { 333a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 334a0842b40441db5332a5290f941021636b1182761Sol Boucher } 335a0842b40441db5332a5290f941021636b1182761Sol Boucher 336a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_PREVIEW_CALLBACK: { 337a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 338a0842b40441db5332a5290f941021636b1182761Sol Boucher } 339a0842b40441db5332a5290f941021636b1182761Sol Boucher 340a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_ONE_SHOT_PREVIEW_CALLBACK: { 341a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 342a0842b40441db5332a5290f941021636b1182761Sol Boucher } 343a0842b40441db5332a5290f941021636b1182761Sol Boucher 344a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_PARAMETERS: { 345a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 346a0842b40441db5332a5290f941021636b1182761Sol Boucher } 347a0842b40441db5332a5290f941021636b1182761Sol Boucher 348a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.GET_PARAMETERS: { 349a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 350a0842b40441db5332a5290f941021636b1182761Sol Boucher } 351a0842b40441db5332a5290f941021636b1182761Sol Boucher 352a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.REFRESH_PARAMETERS: { 353a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 354a0842b40441db5332a5290f941021636b1182761Sol Boucher }*/ 355a0842b40441db5332a5290f941021636b1182761Sol Boucher 356a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.APPLY_SETTINGS: { 357de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher AndroidCamera2Settings settings = (AndroidCamera2Settings) msg.obj; 358a0842b40441db5332a5290f941021636b1182761Sol Boucher applyToRequest(settings); 359a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 360a0842b40441db5332a5290f941021636b1182761Sol Boucher } 361a0842b40441db5332a5290f941021636b1182761Sol Boucher 362a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher case CameraActions.AUTO_FOCUS: { 363a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // We only support locking the focus while a preview is being displayed. 364a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // However, it can be requested multiple times in succession; the effect of 365a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // the subsequent invocations is determined by the focus mode defined in the 366a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // provided CameraSettings object. In passive (CONTINUOUS_*) mode, the 367a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // duplicate requests are no-ops and leave the lens locked at its current 368a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // position, but in active (AUTO) mode, they perform another scan and lock 369a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // once that is finished. In any manual focus mode, this call is a no-op, 370a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // and most notably, this is the only case where the callback isn't invoked. 371a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mCameraState.getState() < 372a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) { 373a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Ignoring attempt to autofocus without preview"); 374a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher break; 375a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 376a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 377a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // The earliest we can reliably tell whether the autofocus has locked in 378984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // response to our latest request is when our one-time capture progresses. 379a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // However, it will probably take longer than that, so once that happens, 380a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // just start checking the repeating preview requests as they complete. 381a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher final CameraAFCallback callback = (CameraAFCallback) msg.obj; 382bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala CameraCaptureSession.CaptureCallback deferredCallbackSetter = 383bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala new CameraCaptureSession.CaptureCallback() { 384984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private boolean mAlreadyDispatched = false; 385984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 386984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher @Override 387984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher public void onCaptureProgressed(CameraCaptureSession session, 388984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher CaptureRequest request, 389984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher CaptureResult result) { 390984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher checkAfState(result); 391984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 392984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 393a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 394a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onCaptureCompleted(CameraCaptureSession session, 395a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureRequest request, 396a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher TotalCaptureResult result) { 397984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher checkAfState(result); 398984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 399984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 400984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private void checkAfState(CaptureResult result) { 401984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (result.get(CaptureResult.CONTROL_AF_STATE) != null && 402984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher !mAlreadyDispatched) { 403bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala // Now our mCameraResultStateCallback will invoke the callback 404984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // the first time it finds the focus motor to be locked. 405984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mAlreadyDispatched = true; 406984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mOneshotAfCallback = callback; 407984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // This is an optimization: check the AF state of this frame 408984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // instead of simply waiting for the next. 409bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala mCameraResultStateCallback.monitorControlStates(result); 410984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 411a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 412a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 413a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 414a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onCaptureFailed(CameraCaptureSession session, 415a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureRequest request, 416a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureFailure failure) { 417a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.e(TAG, "Focusing failed with reason " + failure.getReason()); 418a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher callback.onAutoFocus(false, mCameraProxy); 419a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}; 420a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 421a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Send a one-time capture to trigger the camera driver to lock focus. 422984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher changeState(AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED); 423de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Camera2RequestSettingsSet trigger = 424de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher new Camera2RequestSettingsSet(mPersistentSettings); 425de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher trigger.set(CaptureRequest.CONTROL_AF_TRIGGER, 426a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureRequest.CONTROL_AF_TRIGGER_START); 427a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher try { 428de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mSession.capture( 429de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher trigger.createRequest(mCamera, CameraDevice.TEMPLATE_PREVIEW, 430de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mPreviewSurface), 431a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /*listener*/deferredCallbackSetter, /*handler*/ this); 432a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } catch(CameraAccessException ex) { 433a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.e(TAG, "Unable to lock autofocus", ex); 434984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE); 435a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 436a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 437a0842b40441db5332a5290f941021636b1182761Sol Boucher } 438a0842b40441db5332a5290f941021636b1182761Sol Boucher 439a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.CANCEL_AUTO_FOCUS: { 440a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Why would you want to unlock the lens if it isn't already locked? 441a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mCameraState.getState() < 442a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) { 443a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Ignoring attempt to release focus lock without preview"); 444a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher break; 445a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 446a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 447a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Send a one-time capture to trigger the camera driver to resume scanning. 448984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE); 449de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Camera2RequestSettingsSet cancel = 450de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher new Camera2RequestSettingsSet(mPersistentSettings); 451de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher cancel.set(CaptureRequest.CONTROL_AF_TRIGGER, 452a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureRequest.CONTROL_AF_TRIGGER_CANCEL); 453a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher try { 454de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mSession.capture( 455de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher cancel.createRequest(mCamera, CameraDevice.TEMPLATE_PREVIEW, 456de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mPreviewSurface), 457a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /*listener*/null, /*handler*/this); 458a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } catch(CameraAccessException ex) { 459a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.e(TAG, "Unable to cancel autofocus", ex); 460984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher changeState(AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED); 461a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 462a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 463a0842b40441db5332a5290f941021636b1182761Sol Boucher } 464a0842b40441db5332a5290f941021636b1182761Sol Boucher 465a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK: { 466a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPassiveAfCallback = (CameraAFMoveCallback) msg.obj; 467a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 468a0842b40441db5332a5290f941021636b1182761Sol Boucher } 469a0842b40441db5332a5290f941021636b1182761Sol Boucher 470a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /*case CameraActions.SET_ZOOM_CHANGE_LISTENER: { 471a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 472a0842b40441db5332a5290f941021636b1182761Sol Boucher } 473a0842b40441db5332a5290f941021636b1182761Sol Boucher 474a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_FACE_DETECTION_LISTENER: { 475a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 476a0842b40441db5332a5290f941021636b1182761Sol Boucher } 477a0842b40441db5332a5290f941021636b1182761Sol Boucher 478a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.START_FACE_DETECTION: { 479a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 480a0842b40441db5332a5290f941021636b1182761Sol Boucher } 481a0842b40441db5332a5290f941021636b1182761Sol Boucher 482a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.STOP_FACE_DETECTION: { 483a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 484a0842b40441db5332a5290f941021636b1182761Sol Boucher } 485a0842b40441db5332a5290f941021636b1182761Sol Boucher 486a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_ERROR_CALLBACK: { 487a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 488a0842b40441db5332a5290f941021636b1182761Sol Boucher } 489a0842b40441db5332a5290f941021636b1182761Sol Boucher 490a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.ENABLE_SHUTTER_SOUND: { 491a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 492de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher }*/ 493a0842b40441db5332a5290f941021636b1182761Sol Boucher 494a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_DISPLAY_ORIENTATION: { 495de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // Only set the JPEG capture orientation if requested to do so; otherwise, 496de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // capture in the sensor's physical orientation 497de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mPersistentSettings.set(CaptureRequest.JPEG_ORIENTATION, msg.arg2 > 0 ? 498de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mCameraProxy.getCharacteristics().getJpegOrientation(msg.arg1) : 0); 499a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 500a0842b40441db5332a5290f941021636b1182761Sol Boucher } 501a0842b40441db5332a5290f941021636b1182761Sol Boucher 502a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.CAPTURE_PHOTO: { 503de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (mCameraState.getState() < 504de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) { 505de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.e(TAG, "Photos may only be taken when a preview is active"); 506de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher break; 507de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 508de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (mCameraState.getState() != 509de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED) { 510de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.w(TAG, "Taking a (likely blurry) photo without the lens locked"); 511de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 512de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 513de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher final CaptureAvailableListener listener = 514de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher (CaptureAvailableListener) msg.obj; 515984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (mLegacyDevice || 516984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher (mCurrentAeState == CaptureResult.CONTROL_AE_STATE_CONVERGED && 517984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher !mPersistentSettings.matches(CaptureRequest.CONTROL_AE_MODE, 518984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH) && 519984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher !mPersistentSettings.matches(CaptureRequest.FLASH_MODE, 520984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher CaptureRequest.FLASH_MODE_SINGLE))) 521984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher { 522984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // Legacy devices don't support the precapture state keys and instead 523984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // perform autoexposure convergence automatically upon capture. 524984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 525984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // On other devices, as long as it has already converged, it determined 526984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // that flash was not required, and we're not going to invalidate the 527984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // current exposure levels by forcing the force on, we can save 528984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // significant capture time by not forcing a recalculation. 529984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher Log.i(TAG, "Skipping pre-capture autoexposure convergence"); 530de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mCaptureReader.setOnImageAvailableListener(listener, /*handler*/this); 531de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher try { 532de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mSession.capture( 533de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mPersistentSettings.createRequest(mCamera, 534de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher CameraDevice.TEMPLATE_STILL_CAPTURE, 535de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mCaptureReader.getSurface()), 536de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher listener, /*handler*/this); 537de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } catch (CameraAccessException ex) { 538984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher Log.e(TAG, "Unable to initiate immediate capture", ex); 539de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 540de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } else { 541984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // We need to let AE converge before capturing. Once our one-time 542984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // trigger capture has made it into the pipeline, we'll start checking 543984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // for the completion of that convergence, capturing when that happens. 544984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher Log.i(TAG, "Forcing pre-capture autoexposure convergence"); 545bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala CameraCaptureSession.CaptureCallback deferredCallbackSetter = 546bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala new CameraCaptureSession.CaptureCallback() { 547984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private boolean mAlreadyDispatched = false; 548984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 549984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher @Override 550984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher public void onCaptureProgressed(CameraCaptureSession session, 551984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher CaptureRequest request, 552984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher CaptureResult result) { 553984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher checkAeState(result); 554984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 555984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 556de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher @Override 557de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public void onCaptureCompleted(CameraCaptureSession session, 558de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher CaptureRequest request, 559de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher TotalCaptureResult result) { 560984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher checkAeState(result); 561984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 562984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 563984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private void checkAeState(CaptureResult result) { 564984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (result.get(CaptureResult.CONTROL_AE_STATE) != null && 565984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher !mAlreadyDispatched) { 566bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala // Now our mCameraResultStateCallback will invoke the 567984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // callback once the autoexposure routine has converged. 568984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mAlreadyDispatched = true; 569984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mOneshotCaptureCallback = listener; 570984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // This is an optimization: check the AE state of this frame 571984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // instead of simply waiting for the next. 572bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala mCameraResultStateCallback.monitorControlStates(result); 573984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 574de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 575de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 576de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher @Override 577de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public void onCaptureFailed(CameraCaptureSession session, 578de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher CaptureRequest request, 579de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher CaptureFailure failure) { 580de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.e(TAG, "Autoexposure and capture failed with reason " + 581de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher failure.getReason()); 582de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // TODO: Make an error callback? 583de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher }}; 584de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 585de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // Set a one-time capture to trigger the camera driver's autoexposure: 586de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Camera2RequestSettingsSet expose = 587de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher new Camera2RequestSettingsSet(mPersistentSettings); 588de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher expose.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, 589de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START); 590de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher try { 591de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mSession.capture( 592de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher expose.createRequest(mCamera, CameraDevice.TEMPLATE_PREVIEW, 593de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mPreviewSurface), 594de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /*listener*/deferredCallbackSetter, /*handler*/this); 595de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } catch (CameraAccessException ex) { 596de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.e(TAG, "Unable to run autoexposure and perform capture", ex); 597de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 598de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 599a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 600de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 601a0842b40441db5332a5290f941021636b1182761Sol Boucher 602a0842b40441db5332a5290f941021636b1182761Sol Boucher default: { 603a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Rephrase once everything has been implemented 604a0842b40441db5332a5290f941021636b1182761Sol Boucher throw new RuntimeException("Unimplemented CameraProxy message=" + msg.what); 605a0842b40441db5332a5290f941021636b1182761Sol Boucher } 606a0842b40441db5332a5290f941021636b1182761Sol Boucher } 607a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (final Exception ex) { 608a0842b40441db5332a5290f941021636b1182761Sol Boucher if (msg.what != CameraActions.RELEASE && mCamera != null) { 609a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // TODO: Handle this better 610a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera.close(); 611a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera = null; 612a0842b40441db5332a5290f941021636b1182761Sol Boucher } else if (mCamera == null) { 613a0842b40441db5332a5290f941021636b1182761Sol Boucher if (msg.what == CameraActions.OPEN_CAMERA) { 614a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mOpenCallback != null) { 615a0842b40441db5332a5290f941021636b1182761Sol Boucher mOpenCallback.onDeviceOpenFailure(mCameraIndex, 616a0842b40441db5332a5290f941021636b1182761Sol Boucher generateHistoryString(mCameraIndex)); 617a0842b40441db5332a5290f941021636b1182761Sol Boucher } 618a0842b40441db5332a5290f941021636b1182761Sol Boucher } else { 619a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.w(TAG, "Cannot handle message " + msg.what + ", mCamera is null"); 620a0842b40441db5332a5290f941021636b1182761Sol Boucher } 621a0842b40441db5332a5290f941021636b1182761Sol Boucher return; 622a0842b40441db5332a5290f941021636b1182761Sol Boucher } 623a0842b40441db5332a5290f941021636b1182761Sol Boucher 624a0842b40441db5332a5290f941021636b1182761Sol Boucher if (ex instanceof RuntimeException) { 625a0842b40441db5332a5290f941021636b1182761Sol Boucher post(new Runnable() { 626a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 627a0842b40441db5332a5290f941021636b1182761Sol Boucher public void run() { 628a0842b40441db5332a5290f941021636b1182761Sol Boucher sCameraExceptionCallback.onCameraException((RuntimeException) ex); 629a0842b40441db5332a5290f941021636b1182761Sol Boucher }}); 630a0842b40441db5332a5290f941021636b1182761Sol Boucher } 631a0842b40441db5332a5290f941021636b1182761Sol Boucher } 632a0842b40441db5332a5290f941021636b1182761Sol Boucher } 633a0842b40441db5332a5290f941021636b1182761Sol Boucher 634a0842b40441db5332a5290f941021636b1182761Sol Boucher public CameraSettings buildSettings(AndroidCamera2Capabilities caps) { 635de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher try { 636de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return new AndroidCamera2Settings(mCamera, CameraDevice.TEMPLATE_PREVIEW, 637de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mActiveArray, mPreviewSize, mPhotoSize); 638de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } catch (CameraAccessException ex) { 639de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.e(TAG, "Unable to query camera device to build settings representation"); 640de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return null; 641de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 642a0842b40441db5332a5290f941021636b1182761Sol Boucher } 643a0842b40441db5332a5290f941021636b1182761Sol Boucher 644a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** 645a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Simply propagates settings from provided {@link CameraSettings} 646a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * object to our {@link CaptureRequest.Builder} for use in captures. 647a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * <p>Most conversions to match the API 2 formats are performed by 648a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * {@link AndroidCamera2Capabilities.IntegralStringifier}; otherwise 649a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * any final adjustments are done here before updating the builder.</p> 650a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * 651a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * @param settings The new/updated settings 652a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher */ 653de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher private void applyToRequest(AndroidCamera2Settings settings) { 654a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: If invoked when in PREVIEW_READY state, a new preview size will not take effect 655de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 656de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mPersistentSettings.union(settings.getRequestSettings()); 657a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewSize = settings.getCurrentPreviewSize(); 658a0842b40441db5332a5290f941021636b1182761Sol Boucher mPhotoSize = settings.getCurrentPhotoSize(); 659a0842b40441db5332a5290f941021636b1182761Sol Boucher 660a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mCameraState.getState() >= AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) { 661a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // If we're already previewing, reflect most settings immediately 662a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher try { 663de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mSession.setRepeatingRequest( 664de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mPersistentSettings.createRequest(mCamera, 665de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher CameraDevice.TEMPLATE_PREVIEW, mPreviewSurface), 666bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala /*listener*/mCameraResultStateCallback, /*handler*/this); 667a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } catch (CameraAccessException ex) { 668a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.e(TAG, "Failed to apply updated request settings", ex); 669a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 670a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } else if (mCameraState.getState() < AndroidCamera2StateHolder.CAMERA_PREVIEW_READY) { 671a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // If we're already ready to preview, this doesn't regress our state 672984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher changeState(AndroidCamera2StateHolder.CAMERA_CONFIGURED); 673a0842b40441db5332a5290f941021636b1182761Sol Boucher } 674a0842b40441db5332a5290f941021636b1182761Sol Boucher } 675a0842b40441db5332a5290f941021636b1182761Sol Boucher 676a0842b40441db5332a5290f941021636b1182761Sol Boucher private void setPreviewTexture(SurfaceTexture surfaceTexture) { 677a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Must be called after providing a .*Settings populated with sizes 678a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: We don't technically offer a selection of sizes tailored to SurfaceTextures! 679a0842b40441db5332a5290f941021636b1182761Sol Boucher 680a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Handle this error condition with a callback or exception 681a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mCameraState.getState() < AndroidCamera2StateHolder.CAMERA_CONFIGURED) { 682a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Ignoring texture setting at inappropriate time"); 683a0842b40441db5332a5290f941021636b1182761Sol Boucher return; 684a0842b40441db5332a5290f941021636b1182761Sol Boucher } 685a0842b40441db5332a5290f941021636b1182761Sol Boucher 686a0842b40441db5332a5290f941021636b1182761Sol Boucher // Avoid initializing another capture session unless we absolutely have to 687a0842b40441db5332a5290f941021636b1182761Sol Boucher if (surfaceTexture == mPreviewTexture) { 688a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.i(TAG, "Optimizing out redundant preview texture setting"); 689a0842b40441db5332a5290f941021636b1182761Sol Boucher return; 690a0842b40441db5332a5290f941021636b1182761Sol Boucher } 691a0842b40441db5332a5290f941021636b1182761Sol Boucher 692a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mSession != null) { 693a0842b40441db5332a5290f941021636b1182761Sol Boucher closePreviewSession(); 694a0842b40441db5332a5290f941021636b1182761Sol Boucher } 695a0842b40441db5332a5290f941021636b1182761Sol Boucher 696a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewTexture = surfaceTexture; 697a0842b40441db5332a5290f941021636b1182761Sol Boucher surfaceTexture.setDefaultBufferSize(mPreviewSize.width(), mPreviewSize.height()); 698a0842b40441db5332a5290f941021636b1182761Sol Boucher 699a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mPreviewSurface != null) { 700a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewSurface.release(); 701a0842b40441db5332a5290f941021636b1182761Sol Boucher } 702a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewSurface = new Surface(surfaceTexture); 703de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 704de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (mCaptureReader != null) { 705de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mCaptureReader.close(); 706de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 707de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mCaptureReader = ImageReader.newInstance( 708de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mPhotoSize.width(), mPhotoSize.height(), ImageFormat.JPEG, 1); 709a0842b40441db5332a5290f941021636b1182761Sol Boucher 710a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 711de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mCamera.createCaptureSession( 712de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Arrays.asList(mPreviewSurface, mCaptureReader.getSurface()), 713bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala mCameraPreviewStateCallback, this); 714a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (CameraAccessException ex) { 715a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "Failed to create camera capture session", ex); 716a0842b40441db5332a5290f941021636b1182761Sol Boucher } 717a0842b40441db5332a5290f941021636b1182761Sol Boucher } 718a0842b40441db5332a5290f941021636b1182761Sol Boucher 719a0842b40441db5332a5290f941021636b1182761Sol Boucher private void closePreviewSession() { 720a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 721a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession.abortCaptures(); 722a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession = null; 723a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (CameraAccessException ex) { 724a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "Failed to close existing camera capture session", ex); 725a0842b40441db5332a5290f941021636b1182761Sol Boucher } 726984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher changeState(AndroidCamera2StateHolder.CAMERA_CONFIGURED); 727984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 728984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 729984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private void changeState(int newState) { 730984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (mCameraState.getState() != newState) { 731984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mCameraState.setState(newState); 732984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (newState < AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) { 733984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mCurrentAeState = CaptureResult.CONTROL_AE_STATE_INACTIVE; 734bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala mCameraResultStateCallback.resetState(); 735984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 736984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 737a0842b40441db5332a5290f941021636b1182761Sol Boucher } 738a0842b40441db5332a5290f941021636b1182761Sol Boucher 739bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala // This callback monitors our connection to and disconnection from camera devices. 740bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala private CameraDevice.StateCallback mCameraDeviceStateCallback = 741bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala new CameraDevice.StateCallback() { 742a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 743a0842b40441db5332a5290f941021636b1182761Sol Boucher public void onOpened(CameraDevice camera) { 744a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera = camera; 745a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mOpenCallback != null) { 746a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 747a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraCharacteristics props = 748a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraManager.getCameraCharacteristics(mCameraId); 749a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraProxy = new AndroidCamera2ProxyImpl(mCameraIndex, mCamera, 750a0842b40441db5332a5290f941021636b1182761Sol Boucher getCameraDeviceInfo().getCharacteristics(mCameraIndex), props); 751de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mPersistentSettings = new Camera2RequestSettingsSet(); 752a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mActiveArray = 753a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher props.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); 754de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mLegacyDevice = 755de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher props.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) == 756de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY; 757984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher changeState(AndroidCamera2StateHolder.CAMERA_UNCONFIGURED); 758a0842b40441db5332a5290f941021636b1182761Sol Boucher mOpenCallback.onCameraOpened(mCameraProxy); 759a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (CameraAccessException ex) { 760a0842b40441db5332a5290f941021636b1182761Sol Boucher mOpenCallback.onDeviceOpenFailure(mCameraIndex, 761a0842b40441db5332a5290f941021636b1182761Sol Boucher generateHistoryString(mCameraIndex)); 762a0842b40441db5332a5290f941021636b1182761Sol Boucher } 763a0842b40441db5332a5290f941021636b1182761Sol Boucher } 764a0842b40441db5332a5290f941021636b1182761Sol Boucher } 765a0842b40441db5332a5290f941021636b1182761Sol Boucher 766a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 767a0842b40441db5332a5290f941021636b1182761Sol Boucher public void onDisconnected(CameraDevice camera) { 768a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.w(TAG, "Camera device '" + mCameraIndex + "' was disconnected"); 769a0842b40441db5332a5290f941021636b1182761Sol Boucher } 770a0842b40441db5332a5290f941021636b1182761Sol Boucher 771a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 772a0842b40441db5332a5290f941021636b1182761Sol Boucher public void onError(CameraDevice camera, int error) { 773a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "Camera device '" + mCameraIndex + "' encountered error code '" + 774a0842b40441db5332a5290f941021636b1182761Sol Boucher error + '\''); 775a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mOpenCallback != null) { 776a0842b40441db5332a5290f941021636b1182761Sol Boucher mOpenCallback.onDeviceOpenFailure(mCameraIndex, 777a0842b40441db5332a5290f941021636b1182761Sol Boucher generateHistoryString(mCameraIndex)); 778a0842b40441db5332a5290f941021636b1182761Sol Boucher } 779a0842b40441db5332a5290f941021636b1182761Sol Boucher }}; 780a0842b40441db5332a5290f941021636b1182761Sol Boucher 781bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala // This callback monitors our camera session (i.e. our transition into and out of preview). 782bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala private CameraCaptureSession.StateCallback mCameraPreviewStateCallback = 783bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala new CameraCaptureSession.StateCallback() { 784a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 785a0842b40441db5332a5290f941021636b1182761Sol Boucher public void onConfigured(CameraCaptureSession session) { 786a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession = session; 787984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY); 788a0842b40441db5332a5290f941021636b1182761Sol Boucher } 789a0842b40441db5332a5290f941021636b1182761Sol Boucher 790a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 791a0842b40441db5332a5290f941021636b1182761Sol Boucher public void onConfigureFailed(CameraCaptureSession session) { 792a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Invoke a callback 793a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "Failed to configure the camera for capture"); 794a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 795a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 796a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 797a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onActive(CameraCaptureSession session) { 798a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mOneshotPreviewingCallback != null) { 799a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // The session is up and processing preview requests. Inform the caller. 800a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mOneshotPreviewingCallback.onPreviewStarted(); 801a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mOneshotPreviewingCallback = null; 802a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 803a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}; 804a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 805bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala private abstract class CameraResultStateCallback 806bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala extends CameraCaptureSession.CaptureCallback { 807984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher public abstract void monitorControlStates(CaptureResult result); 808984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 809984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher public abstract void resetState(); 810984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 811984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 812bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala // This callback monitors requested captures and notifies any relevant callbacks. 813bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala private CameraResultStateCallback mCameraResultStateCallback = 814bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala new CameraResultStateCallback() { 815a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private int mLastAfState = -1; 816984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private long mLastAfFrameNumber = -1; 817984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private long mLastAeFrameNumber = -1; 818984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 819984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher @Override 820984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, 821984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher CaptureResult result) { 822984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher monitorControlStates(result); 823984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 824a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 825a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 826a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, 827a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher TotalCaptureResult result) { 828984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher monitorControlStates(result); 829984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 830984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 831984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher @Override 832984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher public void monitorControlStates(CaptureResult result) { 833a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Integer afStateMaybe = result.get(CaptureResult.CONTROL_AF_STATE); 834a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (afStateMaybe != null) { 835a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher int afState = afStateMaybe; 836984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // Since we handle both partial and total results for multiple frames here, we 837984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // might get the final callbacks for an earlier frame after receiving one or 838984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // more that correspond to the next one. To prevent our data from oscillating, 839984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // we never consider AF states that are older than the last one we've seen. 840984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (result.getFrameNumber() > mLastAfFrameNumber) { 841984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher boolean afStateChanged = afState != mLastAfState; 842a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mLastAfState = afState; 843984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mLastAfFrameNumber = result.getFrameNumber(); 844984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 845984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher switch (afState) { 846984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN: 847984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED: 848984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: { 849984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (afStateChanged && mPassiveAfCallback != null) { 850984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // A CameraAFMoveCallback is attached. If we just started to 851984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // scan, the motor is moving; otherwise, it has settled. 852984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mPassiveAfCallback.onAutoFocusMoving( 853984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN, 854984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mCameraProxy); 855984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 856984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher break; 857a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 858a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 859984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED: 860984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: { 8617d71703202c2fba36653293eba2772745db46c00Sol Boucher // This check must be made regardless of whether the focus state has 8627d71703202c2fba36653293eba2772745db46c00Sol Boucher // changed recently to avoid infinite waiting during autoFocus() 8637d71703202c2fba36653293eba2772745db46c00Sol Boucher // when the algorithm has already either converged or failed to. 864984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (mOneshotAfCallback != null) { 865984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // A call to autoFocus() was just made to request a focus lock. 866984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // Notify the caller that the lens is now indefinitely fixed, 867984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // and report whether the image we're stuck with is in focus. 868984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mOneshotAfCallback.onAutoFocus( 869984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED, 870984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mCameraProxy); 871984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mOneshotAfCallback = null; 872984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 873984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher break; 874a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 875a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 876a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 877a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 878de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 879de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Integer aeStateMaybe = result.get(CaptureResult.CONTROL_AE_STATE); 880de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (aeStateMaybe != null) { 881de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher int aeState = aeStateMaybe; 882984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // Since we handle both partial and total results for multiple frames here, we 883984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // might get the final callbacks for an earlier frame after receiving one or 884984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // more that correspond to the next one. To prevent our data from oscillating, 885984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // we never consider AE states that are older than the last one we've seen. 8867d71703202c2fba36653293eba2772745db46c00Sol Boucher if (result.getFrameNumber() > mLastAeFrameNumber) { 887984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mCurrentAeState = aeStateMaybe; 888984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mLastAeFrameNumber = result.getFrameNumber(); 889984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 890984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher switch (aeState) { 891984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher case CaptureResult.CONTROL_AE_STATE_CONVERGED: 892984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher case CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED: 893984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher case CaptureResult.CONTROL_AE_STATE_LOCKED: { 8947d71703202c2fba36653293eba2772745db46c00Sol Boucher // This check must be made regardless of whether the exposure state 8957d71703202c2fba36653293eba2772745db46c00Sol Boucher // has changed recently to avoid infinite waiting during 8967d71703202c2fba36653293eba2772745db46c00Sol Boucher // takePicture() when the algorithm has already converged. 897984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (mOneshotCaptureCallback != null) { 898984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // A call to takePicture() was just made, and autoexposure 899984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // converged so it's time to initiate the capture! 900984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mCaptureReader.setOnImageAvailableListener( 901de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /*listener*/mOneshotCaptureCallback, 902de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /*handler*/Camera2Handler.this); 903984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher try { 904984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mSession.capture( 905984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mPersistentSettings.createRequest(mCamera, 906984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher CameraDevice.TEMPLATE_STILL_CAPTURE, 907984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mCaptureReader.getSurface()), 908bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala /*callback*/mOneshotCaptureCallback, 909984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher /*handler*/Camera2Handler.this); 910984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } catch (CameraAccessException ex) { 911984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher Log.e(TAG, "Unable to initiate capture", ex); 912984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } finally { 913984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mOneshotCaptureCallback = null; 914984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 915de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 916984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher break; 917de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 918de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 919de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 920de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 921a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 922a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 923a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 924984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher public void resetState() { 925984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mLastAfState = -1; 926984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mLastAfFrameNumber = -1; 927984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mLastAeFrameNumber = -1; 928984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 929984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 930984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher @Override 931a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, 932a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureFailure failure) { 933a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.e(TAG, "Capture attempt failed with reason " + failure.getReason()); 934a0842b40441db5332a5290f941021636b1182761Sol Boucher }}; 935a0842b40441db5332a5290f941021636b1182761Sol Boucher } 936a0842b40441db5332a5290f941021636b1182761Sol Boucher 937a0842b40441db5332a5290f941021636b1182761Sol Boucher private class AndroidCamera2ProxyImpl extends CameraAgent.CameraProxy { 938a0842b40441db5332a5290f941021636b1182761Sol Boucher private final int mCameraIndex; 939a0842b40441db5332a5290f941021636b1182761Sol Boucher private final CameraDevice mCamera; 940a0842b40441db5332a5290f941021636b1182761Sol Boucher private final CameraDeviceInfo.Characteristics mCharacteristics; 941a0842b40441db5332a5290f941021636b1182761Sol Boucher private final AndroidCamera2Capabilities mCapabilities; 94280cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher private CameraSettings mLastSettings; 943415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher private boolean mShutterSoundEnabled; 944a0842b40441db5332a5290f941021636b1182761Sol Boucher 945a0842b40441db5332a5290f941021636b1182761Sol Boucher public AndroidCamera2ProxyImpl(int cameraIndex, CameraDevice camera, 946a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraDeviceInfo.Characteristics characteristics, 947a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraCharacteristics properties) { 948a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraIndex = cameraIndex; 949a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera = camera; 950a0842b40441db5332a5290f941021636b1182761Sol Boucher mCharacteristics = characteristics; 951a0842b40441db5332a5290f941021636b1182761Sol Boucher mCapabilities = new AndroidCamera2Capabilities(properties); 95280cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher mLastSettings = null; 953415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher mShutterSoundEnabled = true; 954a0842b40441db5332a5290f941021636b1182761Sol Boucher } 955a0842b40441db5332a5290f941021636b1182761Sol Boucher 956a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 957a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 958a0842b40441db5332a5290f941021636b1182761Sol Boucher public android.hardware.Camera getCamera() { return null; } 959a0842b40441db5332a5290f941021636b1182761Sol Boucher 960a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 961a0842b40441db5332a5290f941021636b1182761Sol Boucher public int getCameraId() { 962a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraIndex; 963a0842b40441db5332a5290f941021636b1182761Sol Boucher } 964a0842b40441db5332a5290f941021636b1182761Sol Boucher 965a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 966a0842b40441db5332a5290f941021636b1182761Sol Boucher public CameraDeviceInfo.Characteristics getCharacteristics() { 967a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCharacteristics; 968a0842b40441db5332a5290f941021636b1182761Sol Boucher } 969a0842b40441db5332a5290f941021636b1182761Sol Boucher 970a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 971a0842b40441db5332a5290f941021636b1182761Sol Boucher public CameraCapabilities getCapabilities() { 972a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCapabilities; 973a0842b40441db5332a5290f941021636b1182761Sol Boucher } 974a0842b40441db5332a5290f941021636b1182761Sol Boucher 975a0842b40441db5332a5290f941021636b1182761Sol Boucher private AndroidCamera2Capabilities getSpecializedCapabilities() { 976a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCapabilities; 977a0842b40441db5332a5290f941021636b1182761Sol Boucher } 978a0842b40441db5332a5290f941021636b1182761Sol Boucher 9792569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // FIXME: Unlock the sizes in stopPreview(), as per the corresponding 9802569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // explanation on the STOP_PREVIEW case in the handler. 9812569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher @Override 9822569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher public void setPreviewTexture(SurfaceTexture surfaceTexture) { 9832569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // Once the Surface has been selected, we configure the session and 9842569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // are no longer able to change the sizes. 9852569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher getSettings().setSizesLocked(true); 9862569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher super.setPreviewTexture(surfaceTexture); 9872569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher } 9882569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher 9892569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // FIXME: Unlock the sizes in stopPreview(), as per the corresponding 9902569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // explanation on the STOP_PREVIEW case in the handler. 9912569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher @Override 9922569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher public void setPreviewTextureSync(SurfaceTexture surfaceTexture) { 9932569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // Once the Surface has been selected, we configure the session and 9942569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // are no longer able to change the sizes. 9952569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher getSettings().setSizesLocked(true); 9962569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher super.setPreviewTexture(surfaceTexture); 9972569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher } 9982569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher 999a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 1000a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1001a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setPreviewDataCallback(Handler handler, CameraPreviewDataCallback cb) {} 1002a0842b40441db5332a5290f941021636b1182761Sol Boucher 1003a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 1004a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1005a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setOneShotPreviewCallback(Handler handler, CameraPreviewDataCallback cb) {} 1006a0842b40441db5332a5290f941021636b1182761Sol Boucher 1007a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 1008a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1009a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setPreviewDataCallbackWithBuffer(Handler handler, CameraPreviewDataCallback cb) 1010a0842b40441db5332a5290f941021636b1182761Sol Boucher {} 1011a0842b40441db5332a5290f941021636b1182761Sol Boucher 101250f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher // TODO: Implement 101350f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher public void addCallbackBuffer(final byte[] callbackBuffer) {} 101450f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher 1015a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1016a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void autoFocus(final Handler handler, final CameraAFCallback cb) { 1017a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mDispatchThread.runJob(new Runnable() { 1018a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 1019a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void run() { 1020a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CameraAFCallback cbForward = null; 1021a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (cb != null) { 1022a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher cbForward = new CameraAFCallback() { 1023a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 1024a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onAutoFocus(final boolean focused, 1025a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher final CameraProxy camera) { 1026a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher handler.post(new Runnable() { 1027a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 1028a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void run() { 1029a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher cb.onAutoFocus(focused, camera); 1030a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}); 1031a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}; 1032a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 1033a0842b40441db5332a5290f941021636b1182761Sol Boucher 1034a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraState.waitForStates(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE | 1035a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED); 1036a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraHandler.obtainMessage(CameraActions.AUTO_FOCUS, cbForward) 1037a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher .sendToTarget(); 1038a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}); 1039a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 1040a0842b40441db5332a5290f941021636b1182761Sol Boucher 1041a0842b40441db5332a5290f941021636b1182761Sol Boucher @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 1042a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1043a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void setAutoFocusMoveCallback(final Handler handler, final CameraAFMoveCallback cb) { 1044a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mDispatchThread.runJob(new Runnable() { 1045a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 1046a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void run() { 1047a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CameraAFMoveCallback cbForward = null; 1048a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (cb != null) { 1049a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher cbForward = new CameraAFMoveCallback() { 1050a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 1051a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onAutoFocusMoving(final boolean moving, 1052a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher final CameraProxy camera) { 1053a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher handler.post(new Runnable() { 1054a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 1055a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void run() { 1056a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher cb.onAutoFocusMoving(moving, camera); 1057a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}); 1058a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}; 1059a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 1060a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 1061a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraHandler.obtainMessage(CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK, 1062a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher cbForward).sendToTarget(); 1063a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}); 1064a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 1065a0842b40441db5332a5290f941021636b1182761Sol Boucher 1066a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1067de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public void takePicture(final Handler handler, 1068de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher final CameraShutterCallback shutter, 1069a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraPictureCallback raw, 1070a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraPictureCallback postview, 1071de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher final CameraPictureCallback jpeg) { 1072de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // TODO: We never call raw or postview 1073de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher final CaptureAvailableListener picListener = 1074de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher new CaptureAvailableListener() { 1075de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher @Override 1076de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, 1077171362f843c1e7623f29db1781176f85b1f74815Eino-Ville Talvala long timestamp, long frameNumber) { 1078de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (shutter != null) { 1079de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher handler.post(new Runnable() { 1080de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher @Override 1081de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public void run() { 1082415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher if (mShutterSoundEnabled) { 1083415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher mNoisemaker.play(MediaActionSound.SHUTTER_CLICK); 1084415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher } 1085de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher shutter.onShutter(AndroidCamera2ProxyImpl.this); 1086de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher }}); 1087de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1088de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1089a0842b40441db5332a5290f941021636b1182761Sol Boucher 1090de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher @Override 1091de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public void onImageAvailable(ImageReader reader) { 1092de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher try (Image image = reader.acquireNextImage()) { 1093de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (jpeg != null) { 1094de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher ByteBuffer buffer = image.getPlanes()[0].getBuffer(); 1095de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher final byte[] pixels = new byte[buffer.remaining()]; 1096de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher buffer.get(pixels); 1097de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher handler.post(new Runnable() { 1098de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher @Override 1099de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public void run() { 1100de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher jpeg.onPictureTaken(pixels, AndroidCamera2ProxyImpl.this); 1101de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher }}); 1102de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1103de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1104de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher }}; 1105de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mDispatchThread.runJob(new Runnable() { 1106de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher @Override 1107de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public void run() { 1108772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher // Wait until PREVIEW_ACTIVE or better 1109772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher mCameraState.waitForStates( 1110772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher ~(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE - 1)); 1111de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mCameraHandler.obtainMessage(CameraActions.CAPTURE_PHOTO, picListener) 1112de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher .sendToTarget(); 1113de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher }}); 1114de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1115a0842b40441db5332a5290f941021636b1182761Sol Boucher 1116a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 1117a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1118a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setZoomChangeListener(android.hardware.Camera.OnZoomChangeListener listener) {} 1119a0842b40441db5332a5290f941021636b1182761Sol Boucher 1120a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 1121a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1122a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setFaceDetectionCallback(Handler handler, CameraFaceDetectionCallback callback) 1123a0842b40441db5332a5290f941021636b1182761Sol Boucher {} 1124a0842b40441db5332a5290f941021636b1182761Sol Boucher 1125a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Remove this method override once we handle this message 1126a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1127a0842b40441db5332a5290f941021636b1182761Sol Boucher public void startFaceDetection() {} 1128a0842b40441db5332a5290f941021636b1182761Sol Boucher 1129a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // TODO: Remove this method override once we handle this message 1130a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 1131a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void stopFaceDetection() {} 1132a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 1133a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 1134a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1135a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setErrorCallback(Handler handler, CameraErrorCallback cb) {} 1136a0842b40441db5332a5290f941021636b1182761Sol Boucher 1137a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 1138a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1139a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setParameters(android.hardware.Camera.Parameters params) {} 1140a0842b40441db5332a5290f941021636b1182761Sol Boucher 1141a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 1142a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1143a0842b40441db5332a5290f941021636b1182761Sol Boucher public android.hardware.Camera.Parameters getParameters() { return null; } 1144a0842b40441db5332a5290f941021636b1182761Sol Boucher 1145a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1146a0842b40441db5332a5290f941021636b1182761Sol Boucher public CameraSettings getSettings() { 114780cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher if (mLastSettings == null) { 114880cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher mLastSettings = mCameraHandler.buildSettings(mCapabilities); 114980cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher } 115080cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher return mLastSettings; 1151a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1152a0842b40441db5332a5290f941021636b1182761Sol Boucher 1153a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1154a0842b40441db5332a5290f941021636b1182761Sol Boucher public boolean applySettings(CameraSettings settings) { 1155de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (settings == null) { 1156de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.w(TAG, "null parameters in applySettings()"); 1157de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return false; 1158de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1159de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (!(settings instanceof AndroidCamera2Settings)) { 1160de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.e(TAG, "Provided settings not compatible with the backing framework API"); 1161de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return false; 1162de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1163de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 1164772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher // Wait for any state that isn't OPENED 1165772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher if (applySettingsHelper(settings, ~AndroidCamera2StateHolder.CAMERA_UNOPENED)) { 116680cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher mLastSettings = settings; 116780cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher return true; 116880cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher } 116980cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher return false; 1170a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1171a0842b40441db5332a5290f941021636b1182761Sol Boucher 1172415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher @Override 1173415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher public void enableShutterSound(boolean enable) { 1174415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher mShutterSoundEnabled = enable; 1175415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher } 1176415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher 1177a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 1178a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1179a0842b40441db5332a5290f941021636b1182761Sol Boucher public String dumpDeviceSettings() { return null; } 1180a0842b40441db5332a5290f941021636b1182761Sol Boucher 1181a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1182a0842b40441db5332a5290f941021636b1182761Sol Boucher public Handler getCameraHandler() { 1183a0842b40441db5332a5290f941021636b1182761Sol Boucher return AndroidCamera2AgentImpl.this.getCameraHandler(); 1184a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1185a0842b40441db5332a5290f941021636b1182761Sol Boucher 1186a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1187a0842b40441db5332a5290f941021636b1182761Sol Boucher public DispatchThread getDispatchThread() { 1188a0842b40441db5332a5290f941021636b1182761Sol Boucher return AndroidCamera2AgentImpl.this.getDispatchThread(); 1189a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1190a0842b40441db5332a5290f941021636b1182761Sol Boucher 1191a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1192a0842b40441db5332a5290f941021636b1182761Sol Boucher public CameraStateHolder getCameraState() { 1193a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraState; 1194a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1195a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1196a0842b40441db5332a5290f941021636b1182761Sol Boucher 1197a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** A linear state machine: each state entails all the states below it. */ 1198a0842b40441db5332a5290f941021636b1182761Sol Boucher private static class AndroidCamera2StateHolder extends CameraStateHolder { 1199a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Usage flow: openCamera() -> applySettings() -> setPreviewTexture() -> startPreview() -> 1200a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // autoFocus() -> takePicture() 1201772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher // States are mutually exclusive, but must be separate bits so that they can be used with 1202772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher // the StateHolder#waitForStates() and StateHolder#waitToAvoidStates() methods. 1203772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher // Do not set the state to be a combination of these values! 1204a0842b40441db5332a5290f941021636b1182761Sol Boucher /* Camera states */ 1205a0842b40441db5332a5290f941021636b1182761Sol Boucher /** No camera device is opened. */ 1206772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher public static final int CAMERA_UNOPENED = 1 << 0; 1207a0842b40441db5332a5290f941021636b1182761Sol Boucher /** A camera is opened, but no settings have been provided. */ 1208772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher public static final int CAMERA_UNCONFIGURED = 1 << 1; 1209a0842b40441db5332a5290f941021636b1182761Sol Boucher /** The open camera has been configured by providing it with settings. */ 1210772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher public static final int CAMERA_CONFIGURED = 1 << 2; 1211a0842b40441db5332a5290f941021636b1182761Sol Boucher /** A capture session is ready to stream a preview, but still has no repeating request. */ 1212772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher public static final int CAMERA_PREVIEW_READY = 1 << 3; 1213a0842b40441db5332a5290f941021636b1182761Sol Boucher /** A preview is currently being streamed. */ 1214772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher public static final int CAMERA_PREVIEW_ACTIVE = 1 << 4; 1215a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** The lens is locked on a particular region. */ 1216772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher public static final int CAMERA_FOCUS_LOCKED = 1 << 5; 1217a0842b40441db5332a5290f941021636b1182761Sol Boucher 1218a0842b40441db5332a5290f941021636b1182761Sol Boucher public AndroidCamera2StateHolder() { 1219a0842b40441db5332a5290f941021636b1182761Sol Boucher this(CAMERA_UNOPENED); 1220a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1221a0842b40441db5332a5290f941021636b1182761Sol Boucher 1222a0842b40441db5332a5290f941021636b1182761Sol Boucher public AndroidCamera2StateHolder(int state) { 12237e0d39bf7b6e0f0df606e3f6c15f673f70fed3f7Sol Boucher super(state); 1224a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1225a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1226a0842b40441db5332a5290f941021636b1182761Sol Boucher 1227a0842b40441db5332a5290f941021636b1182761Sol Boucher private static class AndroidCamera2DeviceInfo implements CameraDeviceInfo { 1228a0842b40441db5332a5290f941021636b1182761Sol Boucher private final CameraManager mCameraManager; 1229a0842b40441db5332a5290f941021636b1182761Sol Boucher private final String[] mCameraIds; 1230a0842b40441db5332a5290f941021636b1182761Sol Boucher private final int mNumberOfCameras; 1231a0842b40441db5332a5290f941021636b1182761Sol Boucher private final int mFirstBackCameraId; 1232a0842b40441db5332a5290f941021636b1182761Sol Boucher private final int mFirstFrontCameraId; 1233a0842b40441db5332a5290f941021636b1182761Sol Boucher 1234a0842b40441db5332a5290f941021636b1182761Sol Boucher public AndroidCamera2DeviceInfo(CameraManager cameraManager, 1235a0842b40441db5332a5290f941021636b1182761Sol Boucher String[] cameraIds, int numberOfCameras) { 1236a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraManager = cameraManager; 1237a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraIds = cameraIds; 1238a0842b40441db5332a5290f941021636b1182761Sol Boucher mNumberOfCameras = numberOfCameras; 1239a0842b40441db5332a5290f941021636b1182761Sol Boucher 1240a0842b40441db5332a5290f941021636b1182761Sol Boucher int firstBackId = NO_DEVICE; 1241a0842b40441db5332a5290f941021636b1182761Sol Boucher int firstFrontId = NO_DEVICE; 1242a0842b40441db5332a5290f941021636b1182761Sol Boucher for (int id = 0; id < cameraIds.length; ++id) { 1243a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 1244a0842b40441db5332a5290f941021636b1182761Sol Boucher int lensDirection = cameraManager.getCameraCharacteristics(cameraIds[id]) 1245a0842b40441db5332a5290f941021636b1182761Sol Boucher .get(CameraCharacteristics.LENS_FACING); 1246a0842b40441db5332a5290f941021636b1182761Sol Boucher if (firstBackId == NO_DEVICE && 1247a0842b40441db5332a5290f941021636b1182761Sol Boucher lensDirection == CameraCharacteristics.LENS_FACING_BACK) { 1248a0842b40441db5332a5290f941021636b1182761Sol Boucher firstBackId = id; 1249a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1250a0842b40441db5332a5290f941021636b1182761Sol Boucher if (firstFrontId == NO_DEVICE && 1251a0842b40441db5332a5290f941021636b1182761Sol Boucher lensDirection == CameraCharacteristics.LENS_FACING_FRONT) { 1252a0842b40441db5332a5290f941021636b1182761Sol Boucher firstFrontId = id; 1253a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1254a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (CameraAccessException ex) { 1255a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.w(TAG, "Couldn't get characteristics of camera '" + id + "'", ex); 1256a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1257a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1258a0842b40441db5332a5290f941021636b1182761Sol Boucher mFirstBackCameraId = firstBackId; 1259a0842b40441db5332a5290f941021636b1182761Sol Boucher mFirstFrontCameraId = firstFrontId; 1260a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1261a0842b40441db5332a5290f941021636b1182761Sol Boucher 1262a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1263a0842b40441db5332a5290f941021636b1182761Sol Boucher public Characteristics getCharacteristics(int cameraId) { 1264a0842b40441db5332a5290f941021636b1182761Sol Boucher String actualId = mCameraIds[cameraId]; 1265a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 1266a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraCharacteristics info = mCameraManager.getCameraCharacteristics(actualId); 1267a0842b40441db5332a5290f941021636b1182761Sol Boucher return new AndroidCharacteristics2(info); 1268a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (CameraAccessException ex) { 1269a0842b40441db5332a5290f941021636b1182761Sol Boucher return null; 1270a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1271a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1272a0842b40441db5332a5290f941021636b1182761Sol Boucher 1273a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1274a0842b40441db5332a5290f941021636b1182761Sol Boucher public int getNumberOfCameras() { 1275a0842b40441db5332a5290f941021636b1182761Sol Boucher return mNumberOfCameras; 1276a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1277a0842b40441db5332a5290f941021636b1182761Sol Boucher 1278a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1279a0842b40441db5332a5290f941021636b1182761Sol Boucher public int getFirstBackCameraId() { 1280a0842b40441db5332a5290f941021636b1182761Sol Boucher return mFirstBackCameraId; 1281a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1282a0842b40441db5332a5290f941021636b1182761Sol Boucher 1283a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1284a0842b40441db5332a5290f941021636b1182761Sol Boucher public int getFirstFrontCameraId() { 1285a0842b40441db5332a5290f941021636b1182761Sol Boucher return mFirstFrontCameraId; 1286a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1287a0842b40441db5332a5290f941021636b1182761Sol Boucher 1288de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher private static class AndroidCharacteristics2 extends Characteristics { 1289a0842b40441db5332a5290f941021636b1182761Sol Boucher private CameraCharacteristics mCameraInfo; 1290a0842b40441db5332a5290f941021636b1182761Sol Boucher 1291a0842b40441db5332a5290f941021636b1182761Sol Boucher AndroidCharacteristics2(CameraCharacteristics cameraInfo) { 1292a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraInfo = cameraInfo; 1293a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1294a0842b40441db5332a5290f941021636b1182761Sol Boucher 1295a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1296a0842b40441db5332a5290f941021636b1182761Sol Boucher public boolean isFacingBack() { 1297a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraInfo.get(CameraCharacteristics.LENS_FACING) 1298a0842b40441db5332a5290f941021636b1182761Sol Boucher .equals(CameraCharacteristics.LENS_FACING_BACK); 1299a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1300a0842b40441db5332a5290f941021636b1182761Sol Boucher 1301a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1302a0842b40441db5332a5290f941021636b1182761Sol Boucher public boolean isFacingFront() { 1303a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraInfo.get(CameraCharacteristics.LENS_FACING) 1304a0842b40441db5332a5290f941021636b1182761Sol Boucher .equals(CameraCharacteristics.LENS_FACING_FRONT); 1305a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1306a0842b40441db5332a5290f941021636b1182761Sol Boucher 1307a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1308a0842b40441db5332a5290f941021636b1182761Sol Boucher public int getSensorOrientation() { 1309a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraInfo.get(CameraCharacteristics.SENSOR_ORIENTATION); 1310a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1311a0842b40441db5332a5290f941021636b1182761Sol Boucher 1312a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1313f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher public Matrix getPreviewTransform(int currentDisplayOrientation, 1314f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher RectF surfaceDimensions, 1315f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher RectF desiredBounds) { 1316f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher if (!orientationIsValid(currentDisplayOrientation)) { 1317f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return new Matrix(); 1318f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 1319f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher 1320f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher // The system transparently transforms the image to fill the surface 1321f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher // when the device is in its natural orientation. We rotate the 1322f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher // coordinates of the rectangle's corners to be relative to the 1323f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher // original image, instead of to the current screen orientation. 1324f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher float[] surfacePolygon = rotate(convertRectToPoly(surfaceDimensions), 1325f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher 2 * currentDisplayOrientation / 90); 1326f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher float[] desiredPolygon = convertRectToPoly(desiredBounds); 1327f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher 1328f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher Matrix transform = new Matrix(); 1329f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher // Use polygons instead of rectangles so that rotation will be 1330f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher // calculated, since that is not done by the new camera API. 1331f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher transform.setPolyToPoly(surfacePolygon, 0, desiredPolygon, 0, 4); 1332f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return transform; 1333f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 1334f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher 1335f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher @Override 1336a0842b40441db5332a5290f941021636b1182761Sol Boucher public boolean canDisableShutterSound() { 1337415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher return true; 1338a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1339f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher 1340f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher private static float[] convertRectToPoly(RectF rf) { 1341f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return new float[] {rf.left, rf.top, rf.right, rf.top, 1342f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher rf.right, rf.bottom, rf.left, rf.bottom}; 1343f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 1344f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher 1345f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher private static float[] rotate(float[] arr, int times) { 1346f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher if (times < 0) { 1347f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher times = times % arr.length + arr.length; 1348f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 1349f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher 1350f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher float[] res = new float[arr.length]; 1351f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher for (int offset = 0; offset < arr.length; ++offset) { 1352f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher res[offset] = arr[(times + offset) % arr.length]; 1353f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 1354f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return res; 1355f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 1356a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1357a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1358a0842b40441db5332a5290f941021636b1182761Sol Boucher 1359a0842b40441db5332a5290f941021636b1182761Sol Boucher private static final CameraExceptionCallback sCameraExceptionCallback = 1360a0842b40441db5332a5290f941021636b1182761Sol Boucher new CameraExceptionCallback() { 1361a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1362a0842b40441db5332a5290f941021636b1182761Sol Boucher public synchronized void onCameraException(RuntimeException e) { 1363a0842b40441db5332a5290f941021636b1182761Sol Boucher throw e; 1364a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1365a0842b40441db5332a5290f941021636b1182761Sol Boucher }; 1366a0842b40441db5332a5290f941021636b1182761Sol Boucher} 1367