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