LegacyCameraDevice.java revision 3e4fed203fe7c945c53c6d6bb9f160932a1d15b3
1feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/* 2feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Copyright (C) 2014 The Android Open Source Project 3feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 4feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 5feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * you may not use this file except in compliance with the License. 6feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * You may obtain a copy of the License at 7feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 8feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * http://www.apache.org/licenses/LICENSE-2.0 9feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 10feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Unless required by applicable law or agreed to in writing, software 11feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 12feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * See the License for the specific language governing permissions and 14feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * limitations under the License. 15feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 16feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 17feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpackage android.hardware.camera2.legacy; 18feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 19feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.graphics.ImageFormat; 20feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.Camera; 21feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.CaptureRequest; 22feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CaptureResultExtras; 23feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.ICameraDeviceCallbacks; 24feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.LongParcelable; 25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CameraMetadataNative; 26feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.CameraBinderDecorator; 27feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.CameraRuntimeException; 28feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.ConditionVariable; 29feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.Handler; 30feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.HandlerThread; 31feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.RemoteException; 32feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log; 33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.view.Surface; 34feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 35feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.ArrayList; 36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.List; 37feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.concurrent.atomic.AtomicInteger; 38feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 39feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/** 40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This class emulates the functionality of a Camera2 device using a the old Camera class. 41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 42feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 43feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * There are two main components that are used to implement this: 44feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A state machine containing valid Camera2 device states ({@link CameraDeviceState}). 45feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A message-queue based pipeline that manages an old Camera class, and executes capture and 46feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * configuration requests. 47feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 48feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class LegacyCameraDevice implements AutoCloseable { 50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public static final String DEBUG_PROP = "HAL1ShimLogging"; 51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final String TAG; 52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 533e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk private static final boolean DEBUG = false; 54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final int mCameraId; 55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final ICameraDeviceCallbacks mDeviceCallbacks; 56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final CameraDeviceState mDeviceState = new CameraDeviceState(); 57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final ConditionVariable mIdle = new ConditionVariable(/*open*/true); 59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 60d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final HandlerThread mResultThread = new HandlerThread("ResultThread"); 61d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final HandlerThread mCallbackHandlerThread = new HandlerThread("CallbackThread"); 62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final Handler mCallbackHandler; 63d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final Handler mResultHandler; 64feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private static final int ILLEGAL_VALUE = -1; 65feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) { 67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (holder == null) { 68feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, 69feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk ILLEGAL_VALUE, ILLEGAL_VALUE); 70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(), 72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber()); 73feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 74feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 76feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Listener for the camera device state machine. Calls the appropriate 77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link ICameraDeviceCallbacks} for each state transition. 78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 79feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final CameraDeviceState.CameraDeviceStateListener mStateListener = 80feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk new CameraDeviceState.CameraDeviceStateListener() { 81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 82feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onError(final int errorCode, RequestHolder holder) { 83feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.open(); 84feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 85d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 86d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 87d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 883e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 893e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onError callback."); 903e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 91d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 92d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onCameraError(errorCode, extras); 93d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 94d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 95d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 96d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 97d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 98d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 99feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 100feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 101feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 102feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onConfiguring() { 103feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // Do nothing 1043e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1053e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onConfiguring callback."); 1063e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 107feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 108feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 109feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 110feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onIdle() { 111feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.open(); 112feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 113d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 114d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 115d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1163e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1173e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onIdle callback."); 1183e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 119d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 120d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onCameraIdle(); 121d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 122d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 123d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraIdle callback: ", e); 124d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 125d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 126d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 127feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 128feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 129feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 130feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onCaptureStarted(RequestHolder holder) { 131feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 132feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 133d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk final long timestamp = System.nanoTime(); 134d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 135d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 136d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1373e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1383e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onCaptureStarted callback."); 1393e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 140d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 141d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk // TODO: Don't fake timestamp 142d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onCaptureStarted(extras, timestamp); 143d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 144d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 145d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 146d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 147d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 148d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 149feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 150feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 151feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 152d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void onCaptureResult(final CameraMetadataNative result, RequestHolder holder) { 153feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 154feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 155d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 156d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 157d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1583e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1593e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onCaptureResult callback."); 1603e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 161d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 162d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk // TODO: Don't fake metadata 163d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onResultReceived(result, extras); 164d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 165d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 166d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 167d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 168d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 169d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 170feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 171feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk }; 172feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 173feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final RequestThreadManager mRequestThreadManager; 174feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 175feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 176feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Check if a given surface uses {@link ImageFormat#YUV_420_888} format. 177feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 178feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param s the surface to check. 179feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return {@code true} if the surfaces uses {@link ImageFormat#YUV_420_888}. 180feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 181feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk static boolean needsConversion(Surface s) { 182feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return LegacyCameraDevice.nativeDetectSurfaceType(s) == ImageFormat.YUV_420_888; 183feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 184feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 185feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 186feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Create a new emulated camera device from a given Camera 1 API camera. 187feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 188feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 189feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * The {@link Camera} provided to this constructor must already have been successfully opened, 190feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * and ownership of the provided camera is passed to this object. No further calls to the 191feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * camera methods should be made following this constructor. 192feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 193feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 194feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param cameraId the id of the camera. 195feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param camera an open {@link Camera} device. 196feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param callbacks {@link ICameraDeviceCallbacks} callbacks to call for Camera2 API operations. 197feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 198feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public LegacyCameraDevice(int cameraId, Camera camera, ICameraDeviceCallbacks callbacks) { 199feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCameraId = cameraId; 200feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDeviceCallbacks = callbacks; 201feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk TAG = String.format("CameraDevice-%d-LE", mCameraId); 202feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 203d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.start(); 204d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler = new Handler(mResultThread.getLooper()); 205feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandlerThread.start(); 206feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandler = new Handler(mCallbackHandlerThread.getLooper()); 207feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDeviceState.setCameraDeviceCallbacks(mCallbackHandler, mStateListener); 208feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager = 209feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk new RequestThreadManager(cameraId, camera, mDeviceState); 210feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.start(); 211feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 212feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 213feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 214feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Configure the device with a set of output surfaces. 215feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 216feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param outputs a list of surfaces to set. 217feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return an error code for this binder operation, or {@link CameraBinderDecorator.NO_ERROR} 218feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * on success. 219feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 220feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public int configureOutputs(List<Surface> outputs) { 221feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int error = mDeviceState.setConfiguring(); 222feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (error == CameraBinderDecorator.NO_ERROR) { 223feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.configure(outputs); 224feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk error = mDeviceState.setIdle(); 225feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 226feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return error; 227feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 228feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 229feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 230feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit a burst of capture requests. 231feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 232feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestList a list of capture requests to execute. 233feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating {@code true} if this burst is repeating. 234feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param frameNumber an output argument that contains either the frame number of the last frame 235feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * that will be returned for this request, or the frame number of the last 236feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * frame that will be returned for the current repeating request if this 237feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * burst is set to be repeating. 238feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the request id. 239feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 240feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public int submitRequestList(List<CaptureRequest> requestList, boolean repeating, 241feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /*out*/LongParcelable frameNumber) { 242feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // TODO: validate request here 243feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.close(); 244feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return mRequestThreadManager.submitCaptureRequests(requestList, repeating, 245feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk frameNumber); 246feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 247feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 248feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 249feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit a single capture request. 250feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 251feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param request the capture request to execute. 252feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating {@code true} if this request is repeating. 253feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param frameNumber an output argument that contains either the frame number of the last frame 254feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * that will be returned for this request, or the frame number of the last 255feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * frame that will be returned for the current repeating request if this 256feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * request is set to be repeating. 257feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the request id. 258feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 259feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public int submitRequest(CaptureRequest request, boolean repeating, 260feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /*out*/LongParcelable frameNumber) { 261feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk ArrayList<CaptureRequest> requestList = new ArrayList<CaptureRequest>(); 262feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk requestList.add(request); 263feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return submitRequestList(requestList, repeating, frameNumber); 264feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 265feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 266feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 267feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Cancel the repeating request with the given request id. 268feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 269feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestId the request id of the request to cancel. 270feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the last frame number to be returned from the HAL for the given repeating request, or 271feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@code INVALID_FRAME} if none exists. 272feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 273feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public long cancelRequest(int requestId) { 274feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return mRequestThreadManager.cancelRepeating(requestId); 275feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 276feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 277feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 278feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Block until the {@link ICameraDeviceCallbacks#onCameraIdle()} callback is received. 279feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 280feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void waitUntilIdle() { 281feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.block(); 282feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 283feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 284feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 285feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void close() { 286feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.quit(); 287feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandlerThread.quitSafely(); 288d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.quitSafely(); 289d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 290d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 291d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mCallbackHandlerThread.join(); 292d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (InterruptedException e) { 293d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 294d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mCallbackHandlerThread.getName(), mCallbackHandlerThread.getId())); 295d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 296d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 297d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 298d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.join(); 299d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (InterruptedException e) { 300d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 301d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.getName(), mResultThread.getId())); 302d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 303d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 304feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // TODO: throw IllegalStateException in every method after close has been called 305feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 306feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 307feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 308feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk protected void finalize() throws Throwable { 309feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk try { 310feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk close(); 311feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } catch (CameraRuntimeException e) { 312feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage()); 313feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } finally { 314feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk super.finalize(); 315feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 316feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 317feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 318feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk protected static native int nativeDetectSurfaceType(Surface surface); 319feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 320feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk protected static native void nativeDetectSurfaceDimens(Surface surface, int[] dimens); 321feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 322feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk protected static native void nativeConfigureSurface(Surface surface, int width, int height, 323feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int pixelFormat); 324feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 325feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk protected static native void nativeProduceFrame(Surface surface, byte[] pixelBuffer, int width, 326feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int height, int pixelFormat); 327feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 328feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk protected static native void nativeSetSurfaceFormat(Surface surface, int pixelFormat); 329feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 330feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk protected static native void nativeSetSurfaceDimens(Surface surface, int width, int height); 331feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 332feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk} 333