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