AndroidCamera2AgentImpl.java revision a97b7d1192e246a5f738991adca37cce282e1382
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; 21a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.graphics.Rect; 22a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.graphics.SurfaceTexture; 23a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.hardware.camera2.CameraAccessException; 24a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.hardware.camera2.CameraCaptureSession; 25a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.hardware.camera2.CameraCharacteristics; 26a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.hardware.camera2.CameraDevice; 27a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.hardware.camera2.CameraManager; 28a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.hardware.camera2.CaptureFailure; 29a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.hardware.camera2.CaptureRequest; 30a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.hardware.camera2.CaptureResult; 31a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.hardware.camera2.TotalCaptureResult; 32a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.hardware.camera2.params.MeteringRectangle; 33a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.os.Build; 34a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.os.Handler; 35a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.os.HandlerThread; 36a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.os.Looper; 37a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.os.Message; 38a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.view.Surface; 39a0842b40441db5332a5290f941021636b1182761Sol Boucher 40a0842b40441db5332a5290f941021636b1182761Sol Boucherimport com.android.ex.camera2.portability.debug.Log; 41a0842b40441db5332a5290f941021636b1182761Sol Boucher 42a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.ArrayList; 43a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.Arrays; 44a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.HashSet; 45a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.List; 46a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.Set; 47a0842b40441db5332a5290f941021636b1182761Sol Boucher 48a0842b40441db5332a5290f941021636b1182761Sol Boucher/** 49a0842b40441db5332a5290f941021636b1182761Sol Boucher * A class to implement {@link CameraAgent} of the Android camera2 framework. 50a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 51a0842b40441db5332a5290f941021636b1182761Sol Boucherclass AndroidCamera2AgentImpl extends CameraAgent { 52a0842b40441db5332a5290f941021636b1182761Sol Boucher private static final Log.Tag TAG = new Log.Tag("AndCam2AgntImp"); 53a0842b40441db5332a5290f941021636b1182761Sol Boucher 54a0842b40441db5332a5290f941021636b1182761Sol Boucher private final Camera2Handler mCameraHandler; 55a0842b40441db5332a5290f941021636b1182761Sol Boucher private final HandlerThread mCameraHandlerThread; 56a0842b40441db5332a5290f941021636b1182761Sol Boucher private final CameraStateHolder mCameraState; 57a0842b40441db5332a5290f941021636b1182761Sol Boucher private final DispatchThread mDispatchThread; 58a0842b40441db5332a5290f941021636b1182761Sol Boucher private final CameraManager mCameraManager; 59a0842b40441db5332a5290f941021636b1182761Sol Boucher 60a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 61a0842b40441db5332a5290f941021636b1182761Sol Boucher * Number of camera devices. The length of {@code mCameraDevices} does not reveal this 62a0842b40441db5332a5290f941021636b1182761Sol Boucher * information because that list may contain since-invalidated indices. 63a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 64a0842b40441db5332a5290f941021636b1182761Sol Boucher private int mNumCameraDevices; 65a0842b40441db5332a5290f941021636b1182761Sol Boucher 66a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 67a0842b40441db5332a5290f941021636b1182761Sol Boucher * Transformation between integral camera indices and the {@link java.lang.String} indices used 68a0842b40441db5332a5290f941021636b1182761Sol Boucher * by the underlying API. Note that devices may disappear because they've been disconnected or 69a0842b40441db5332a5290f941021636b1182761Sol Boucher * have otherwise gone offline. Because we need to keep the meanings of whatever indices we 70a0842b40441db5332a5290f941021636b1182761Sol Boucher * expose stable, we cannot simply remove them in such a case; instead, we insert {@code null}s 71a0842b40441db5332a5290f941021636b1182761Sol Boucher * to invalidate any such indices. Whenever new devices appear, they are appended to the end of 72a0842b40441db5332a5290f941021636b1182761Sol Boucher * the list, and thereby assigned the lowest index that has never yet been used. 73a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 74a0842b40441db5332a5290f941021636b1182761Sol Boucher private final List<String> mCameraDevices; 75a0842b40441db5332a5290f941021636b1182761Sol Boucher 76a0842b40441db5332a5290f941021636b1182761Sol Boucher AndroidCamera2AgentImpl(Context context) { 77a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraHandlerThread = new HandlerThread("Camera2 Handler Thread"); 78a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraHandlerThread.start(); 79a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraHandler = new Camera2Handler(mCameraHandlerThread.getLooper()); 80a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraState = new AndroidCamera2StateHolder(); 81a0842b40441db5332a5290f941021636b1182761Sol Boucher mDispatchThread = new DispatchThread(mCameraHandler, mCameraHandlerThread); 82a0842b40441db5332a5290f941021636b1182761Sol Boucher mDispatchThread.start(); 83a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); 84a0842b40441db5332a5290f941021636b1182761Sol Boucher 85a0842b40441db5332a5290f941021636b1182761Sol Boucher mNumCameraDevices = 0; 86a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraDevices = new ArrayList<String>(); 87a0842b40441db5332a5290f941021636b1182761Sol Boucher updateCameraDevices(); 88a0842b40441db5332a5290f941021636b1182761Sol Boucher } 89a0842b40441db5332a5290f941021636b1182761Sol Boucher 90a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 91a0842b40441db5332a5290f941021636b1182761Sol Boucher * Updates the camera device index assignments stored in {@link mCameraDevices}, without 92a0842b40441db5332a5290f941021636b1182761Sol Boucher * reappropriating any currently-assigned index. 93a0842b40441db5332a5290f941021636b1182761Sol Boucher * @return Whether the operation was successful 94a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 95a0842b40441db5332a5290f941021636b1182761Sol Boucher private boolean updateCameraDevices() { 96a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 97a0842b40441db5332a5290f941021636b1182761Sol Boucher String[] currentCameraDevices = mCameraManager.getCameraIdList(); 98a0842b40441db5332a5290f941021636b1182761Sol Boucher Set<String> currentSet = new HashSet<String>(Arrays.asList(currentCameraDevices)); 99a0842b40441db5332a5290f941021636b1182761Sol Boucher 100a0842b40441db5332a5290f941021636b1182761Sol Boucher // Invalidate the indices assigned to any camera devices that are no longer present 101a0842b40441db5332a5290f941021636b1182761Sol Boucher for (int index = 0; index < mCameraDevices.size(); ++index) { 102a0842b40441db5332a5290f941021636b1182761Sol Boucher if (!currentSet.contains(mCameraDevices.get(index))) { 103a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraDevices.set(index, null); 104a0842b40441db5332a5290f941021636b1182761Sol Boucher --mNumCameraDevices; 105a0842b40441db5332a5290f941021636b1182761Sol Boucher } 106a0842b40441db5332a5290f941021636b1182761Sol Boucher } 107a0842b40441db5332a5290f941021636b1182761Sol Boucher 108a0842b40441db5332a5290f941021636b1182761Sol Boucher // Assign fresh indices to any new camera devices 109a0842b40441db5332a5290f941021636b1182761Sol Boucher currentSet.removeAll(mCameraDevices); // The devices we didn't know about 110a0842b40441db5332a5290f941021636b1182761Sol Boucher for (String device : currentCameraDevices) { 111a0842b40441db5332a5290f941021636b1182761Sol Boucher if (currentSet.contains(device)) { 112a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraDevices.add(device); 113a0842b40441db5332a5290f941021636b1182761Sol Boucher ++mNumCameraDevices; 114a0842b40441db5332a5290f941021636b1182761Sol Boucher } 115a0842b40441db5332a5290f941021636b1182761Sol Boucher } 116a0842b40441db5332a5290f941021636b1182761Sol Boucher 117a0842b40441db5332a5290f941021636b1182761Sol Boucher return true; 118a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (CameraAccessException ex) { 119a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "Could not get device listing from camera subsystem", ex); 120a0842b40441db5332a5290f941021636b1182761Sol Boucher return false; 121a0842b40441db5332a5290f941021636b1182761Sol Boucher } 122a0842b40441db5332a5290f941021636b1182761Sol Boucher } 123a0842b40441db5332a5290f941021636b1182761Sol Boucher 124a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 125a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 126a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setCameraDefaultExceptionCallback(CameraExceptionCallback callback, 127a0842b40441db5332a5290f941021636b1182761Sol Boucher Handler handler) {} 128a0842b40441db5332a5290f941021636b1182761Sol Boucher 129a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 130a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 131a0842b40441db5332a5290f941021636b1182761Sol Boucher public void recycle() {} 132a0842b40441db5332a5290f941021636b1182761Sol Boucher 133a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Some indices may now be invalid; ensure everyone can handle that and update the docs 134a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 135a0842b40441db5332a5290f941021636b1182761Sol Boucher public CameraDeviceInfo getCameraDeviceInfo() { 136a0842b40441db5332a5290f941021636b1182761Sol Boucher updateCameraDevices(); 137a0842b40441db5332a5290f941021636b1182761Sol Boucher return new AndroidCamera2DeviceInfo(mCameraManager, mCameraDevices.toArray(new String[0]), 138a0842b40441db5332a5290f941021636b1182761Sol Boucher mNumCameraDevices); 139a0842b40441db5332a5290f941021636b1182761Sol Boucher } 140a0842b40441db5332a5290f941021636b1182761Sol Boucher 141a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 142a0842b40441db5332a5290f941021636b1182761Sol Boucher protected Handler getCameraHandler() { 143a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraHandler; 144a0842b40441db5332a5290f941021636b1182761Sol Boucher } 145a0842b40441db5332a5290f941021636b1182761Sol Boucher 146a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 147a0842b40441db5332a5290f941021636b1182761Sol Boucher protected DispatchThread getDispatchThread() { 148a0842b40441db5332a5290f941021636b1182761Sol Boucher return mDispatchThread; 149a0842b40441db5332a5290f941021636b1182761Sol Boucher } 150a0842b40441db5332a5290f941021636b1182761Sol Boucher 151a0842b40441db5332a5290f941021636b1182761Sol Boucher private class Camera2Handler extends HistoryHandler { 152a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Caller-provided when leaving CAMERA_UNOPENED state: 153a0842b40441db5332a5290f941021636b1182761Sol Boucher private CameraOpenCallback mOpenCallback; 154a0842b40441db5332a5290f941021636b1182761Sol Boucher private int mCameraIndex; 155a0842b40441db5332a5290f941021636b1182761Sol Boucher private String mCameraId; 156a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 157a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Available in CAMERA_UNCONFIGURED state and above: 158a0842b40441db5332a5290f941021636b1182761Sol Boucher private CameraDevice mCamera; 159a0842b40441db5332a5290f941021636b1182761Sol Boucher private AndroidCamera2ProxyImpl mCameraProxy; 160a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private CaptureRequest.Builder mPersistentRequestBuilder; 161a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private Rect mActiveArray; 162a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 163a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Available in CAMERA_CONFIGURED state and above: 164a0842b40441db5332a5290f941021636b1182761Sol Boucher private Size mPreviewSize; 165a0842b40441db5332a5290f941021636b1182761Sol Boucher private Size mPhotoSize; 166a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 167a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Available in PREVIEW_READY state and above: 168a0842b40441db5332a5290f941021636b1182761Sol Boucher private SurfaceTexture mPreviewTexture; 169a0842b40441db5332a5290f941021636b1182761Sol Boucher private Surface mPreviewSurface; 170a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private CameraCaptureSession mSession; 171a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 172a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Available from the beginning of PREVIEW_ACTIVE until the first preview frame arrives: 173a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private CameraStartPreviewCallback mOneshotPreviewingCallback; 174a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 175a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Available in FOCUS_LOCKED between AF trigger receipt and whenever the lens stops moving: 176a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private CameraAFCallback mOneshotAfCallback; 177a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 178a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Available whenever setAutoFocusMoveCallback() was last invoked with a non-null argument: 179a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private CameraAFMoveCallback mPassiveAfCallback; 180a0842b40441db5332a5290f941021636b1182761Sol Boucher 181a0842b40441db5332a5290f941021636b1182761Sol Boucher Camera2Handler(Looper looper) { 182a0842b40441db5332a5290f941021636b1182761Sol Boucher super(looper); 183a0842b40441db5332a5290f941021636b1182761Sol Boucher } 184a0842b40441db5332a5290f941021636b1182761Sol Boucher 185a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 186a0842b40441db5332a5290f941021636b1182761Sol Boucher public void handleMessage(final Message msg) { 187a0842b40441db5332a5290f941021636b1182761Sol Boucher super.handleMessage(msg); 188a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 189a0842b40441db5332a5290f941021636b1182761Sol Boucher switch(msg.what) { 190a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.OPEN_CAMERA: 191a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.RECONNECT: { 192a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj; 193a0842b40441db5332a5290f941021636b1182761Sol Boucher int cameraIndex = msg.arg1; 194a0842b40441db5332a5290f941021636b1182761Sol Boucher 195a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mCameraState.getState() != AndroidCamera2StateHolder.CAMERA_UNOPENED) { 196a0842b40441db5332a5290f941021636b1182761Sol Boucher openCallback.onDeviceOpenedAlready(cameraIndex, 197a0842b40441db5332a5290f941021636b1182761Sol Boucher generateHistoryString(cameraIndex)); 198a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 199a0842b40441db5332a5290f941021636b1182761Sol Boucher } 200a0842b40441db5332a5290f941021636b1182761Sol Boucher 201a0842b40441db5332a5290f941021636b1182761Sol Boucher mOpenCallback = openCallback; 202a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraIndex = cameraIndex; 203a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraId = mCameraDevices.get(mCameraIndex); 204a0842b40441db5332a5290f941021636b1182761Sol Boucher 205a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mCameraId == null) { 206a0842b40441db5332a5290f941021636b1182761Sol Boucher mOpenCallback.onCameraDisabled(msg.arg1); 207a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 208a0842b40441db5332a5290f941021636b1182761Sol Boucher } 209a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraManager.openCamera(mCameraId, mCameraDeviceStateListener, this); 210a0842b40441db5332a5290f941021636b1182761Sol Boucher 211a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 212a0842b40441db5332a5290f941021636b1182761Sol Boucher } 213a0842b40441db5332a5290f941021636b1182761Sol Boucher 214a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.RELEASE: { 215a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mCameraState.getState() == AndroidCamera2StateHolder.CAMERA_UNOPENED) { 216a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Ignoring release at inappropriate time"); 217a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher break; 218a0842b40441db5332a5290f941021636b1182761Sol Boucher } 219a0842b40441db5332a5290f941021636b1182761Sol Boucher 220a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mSession != null) { 221a0842b40441db5332a5290f941021636b1182761Sol Boucher closePreviewSession(); 222a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession = null; 223a0842b40441db5332a5290f941021636b1182761Sol Boucher } 224a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mCamera != null) { 225a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera.close(); 226a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera = null; 227a0842b40441db5332a5290f941021636b1182761Sol Boucher } 228a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraProxy = null; 229a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder = null; 230a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mActiveArray = null; 231a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mPreviewSurface != null) { 232a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewSurface.release(); 233a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewSurface = null; 234a0842b40441db5332a5290f941021636b1182761Sol Boucher } 235a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewTexture = null; 236a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewSize = null; 237a0842b40441db5332a5290f941021636b1182761Sol Boucher mPhotoSize = null; 238a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraIndex = 0; 239a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraId = null; 240a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraState.setState(AndroidCamera2StateHolder.CAMERA_UNOPENED); 241a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 242a0842b40441db5332a5290f941021636b1182761Sol Boucher } 243a0842b40441db5332a5290f941021636b1182761Sol Boucher 244a0842b40441db5332a5290f941021636b1182761Sol Boucher /*case CameraActions.UNLOCK: { 245a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 246a0842b40441db5332a5290f941021636b1182761Sol Boucher } 247a0842b40441db5332a5290f941021636b1182761Sol Boucher 248a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.LOCK: { 249a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 250a0842b40441db5332a5290f941021636b1182761Sol Boucher }*/ 251a0842b40441db5332a5290f941021636b1182761Sol Boucher 252a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_PREVIEW_TEXTURE_ASYNC: { 253a0842b40441db5332a5290f941021636b1182761Sol Boucher setPreviewTexture((SurfaceTexture) msg.obj); 254a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 255a0842b40441db5332a5290f941021636b1182761Sol Boucher } 256a0842b40441db5332a5290f941021636b1182761Sol Boucher 257a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.START_PREVIEW_ASYNC: { 258a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mCameraState.getState() != 259a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher AndroidCamera2StateHolder.CAMERA_PREVIEW_READY) { 260a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Provide better feedback here? 261a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Refusing to start preview at inappropriate time"); 262a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 263a0842b40441db5332a5290f941021636b1182761Sol Boucher } 264a0842b40441db5332a5290f941021636b1182761Sol Boucher 265a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mOneshotPreviewingCallback = (CameraStartPreviewCallback) msg.obj; 266a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE); 267a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher try { 268a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession.setRepeatingRequest(mPersistentRequestBuilder.build(), 269a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /*listener*/mCameraFocusStateListener, /*handler*/this); 270a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } catch(CameraAccessException ex) { 271a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Unable to start preview", ex); 272a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY); 273a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 274a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 275a0842b40441db5332a5290f941021636b1182761Sol Boucher } 276a0842b40441db5332a5290f941021636b1182761Sol Boucher 277a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.STOP_PREVIEW: { 278a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mCameraState.getState() < 279a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) { 280a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Refusing to stop preview at inappropriate time"); 281a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher break; 282a0842b40441db5332a5290f941021636b1182761Sol Boucher } 283a0842b40441db5332a5290f941021636b1182761Sol Boucher 284a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession.stopRepeating(); 285a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY); 286a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 287a0842b40441db5332a5290f941021636b1182761Sol Boucher } 288a0842b40441db5332a5290f941021636b1182761Sol Boucher 289a0842b40441db5332a5290f941021636b1182761Sol Boucher /*case CameraActions.SET_PREVIEW_CALLBACK_WITH_BUFFER: { 290a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 291a0842b40441db5332a5290f941021636b1182761Sol Boucher } 292a0842b40441db5332a5290f941021636b1182761Sol Boucher 293a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.ADD_CALLBACK_BUFFER: { 294a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 295a0842b40441db5332a5290f941021636b1182761Sol Boucher } 296a0842b40441db5332a5290f941021636b1182761Sol Boucher 297a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_PREVIEW_DISPLAY_ASYNC: { 298a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 299a0842b40441db5332a5290f941021636b1182761Sol Boucher } 300a0842b40441db5332a5290f941021636b1182761Sol Boucher 301a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_PREVIEW_CALLBACK: { 302a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 303a0842b40441db5332a5290f941021636b1182761Sol Boucher } 304a0842b40441db5332a5290f941021636b1182761Sol Boucher 305a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_ONE_SHOT_PREVIEW_CALLBACK: { 306a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 307a0842b40441db5332a5290f941021636b1182761Sol Boucher } 308a0842b40441db5332a5290f941021636b1182761Sol Boucher 309a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_PARAMETERS: { 310a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 311a0842b40441db5332a5290f941021636b1182761Sol Boucher } 312a0842b40441db5332a5290f941021636b1182761Sol Boucher 313a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.GET_PARAMETERS: { 314a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 315a0842b40441db5332a5290f941021636b1182761Sol Boucher } 316a0842b40441db5332a5290f941021636b1182761Sol Boucher 317a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.REFRESH_PARAMETERS: { 318a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 319a0842b40441db5332a5290f941021636b1182761Sol Boucher }*/ 320a0842b40441db5332a5290f941021636b1182761Sol Boucher 321a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.APPLY_SETTINGS: { 322a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraSettings settings = (CameraSettings) msg.obj; 323a0842b40441db5332a5290f941021636b1182761Sol Boucher applyToRequest(settings); 324a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 325a0842b40441db5332a5290f941021636b1182761Sol Boucher } 326a0842b40441db5332a5290f941021636b1182761Sol Boucher 327a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher case CameraActions.AUTO_FOCUS: { 328a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // We only support locking the focus while a preview is being displayed. 329a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // However, it can be requested multiple times in succession; the effect of 330a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // the subsequent invocations is determined by the focus mode defined in the 331a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // provided CameraSettings object. In passive (CONTINUOUS_*) mode, the 332a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // duplicate requests are no-ops and leave the lens locked at its current 333a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // position, but in active (AUTO) mode, they perform another scan and lock 334a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // once that is finished. In any manual focus mode, this call is a no-op, 335a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // and most notably, this is the only case where the callback isn't invoked. 336a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mCameraState.getState() < 337a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) { 338a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Ignoring attempt to autofocus without preview"); 339a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher break; 340a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 341a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 342a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // The earliest we can reliably tell whether the autofocus has locked in 343a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // response to our latest request is when our one-time capture completes. 344a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // However, it will probably take longer than that, so once that happens, 345a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // just start checking the repeating preview requests as they complete. 346a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher final CameraAFCallback callback = (CameraAFCallback) msg.obj; 347a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CameraCaptureSession.CaptureListener deferredCallbackSetter = 348a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher new CameraCaptureSession.CaptureListener() { 349a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 350a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onCaptureCompleted(CameraCaptureSession session, 351a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureRequest request, 352a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher TotalCaptureResult result) { 353a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Now our mCameraFocusStateListener will invoke the callback the 354a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // first time it finds the focus motor to be locked. 355a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mOneshotAfCallback = callback; 356a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 357a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 358a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 359a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onCaptureFailed(CameraCaptureSession session, 360a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureRequest request, 361a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureFailure failure) { 362a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.e(TAG, "Focusing failed with reason " + failure.getReason()); 363a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher callback.onAutoFocus(false, mCameraProxy); 364a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}; 365a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 366a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Send a one-time capture to trigger the camera driver to lock focus. 367a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraState.setState(AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED); 368a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, 369a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureRequest.CONTROL_AF_TRIGGER_START); 370a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher try { 371a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession.capture(mPersistentRequestBuilder.build(), 372a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /*listener*/deferredCallbackSetter, /*handler*/ this); 373a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } catch(CameraAccessException ex) { 374a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.e(TAG, "Unable to lock autofocus", ex); 375a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE); 376a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 377a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, 378a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureRequest.CONTROL_AF_TRIGGER_IDLE); 379a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 380a0842b40441db5332a5290f941021636b1182761Sol Boucher } 381a0842b40441db5332a5290f941021636b1182761Sol Boucher 382a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.CANCEL_AUTO_FOCUS: { 383a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Why would you want to unlock the lens if it isn't already locked? 384a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mCameraState.getState() < 385a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) { 386a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Ignoring attempt to release focus lock without preview"); 387a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher break; 388a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 389a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 390a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Send a one-time capture to trigger the camera driver to resume scanning. 391a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE); 392a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, 393a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureRequest.CONTROL_AF_TRIGGER_CANCEL); 394a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher try { 395a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession.capture(mPersistentRequestBuilder.build(), 396a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /*listener*/null, /*handler*/this); 397a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } catch(CameraAccessException ex) { 398a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.e(TAG, "Unable to cancel autofocus", ex); 399a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraState.setState( 400a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED); 401a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 402a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, 403a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureRequest.CONTROL_AF_TRIGGER_IDLE); 404a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 405a0842b40441db5332a5290f941021636b1182761Sol Boucher } 406a0842b40441db5332a5290f941021636b1182761Sol Boucher 407a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK: { 408a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPassiveAfCallback = (CameraAFMoveCallback) msg.obj; 409a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 410a0842b40441db5332a5290f941021636b1182761Sol Boucher } 411a0842b40441db5332a5290f941021636b1182761Sol Boucher 412a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /*case CameraActions.SET_ZOOM_CHANGE_LISTENER: { 413a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 414a0842b40441db5332a5290f941021636b1182761Sol Boucher } 415a0842b40441db5332a5290f941021636b1182761Sol Boucher 416a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_FACE_DETECTION_LISTENER: { 417a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 418a0842b40441db5332a5290f941021636b1182761Sol Boucher } 419a0842b40441db5332a5290f941021636b1182761Sol Boucher 420a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.START_FACE_DETECTION: { 421a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 422a0842b40441db5332a5290f941021636b1182761Sol Boucher } 423a0842b40441db5332a5290f941021636b1182761Sol Boucher 424a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.STOP_FACE_DETECTION: { 425a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 426a0842b40441db5332a5290f941021636b1182761Sol Boucher } 427a0842b40441db5332a5290f941021636b1182761Sol Boucher 428a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_ERROR_CALLBACK: { 429a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 430a0842b40441db5332a5290f941021636b1182761Sol Boucher } 431a0842b40441db5332a5290f941021636b1182761Sol Boucher 432a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.ENABLE_SHUTTER_SOUND: { 433a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 434a0842b40441db5332a5290f941021636b1182761Sol Boucher } 435a0842b40441db5332a5290f941021636b1182761Sol Boucher 436a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.SET_DISPLAY_ORIENTATION: { 437a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 438a0842b40441db5332a5290f941021636b1182761Sol Boucher } 439a0842b40441db5332a5290f941021636b1182761Sol Boucher 440a0842b40441db5332a5290f941021636b1182761Sol Boucher case CameraActions.CAPTURE_PHOTO: { 441a0842b40441db5332a5290f941021636b1182761Sol Boucher break; 442a0842b40441db5332a5290f941021636b1182761Sol Boucher }*/ 443a0842b40441db5332a5290f941021636b1182761Sol Boucher 444a0842b40441db5332a5290f941021636b1182761Sol Boucher default: { 445a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Rephrase once everything has been implemented 446a0842b40441db5332a5290f941021636b1182761Sol Boucher throw new RuntimeException("Unimplemented CameraProxy message=" + msg.what); 447a0842b40441db5332a5290f941021636b1182761Sol Boucher } 448a0842b40441db5332a5290f941021636b1182761Sol Boucher } 449a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (final Exception ex) { 450a0842b40441db5332a5290f941021636b1182761Sol Boucher if (msg.what != CameraActions.RELEASE && mCamera != null) { 451a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // TODO: Handle this better 452a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera.close(); 453a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera = null; 454a0842b40441db5332a5290f941021636b1182761Sol Boucher } else if (mCamera == null) { 455a0842b40441db5332a5290f941021636b1182761Sol Boucher if (msg.what == CameraActions.OPEN_CAMERA) { 456a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mOpenCallback != null) { 457a0842b40441db5332a5290f941021636b1182761Sol Boucher mOpenCallback.onDeviceOpenFailure(mCameraIndex, 458a0842b40441db5332a5290f941021636b1182761Sol Boucher generateHistoryString(mCameraIndex)); 459a0842b40441db5332a5290f941021636b1182761Sol Boucher } 460a0842b40441db5332a5290f941021636b1182761Sol Boucher } else { 461a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.w(TAG, "Cannot handle message " + msg.what + ", mCamera is null"); 462a0842b40441db5332a5290f941021636b1182761Sol Boucher } 463a0842b40441db5332a5290f941021636b1182761Sol Boucher return; 464a0842b40441db5332a5290f941021636b1182761Sol Boucher } 465a0842b40441db5332a5290f941021636b1182761Sol Boucher 466a0842b40441db5332a5290f941021636b1182761Sol Boucher if (ex instanceof RuntimeException) { 467a0842b40441db5332a5290f941021636b1182761Sol Boucher post(new Runnable() { 468a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 469a0842b40441db5332a5290f941021636b1182761Sol Boucher public void run() { 470a0842b40441db5332a5290f941021636b1182761Sol Boucher sCameraExceptionCallback.onCameraException((RuntimeException) ex); 471a0842b40441db5332a5290f941021636b1182761Sol Boucher }}); 472a0842b40441db5332a5290f941021636b1182761Sol Boucher } 473a0842b40441db5332a5290f941021636b1182761Sol Boucher } 474a0842b40441db5332a5290f941021636b1182761Sol Boucher } 475a0842b40441db5332a5290f941021636b1182761Sol Boucher 476a0842b40441db5332a5290f941021636b1182761Sol Boucher public CameraSettings buildSettings(AndroidCamera2Capabilities caps) { 477a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher return new AndroidCamera2Settings(caps, mPersistentRequestBuilder, mPreviewSize, 478a0842b40441db5332a5290f941021636b1182761Sol Boucher mPhotoSize); 479a0842b40441db5332a5290f941021636b1182761Sol Boucher } 480a0842b40441db5332a5290f941021636b1182761Sol Boucher 481a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** 482a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Simply propagates settings from provided {@link CameraSettings} 483a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * object to our {@link CaptureRequest.Builder} for use in captures. 484a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * <p>Most conversions to match the API 2 formats are performed by 485a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * {@link AndroidCamera2Capabilities.IntegralStringifier}; otherwise 486a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * any final adjustments are done here before updating the builder.</p> 487a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * 488a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * @param settings The new/updated settings 489a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher */ 490a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Finish implementation to add support for all settings 491a0842b40441db5332a5290f941021636b1182761Sol Boucher private void applyToRequest(CameraSettings settings) { 492a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: If invoked when in PREVIEW_READY state, a new preview size will not take effect 493a0842b40441db5332a5290f941021636b1182761Sol Boucher AndroidCamera2Capabilities.IntegralStringifier intifier = 494a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraProxy.getSpecializedCapabilities().getIntegralStringifier(); 495a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewSize = settings.getCurrentPreviewSize(); 496a0842b40441db5332a5290f941021636b1182761Sol Boucher mPhotoSize = settings.getCurrentPhotoSize(); 497a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, 498a0842b40441db5332a5290f941021636b1182761Sol Boucher intifier.intify(settings.getCurrentFocusMode())); 499a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 500a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, 501a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher legacyAreasToMeteringRectangles(settings.getFocusAreas())); 502a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, 503a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher legacyAreasToMeteringRectangles(settings.getMeteringAreas())); 504a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 505a0842b40441db5332a5290f941021636b1182761Sol Boucher if (settings.getCurrentFlashMode() != CameraCapabilities.FlashMode.NO_FLASH) { 506a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder.set(CaptureRequest.FLASH_MODE, 507a0842b40441db5332a5290f941021636b1182761Sol Boucher intifier.intify(settings.getCurrentFlashMode())); 508a0842b40441db5332a5290f941021636b1182761Sol Boucher } 509a0842b40441db5332a5290f941021636b1182761Sol Boucher if (settings.getCurrentSceneMode() != CameraCapabilities.SceneMode.NO_SCENE_MODE) { 510a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder.set(CaptureRequest.CONTROL_SCENE_MODE, 511a0842b40441db5332a5290f941021636b1182761Sol Boucher intifier.intify(settings.getCurrentSceneMode())); 512a0842b40441db5332a5290f941021636b1182761Sol Boucher } 513a0842b40441db5332a5290f941021636b1182761Sol Boucher 514a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mCameraState.getState() >= AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) { 515a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // If we're already previewing, reflect most settings immediately 516a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher try { 517a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession.setRepeatingRequest(mPersistentRequestBuilder.build(), 518a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /*listener*/mCameraFocusStateListener, /*handler*/this); 519a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } catch (CameraAccessException ex) { 520a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.e(TAG, "Failed to apply updated request settings", ex); 521a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 522a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } else if (mCameraState.getState() < AndroidCamera2StateHolder.CAMERA_PREVIEW_READY) { 523a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // If we're already ready to preview, this doesn't regress our state 524a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraState.setState(AndroidCamera2StateHolder.CAMERA_CONFIGURED); 525a0842b40441db5332a5290f941021636b1182761Sol Boucher } 526a0842b40441db5332a5290f941021636b1182761Sol Boucher } 527a0842b40441db5332a5290f941021636b1182761Sol Boucher 528a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private MeteringRectangle[] legacyAreasToMeteringRectangles( 529a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher List<android.hardware.Camera.Area> reference) { 530a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher MeteringRectangle[] transformed = null; 531a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (reference.size() > 0) { 532a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 533a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher transformed = new MeteringRectangle[reference.size()]; 534a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher for (int index = 0; index < reference.size(); ++index) { 535a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher android.hardware.Camera.Area source = reference.get(index); 536a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Rect rectangle = source.rect; 537a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 538a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Old API coordinates were [-1000,1000]; new ones are [0,ACTIVE_ARRAY_SIZE). 539a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher double oldLeft = (rectangle.left + 1000) / 2000.0; 540a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher double oldTop = (rectangle.top + 1000) / 2000.0; 541a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher double oldRight = (rectangle.right + 1000) / 2000.0; 542a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher double oldBottom = (rectangle.bottom + 1000) / 2000.0; 543a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher int left = toIntConstrained( 544a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mActiveArray.width() * oldLeft + mActiveArray.left, 545a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 0, mActiveArray.width() - 1); 546a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher int top = toIntConstrained( 547a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mActiveArray.height() * oldTop + mActiveArray.top, 548a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 0, mActiveArray.height() - 1); 549a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher int right = toIntConstrained( 550a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mActiveArray.width() * oldRight + mActiveArray.left, 551a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 0, mActiveArray.width() - 1); 552a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher int bottom = toIntConstrained( 553a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mActiveArray.height() * oldBottom + mActiveArray.top, 554a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 0, mActiveArray.height() - 1); 555a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher transformed[index] = new MeteringRectangle(left, top, 556a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher right - left, bottom - top, source.weight); 557a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 558a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 559a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher return transformed; 560a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 561a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 562a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private int toIntConstrained(double original, int min, int max) { 563a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher original = Math.max(original, min); 564a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher original = Math.min(original, max); 565a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher return (int) original; 566a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 567a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 568a0842b40441db5332a5290f941021636b1182761Sol Boucher private void setPreviewTexture(SurfaceTexture surfaceTexture) { 569a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Must be called after providing a .*Settings populated with sizes 570a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: We don't technically offer a selection of sizes tailored to SurfaceTextures! 571a0842b40441db5332a5290f941021636b1182761Sol Boucher 572a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Handle this error condition with a callback or exception 573a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mCameraState.getState() < AndroidCamera2StateHolder.CAMERA_CONFIGURED) { 574a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.w(TAG, "Ignoring texture setting at inappropriate time"); 575a0842b40441db5332a5290f941021636b1182761Sol Boucher return; 576a0842b40441db5332a5290f941021636b1182761Sol Boucher } 577a0842b40441db5332a5290f941021636b1182761Sol Boucher 578a0842b40441db5332a5290f941021636b1182761Sol Boucher // Avoid initializing another capture session unless we absolutely have to 579a0842b40441db5332a5290f941021636b1182761Sol Boucher if (surfaceTexture == mPreviewTexture) { 580a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.i(TAG, "Optimizing out redundant preview texture setting"); 581a0842b40441db5332a5290f941021636b1182761Sol Boucher return; 582a0842b40441db5332a5290f941021636b1182761Sol Boucher } 583a0842b40441db5332a5290f941021636b1182761Sol Boucher 584a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mSession != null) { 585a0842b40441db5332a5290f941021636b1182761Sol Boucher closePreviewSession(); 586a0842b40441db5332a5290f941021636b1182761Sol Boucher } 587a0842b40441db5332a5290f941021636b1182761Sol Boucher 588a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewTexture = surfaceTexture; 589a0842b40441db5332a5290f941021636b1182761Sol Boucher surfaceTexture.setDefaultBufferSize(mPreviewSize.width(), mPreviewSize.height()); 590a0842b40441db5332a5290f941021636b1182761Sol Boucher 591a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mPreviewSurface != null) { 592a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder.removeTarget(mPreviewSurface); 593a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewSurface.release(); 594a0842b40441db5332a5290f941021636b1182761Sol Boucher } 595a0842b40441db5332a5290f941021636b1182761Sol Boucher mPreviewSurface = new Surface(surfaceTexture); 596a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder.addTarget(mPreviewSurface); 597a0842b40441db5332a5290f941021636b1182761Sol Boucher 598a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 599a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera.createCaptureSession(Arrays.asList(mPreviewSurface), 600a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraPreviewStateListener, this); 601a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (CameraAccessException ex) { 602a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "Failed to create camera capture session", ex); 603a0842b40441db5332a5290f941021636b1182761Sol Boucher } 604a0842b40441db5332a5290f941021636b1182761Sol Boucher } 605a0842b40441db5332a5290f941021636b1182761Sol Boucher 606a0842b40441db5332a5290f941021636b1182761Sol Boucher private void closePreviewSession() { 607a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 608a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession.abortCaptures(); 609a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession = null; 610a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (CameraAccessException ex) { 611a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "Failed to close existing camera capture session", ex); 612a0842b40441db5332a5290f941021636b1182761Sol Boucher } 613a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraState.setState(AndroidCamera2StateHolder.CAMERA_CONFIGURED); 614a0842b40441db5332a5290f941021636b1182761Sol Boucher } 615a0842b40441db5332a5290f941021636b1182761Sol Boucher 616a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // This listener monitors our connection to and disconnection from camera devices. 617a0842b40441db5332a5290f941021636b1182761Sol Boucher private CameraDevice.StateListener mCameraDeviceStateListener = 618a0842b40441db5332a5290f941021636b1182761Sol Boucher new CameraDevice.StateListener() { 619a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 620a0842b40441db5332a5290f941021636b1182761Sol Boucher public void onOpened(CameraDevice camera) { 621a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera = camera; 622a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mOpenCallback != null) { 623a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 624a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraCharacteristics props = 625a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraManager.getCameraCharacteristics(mCameraId); 626a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraProxy = new AndroidCamera2ProxyImpl(mCameraIndex, mCamera, 627a0842b40441db5332a5290f941021636b1182761Sol Boucher getCameraDeviceInfo().getCharacteristics(mCameraIndex), props); 628a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPersistentRequestBuilder = 629a0842b40441db5332a5290f941021636b1182761Sol Boucher camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 630a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mActiveArray = 631a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher props.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); 632a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraState.setState(AndroidCamera2StateHolder.CAMERA_UNCONFIGURED); 633a0842b40441db5332a5290f941021636b1182761Sol Boucher mOpenCallback.onCameraOpened(mCameraProxy); 634a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (CameraAccessException ex) { 635a0842b40441db5332a5290f941021636b1182761Sol Boucher mOpenCallback.onDeviceOpenFailure(mCameraIndex, 636a0842b40441db5332a5290f941021636b1182761Sol Boucher generateHistoryString(mCameraIndex)); 637a0842b40441db5332a5290f941021636b1182761Sol Boucher } 638a0842b40441db5332a5290f941021636b1182761Sol Boucher } 639a0842b40441db5332a5290f941021636b1182761Sol Boucher } 640a0842b40441db5332a5290f941021636b1182761Sol Boucher 641a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 642a0842b40441db5332a5290f941021636b1182761Sol Boucher public void onDisconnected(CameraDevice camera) { 643a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.w(TAG, "Camera device '" + mCameraIndex + "' was disconnected"); 644a0842b40441db5332a5290f941021636b1182761Sol Boucher } 645a0842b40441db5332a5290f941021636b1182761Sol Boucher 646a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 647a0842b40441db5332a5290f941021636b1182761Sol Boucher public void onError(CameraDevice camera, int error) { 648a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "Camera device '" + mCameraIndex + "' encountered error code '" + 649a0842b40441db5332a5290f941021636b1182761Sol Boucher error + '\''); 650a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mOpenCallback != null) { 651a0842b40441db5332a5290f941021636b1182761Sol Boucher mOpenCallback.onDeviceOpenFailure(mCameraIndex, 652a0842b40441db5332a5290f941021636b1182761Sol Boucher generateHistoryString(mCameraIndex)); 653a0842b40441db5332a5290f941021636b1182761Sol Boucher } 654a0842b40441db5332a5290f941021636b1182761Sol Boucher }}; 655a0842b40441db5332a5290f941021636b1182761Sol Boucher 656a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // This listener monitors our camera session (i.e. our transition into and out of preview). 657a0842b40441db5332a5290f941021636b1182761Sol Boucher private CameraCaptureSession.StateListener mCameraPreviewStateListener = 658a0842b40441db5332a5290f941021636b1182761Sol Boucher new CameraCaptureSession.StateListener() { 659a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 660a0842b40441db5332a5290f941021636b1182761Sol Boucher public void onConfigured(CameraCaptureSession session) { 661a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSession = session; 662a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY); 663a0842b40441db5332a5290f941021636b1182761Sol Boucher } 664a0842b40441db5332a5290f941021636b1182761Sol Boucher 665a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 666a0842b40441db5332a5290f941021636b1182761Sol Boucher public void onConfigureFailed(CameraCaptureSession session) { 667a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Invoke a callback 668a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "Failed to configure the camera for capture"); 669a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 670a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 671a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 672a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onActive(CameraCaptureSession session) { 673a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mOneshotPreviewingCallback != null) { 674a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // The session is up and processing preview requests. Inform the caller. 675a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mOneshotPreviewingCallback.onPreviewStarted(); 676a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mOneshotPreviewingCallback = null; 677a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 678a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}; 679a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 680a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // This listener monitors requested captures and notifies any relevant callbacks. 681a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private CameraCaptureSession.CaptureListener mCameraFocusStateListener = 682a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher new CameraCaptureSession.CaptureListener() { 683a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private int mLastAfState = -1; 684a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 685a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 686a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, 687a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher TotalCaptureResult result) { 688a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Integer afStateMaybe = result.get(CaptureResult.CONTROL_AF_STATE); 689a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (afStateMaybe != null) { 690a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher int afState = afStateMaybe; 691a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher boolean afStateChanged = false; 692a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (afState != mLastAfState) { 693a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mLastAfState = afState; 694a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher afStateChanged = true; 695a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 696a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 697a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher switch (afState) { 698a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN: 699a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED: 700a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: { 701a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (afStateChanged && mPassiveAfCallback != null) { 702a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // A CameraAFMoveCallback is attached. If we just started to scan, 703a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // the motor is moving; otherwise, it has settled. 704a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mPassiveAfCallback.onAutoFocusMoving( 705a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN, 706a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraProxy); 707a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 708a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher break; 709a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 710a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 711a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED: 712a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: { 713a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (mOneshotAfCallback != null) { 714a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // A call to autoFocus() was just made to request a focus lock. 715a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Notify the caller that the lens is now indefinitely fixed, and 716a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // report whether the image we're now stuck with is in focus. 717a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mOneshotAfCallback.onAutoFocus( 718a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED, 719a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraProxy); 720a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mOneshotAfCallback = null; 721a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 722a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher break; 723a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 724a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 725a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 726a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 727a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 728a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 729a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, 730a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CaptureFailure failure) { 731a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.e(TAG, "Capture attempt failed with reason " + failure.getReason()); 732a0842b40441db5332a5290f941021636b1182761Sol Boucher }}; 733a0842b40441db5332a5290f941021636b1182761Sol Boucher } 734a0842b40441db5332a5290f941021636b1182761Sol Boucher 735a0842b40441db5332a5290f941021636b1182761Sol Boucher private class AndroidCamera2ProxyImpl extends CameraAgent.CameraProxy { 736a0842b40441db5332a5290f941021636b1182761Sol Boucher private final int mCameraIndex; 737a0842b40441db5332a5290f941021636b1182761Sol Boucher private final CameraDevice mCamera; 738a0842b40441db5332a5290f941021636b1182761Sol Boucher private final CameraDeviceInfo.Characteristics mCharacteristics; 739a0842b40441db5332a5290f941021636b1182761Sol Boucher private final AndroidCamera2Capabilities mCapabilities; 740a0842b40441db5332a5290f941021636b1182761Sol Boucher 741a0842b40441db5332a5290f941021636b1182761Sol Boucher public AndroidCamera2ProxyImpl(int cameraIndex, CameraDevice camera, 742a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraDeviceInfo.Characteristics characteristics, 743a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraCharacteristics properties) { 744a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraIndex = cameraIndex; 745a0842b40441db5332a5290f941021636b1182761Sol Boucher mCamera = camera; 746a0842b40441db5332a5290f941021636b1182761Sol Boucher mCharacteristics = characteristics; 747a0842b40441db5332a5290f941021636b1182761Sol Boucher mCapabilities = new AndroidCamera2Capabilities(properties); 748a0842b40441db5332a5290f941021636b1182761Sol Boucher } 749a0842b40441db5332a5290f941021636b1182761Sol Boucher 750a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 751a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 752a0842b40441db5332a5290f941021636b1182761Sol Boucher public android.hardware.Camera getCamera() { return null; } 753a0842b40441db5332a5290f941021636b1182761Sol Boucher 754a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 755a0842b40441db5332a5290f941021636b1182761Sol Boucher public int getCameraId() { 756a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraIndex; 757a0842b40441db5332a5290f941021636b1182761Sol Boucher } 758a0842b40441db5332a5290f941021636b1182761Sol Boucher 759a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 760a0842b40441db5332a5290f941021636b1182761Sol Boucher public CameraDeviceInfo.Characteristics getCharacteristics() { 761a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCharacteristics; 762a0842b40441db5332a5290f941021636b1182761Sol Boucher } 763a0842b40441db5332a5290f941021636b1182761Sol Boucher 764a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 765a0842b40441db5332a5290f941021636b1182761Sol Boucher public CameraCapabilities getCapabilities() { 766a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCapabilities; 767a0842b40441db5332a5290f941021636b1182761Sol Boucher } 768a0842b40441db5332a5290f941021636b1182761Sol Boucher 769a0842b40441db5332a5290f941021636b1182761Sol Boucher private AndroidCamera2Capabilities getSpecializedCapabilities() { 770a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCapabilities; 771a0842b40441db5332a5290f941021636b1182761Sol Boucher } 772a0842b40441db5332a5290f941021636b1182761Sol Boucher 773a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 774a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 775a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setPreviewDataCallback(Handler handler, CameraPreviewDataCallback cb) {} 776a0842b40441db5332a5290f941021636b1182761Sol Boucher 777a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 778a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 779a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setOneShotPreviewCallback(Handler handler, CameraPreviewDataCallback cb) {} 780a0842b40441db5332a5290f941021636b1182761Sol Boucher 781a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 782a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 783a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setPreviewDataCallbackWithBuffer(Handler handler, CameraPreviewDataCallback cb) 784a0842b40441db5332a5290f941021636b1182761Sol Boucher {} 785a0842b40441db5332a5290f941021636b1182761Sol Boucher 786a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 787a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void autoFocus(final Handler handler, final CameraAFCallback cb) { 788a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mDispatchThread.runJob(new Runnable() { 789a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 790a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void run() { 791a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CameraAFCallback cbForward = null; 792a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (cb != null) { 793a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher cbForward = new CameraAFCallback() { 794a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 795a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onAutoFocus(final boolean focused, 796a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher final CameraProxy camera) { 797a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher handler.post(new Runnable() { 798a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 799a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void run() { 800a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher cb.onAutoFocus(focused, camera); 801a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}); 802a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}; 803a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 804a0842b40441db5332a5290f941021636b1182761Sol Boucher 805a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraState.waitForStates(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE | 806a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED); 807a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraHandler.obtainMessage(CameraActions.AUTO_FOCUS, cbForward) 808a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher .sendToTarget(); 809a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}); 810a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 811a0842b40441db5332a5290f941021636b1182761Sol Boucher 812a0842b40441db5332a5290f941021636b1182761Sol Boucher @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 813a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 814a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void setAutoFocusMoveCallback(final Handler handler, final CameraAFMoveCallback cb) { 815a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mDispatchThread.runJob(new Runnable() { 816a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 817a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void run() { 818a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher CameraAFMoveCallback cbForward = null; 819a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (cb != null) { 820a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher cbForward = new CameraAFMoveCallback() { 821a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 822a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void onAutoFocusMoving(final boolean moving, 823a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher final CameraProxy camera) { 824a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher handler.post(new Runnable() { 825a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 826a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void run() { 827a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher cb.onAutoFocusMoving(moving, camera); 828a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}); 829a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}; 830a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 831a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 832a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mCameraHandler.obtainMessage(CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK, 833a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher cbForward).sendToTarget(); 834a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher }}); 835a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 836a0842b40441db5332a5290f941021636b1182761Sol Boucher 837a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 838a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 839a0842b40441db5332a5290f941021636b1182761Sol Boucher public void takePicture(Handler handler, 840a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraShutterCallback shutter, 841a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraPictureCallback raw, 842a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraPictureCallback postview, 843a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraPictureCallback jpeg) {} 844a0842b40441db5332a5290f941021636b1182761Sol Boucher 845a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Remove this method override once we handle the message 846a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 847a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setDisplayOrientation(int degrees) {} 848a0842b40441db5332a5290f941021636b1182761Sol Boucher 849a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 850a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 851a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setZoomChangeListener(android.hardware.Camera.OnZoomChangeListener listener) {} 852a0842b40441db5332a5290f941021636b1182761Sol Boucher 853a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 854a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 855a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setFaceDetectionCallback(Handler handler, CameraFaceDetectionCallback callback) 856a0842b40441db5332a5290f941021636b1182761Sol Boucher {} 857a0842b40441db5332a5290f941021636b1182761Sol Boucher 858a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Remove this method override once we handle this message 859a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 860a0842b40441db5332a5290f941021636b1182761Sol Boucher public void startFaceDetection() {} 861a0842b40441db5332a5290f941021636b1182761Sol Boucher 862a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // TODO: Remove this method override once we handle this message 863a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @Override 864a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public void stopFaceDetection() {} 865a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 866a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 867a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 868a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setErrorCallback(Handler handler, CameraErrorCallback cb) {} 869a0842b40441db5332a5290f941021636b1182761Sol Boucher 870a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 871a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 872a0842b40441db5332a5290f941021636b1182761Sol Boucher public void setParameters(android.hardware.Camera.Parameters params) {} 873a0842b40441db5332a5290f941021636b1182761Sol Boucher 874a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 875a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 876a0842b40441db5332a5290f941021636b1182761Sol Boucher public android.hardware.Camera.Parameters getParameters() { return null; } 877a0842b40441db5332a5290f941021636b1182761Sol Boucher 878a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 879a0842b40441db5332a5290f941021636b1182761Sol Boucher public CameraSettings getSettings() { 880a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraHandler.buildSettings(mCapabilities); 881a0842b40441db5332a5290f941021636b1182761Sol Boucher } 882a0842b40441db5332a5290f941021636b1182761Sol Boucher 883a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 884a0842b40441db5332a5290f941021636b1182761Sol Boucher public boolean applySettings(CameraSettings settings) { 885a0842b40441db5332a5290f941021636b1182761Sol Boucher return applySettingsHelper(settings, AndroidCamera2StateHolder.CAMERA_UNCONFIGURED | 886a0842b40441db5332a5290f941021636b1182761Sol Boucher AndroidCamera2StateHolder.CAMERA_CONFIGURED | 887a0842b40441db5332a5290f941021636b1182761Sol Boucher AndroidCamera2StateHolder.CAMERA_PREVIEW_READY); 888a0842b40441db5332a5290f941021636b1182761Sol Boucher } 889a0842b40441db5332a5290f941021636b1182761Sol Boucher 890a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: Implement 891a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 892a0842b40441db5332a5290f941021636b1182761Sol Boucher public String dumpDeviceSettings() { return null; } 893a0842b40441db5332a5290f941021636b1182761Sol Boucher 894a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 895a0842b40441db5332a5290f941021636b1182761Sol Boucher public Handler getCameraHandler() { 896a0842b40441db5332a5290f941021636b1182761Sol Boucher return AndroidCamera2AgentImpl.this.getCameraHandler(); 897a0842b40441db5332a5290f941021636b1182761Sol Boucher } 898a0842b40441db5332a5290f941021636b1182761Sol Boucher 899a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 900a0842b40441db5332a5290f941021636b1182761Sol Boucher public DispatchThread getDispatchThread() { 901a0842b40441db5332a5290f941021636b1182761Sol Boucher return AndroidCamera2AgentImpl.this.getDispatchThread(); 902a0842b40441db5332a5290f941021636b1182761Sol Boucher } 903a0842b40441db5332a5290f941021636b1182761Sol Boucher 904a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 905a0842b40441db5332a5290f941021636b1182761Sol Boucher public CameraStateHolder getCameraState() { 906a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraState; 907a0842b40441db5332a5290f941021636b1182761Sol Boucher } 908a0842b40441db5332a5290f941021636b1182761Sol Boucher } 909a0842b40441db5332a5290f941021636b1182761Sol Boucher 910a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** A linear state machine: each state entails all the states below it. */ 911a0842b40441db5332a5290f941021636b1182761Sol Boucher private static class AndroidCamera2StateHolder extends CameraStateHolder { 912a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Usage flow: openCamera() -> applySettings() -> setPreviewTexture() -> startPreview() -> 913a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // autoFocus() -> takePicture() 914a0842b40441db5332a5290f941021636b1182761Sol Boucher /* Camera states */ 915a0842b40441db5332a5290f941021636b1182761Sol Boucher /** No camera device is opened. */ 916a0842b40441db5332a5290f941021636b1182761Sol Boucher public static final int CAMERA_UNOPENED = 1; 917a0842b40441db5332a5290f941021636b1182761Sol Boucher /** A camera is opened, but no settings have been provided. */ 918a0842b40441db5332a5290f941021636b1182761Sol Boucher public static final int CAMERA_UNCONFIGURED = 2; 919a0842b40441db5332a5290f941021636b1182761Sol Boucher /** The open camera has been configured by providing it with settings. */ 920a0842b40441db5332a5290f941021636b1182761Sol Boucher public static final int CAMERA_CONFIGURED = 3; 921a0842b40441db5332a5290f941021636b1182761Sol Boucher /** A capture session is ready to stream a preview, but still has no repeating request. */ 922a0842b40441db5332a5290f941021636b1182761Sol Boucher public static final int CAMERA_PREVIEW_READY = 4; 923a0842b40441db5332a5290f941021636b1182761Sol Boucher /** A preview is currently being streamed. */ 924a0842b40441db5332a5290f941021636b1182761Sol Boucher public static final int CAMERA_PREVIEW_ACTIVE = 5; 925a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** The lens is locked on a particular region. */ 926a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public static final int CAMERA_FOCUS_LOCKED = 6; 927a0842b40441db5332a5290f941021636b1182761Sol Boucher 928a0842b40441db5332a5290f941021636b1182761Sol Boucher public AndroidCamera2StateHolder() { 929a0842b40441db5332a5290f941021636b1182761Sol Boucher this(CAMERA_UNOPENED); 930a0842b40441db5332a5290f941021636b1182761Sol Boucher } 931a0842b40441db5332a5290f941021636b1182761Sol Boucher 932a0842b40441db5332a5290f941021636b1182761Sol Boucher public AndroidCamera2StateHolder(int state) { 9337e0d39bf7b6e0f0df606e3f6c15f673f70fed3f7Sol Boucher super(state); 934a0842b40441db5332a5290f941021636b1182761Sol Boucher } 935a0842b40441db5332a5290f941021636b1182761Sol Boucher } 936a0842b40441db5332a5290f941021636b1182761Sol Boucher 937a0842b40441db5332a5290f941021636b1182761Sol Boucher private static class AndroidCamera2DeviceInfo implements CameraDeviceInfo { 938a0842b40441db5332a5290f941021636b1182761Sol Boucher private final CameraManager mCameraManager; 939a0842b40441db5332a5290f941021636b1182761Sol Boucher private final String[] mCameraIds; 940a0842b40441db5332a5290f941021636b1182761Sol Boucher private final int mNumberOfCameras; 941a0842b40441db5332a5290f941021636b1182761Sol Boucher private final int mFirstBackCameraId; 942a0842b40441db5332a5290f941021636b1182761Sol Boucher private final int mFirstFrontCameraId; 943a0842b40441db5332a5290f941021636b1182761Sol Boucher 944a0842b40441db5332a5290f941021636b1182761Sol Boucher public AndroidCamera2DeviceInfo(CameraManager cameraManager, 945a0842b40441db5332a5290f941021636b1182761Sol Boucher String[] cameraIds, int numberOfCameras) { 946a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraManager = cameraManager; 947a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraIds = cameraIds; 948a0842b40441db5332a5290f941021636b1182761Sol Boucher mNumberOfCameras = numberOfCameras; 949a0842b40441db5332a5290f941021636b1182761Sol Boucher 950a0842b40441db5332a5290f941021636b1182761Sol Boucher int firstBackId = NO_DEVICE; 951a0842b40441db5332a5290f941021636b1182761Sol Boucher int firstFrontId = NO_DEVICE; 952a0842b40441db5332a5290f941021636b1182761Sol Boucher for (int id = 0; id < cameraIds.length; ++id) { 953a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 954a0842b40441db5332a5290f941021636b1182761Sol Boucher int lensDirection = cameraManager.getCameraCharacteristics(cameraIds[id]) 955a0842b40441db5332a5290f941021636b1182761Sol Boucher .get(CameraCharacteristics.LENS_FACING); 956a0842b40441db5332a5290f941021636b1182761Sol Boucher if (firstBackId == NO_DEVICE && 957a0842b40441db5332a5290f941021636b1182761Sol Boucher lensDirection == CameraCharacteristics.LENS_FACING_BACK) { 958a0842b40441db5332a5290f941021636b1182761Sol Boucher firstBackId = id; 959a0842b40441db5332a5290f941021636b1182761Sol Boucher } 960a0842b40441db5332a5290f941021636b1182761Sol Boucher if (firstFrontId == NO_DEVICE && 961a0842b40441db5332a5290f941021636b1182761Sol Boucher lensDirection == CameraCharacteristics.LENS_FACING_FRONT) { 962a0842b40441db5332a5290f941021636b1182761Sol Boucher firstFrontId = id; 963a0842b40441db5332a5290f941021636b1182761Sol Boucher } 964a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (CameraAccessException ex) { 965a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.w(TAG, "Couldn't get characteristics of camera '" + id + "'", ex); 966a0842b40441db5332a5290f941021636b1182761Sol Boucher } 967a0842b40441db5332a5290f941021636b1182761Sol Boucher } 968a0842b40441db5332a5290f941021636b1182761Sol Boucher mFirstBackCameraId = firstBackId; 969a0842b40441db5332a5290f941021636b1182761Sol Boucher mFirstFrontCameraId = firstFrontId; 970a0842b40441db5332a5290f941021636b1182761Sol Boucher } 971a0842b40441db5332a5290f941021636b1182761Sol Boucher 972a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 973a0842b40441db5332a5290f941021636b1182761Sol Boucher public Characteristics getCharacteristics(int cameraId) { 974a0842b40441db5332a5290f941021636b1182761Sol Boucher String actualId = mCameraIds[cameraId]; 975a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 976a0842b40441db5332a5290f941021636b1182761Sol Boucher CameraCharacteristics info = mCameraManager.getCameraCharacteristics(actualId); 977a0842b40441db5332a5290f941021636b1182761Sol Boucher return new AndroidCharacteristics2(info); 978a0842b40441db5332a5290f941021636b1182761Sol Boucher } catch (CameraAccessException ex) { 979a0842b40441db5332a5290f941021636b1182761Sol Boucher return null; 980a0842b40441db5332a5290f941021636b1182761Sol Boucher } 981a0842b40441db5332a5290f941021636b1182761Sol Boucher } 982a0842b40441db5332a5290f941021636b1182761Sol Boucher 983a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 984a0842b40441db5332a5290f941021636b1182761Sol Boucher public int getNumberOfCameras() { 985a0842b40441db5332a5290f941021636b1182761Sol Boucher return mNumberOfCameras; 986a0842b40441db5332a5290f941021636b1182761Sol Boucher } 987a0842b40441db5332a5290f941021636b1182761Sol Boucher 988a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 989a0842b40441db5332a5290f941021636b1182761Sol Boucher public int getFirstBackCameraId() { 990a0842b40441db5332a5290f941021636b1182761Sol Boucher return mFirstBackCameraId; 991a0842b40441db5332a5290f941021636b1182761Sol Boucher } 992a0842b40441db5332a5290f941021636b1182761Sol Boucher 993a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 994a0842b40441db5332a5290f941021636b1182761Sol Boucher public int getFirstFrontCameraId() { 995a0842b40441db5332a5290f941021636b1182761Sol Boucher return mFirstFrontCameraId; 996a0842b40441db5332a5290f941021636b1182761Sol Boucher } 997a0842b40441db5332a5290f941021636b1182761Sol Boucher 998a0842b40441db5332a5290f941021636b1182761Sol Boucher private static class AndroidCharacteristics2 implements Characteristics { 999a0842b40441db5332a5290f941021636b1182761Sol Boucher private CameraCharacteristics mCameraInfo; 1000a0842b40441db5332a5290f941021636b1182761Sol Boucher 1001a0842b40441db5332a5290f941021636b1182761Sol Boucher AndroidCharacteristics2(CameraCharacteristics cameraInfo) { 1002a0842b40441db5332a5290f941021636b1182761Sol Boucher mCameraInfo = cameraInfo; 1003a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1004a0842b40441db5332a5290f941021636b1182761Sol Boucher 1005a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1006a0842b40441db5332a5290f941021636b1182761Sol Boucher public boolean isFacingBack() { 1007a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraInfo.get(CameraCharacteristics.LENS_FACING) 1008a0842b40441db5332a5290f941021636b1182761Sol Boucher .equals(CameraCharacteristics.LENS_FACING_BACK); 1009a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1010a0842b40441db5332a5290f941021636b1182761Sol Boucher 1011a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1012a0842b40441db5332a5290f941021636b1182761Sol Boucher public boolean isFacingFront() { 1013a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraInfo.get(CameraCharacteristics.LENS_FACING) 1014a0842b40441db5332a5290f941021636b1182761Sol Boucher .equals(CameraCharacteristics.LENS_FACING_FRONT); 1015a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1016a0842b40441db5332a5290f941021636b1182761Sol Boucher 1017a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1018a0842b40441db5332a5290f941021636b1182761Sol Boucher public int getSensorOrientation() { 1019a0842b40441db5332a5290f941021636b1182761Sol Boucher return mCameraInfo.get(CameraCharacteristics.SENSOR_ORIENTATION); 1020a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1021a0842b40441db5332a5290f941021636b1182761Sol Boucher 1022a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1023a0842b40441db5332a5290f941021636b1182761Sol Boucher public boolean canDisableShutterSound() { 1024a0842b40441db5332a5290f941021636b1182761Sol Boucher // The new API doesn't support this operation, so don't encourage people to try it. 1025a0842b40441db5332a5290f941021636b1182761Sol Boucher // TODO: What kind of assumptions have callers made about this result's meaning? 1026a0842b40441db5332a5290f941021636b1182761Sol Boucher return false; 1027a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1028a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1029a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1030a0842b40441db5332a5290f941021636b1182761Sol Boucher 1031a0842b40441db5332a5290f941021636b1182761Sol Boucher private static final CameraExceptionCallback sCameraExceptionCallback = 1032a0842b40441db5332a5290f941021636b1182761Sol Boucher new CameraExceptionCallback() { 1033a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 1034a0842b40441db5332a5290f941021636b1182761Sol Boucher public synchronized void onCameraException(RuntimeException e) { 1035a0842b40441db5332a5290f941021636b1182761Sol Boucher throw e; 1036a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1037a0842b40441db5332a5290f941021636b1182761Sol Boucher }; 1038a0842b40441db5332a5290f941021636b1182761Sol Boucher} 1039