LegacyCameraDevice.java revision 83159151f618c79040a2e800de8cc78f22bf760b
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; 2028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkimport android.graphics.SurfaceTexture; 21feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.Camera; 22df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkinimport android.hardware.camera2.CameraCharacteristics; 23feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.CaptureRequest; 24feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CaptureResultExtras; 25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.ICameraDeviceCallbacks; 26feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.LongParcelable; 27feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CameraMetadataNative; 28feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.CameraRuntimeException; 29feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.ConditionVariable; 30feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.Handler; 31feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.HandlerThread; 32feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.RemoteException; 33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log; 34a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.util.Size; 35feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.view.Surface; 36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 37feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.ArrayList; 383c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkimport java.util.Collection; 39feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.List; 4049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 41ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkimport static android.hardware.camera2.legacy.LegacyExceptionUtils.*; 4249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkinimport static android.hardware.camera2.utils.CameraBinderDecorator.*; 43a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport static com.android.internal.util.Preconditions.*; 44feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 45feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/** 46feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This class emulates the functionality of a Camera2 device using a the old Camera class. 47feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 48feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * There are two main components that are used to implement this: 50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A state machine containing valid Camera2 device states ({@link CameraDeviceState}). 51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A message-queue based pipeline that manages an old Camera class, and executes capture and 52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * configuration requests. 53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class LegacyCameraDevice implements AutoCloseable { 56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public static final String DEBUG_PROP = "HAL1ShimLogging"; 57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final String TAG; 58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 593e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk private static final boolean DEBUG = false; 60feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final int mCameraId; 61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final ICameraDeviceCallbacks mDeviceCallbacks; 62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final CameraDeviceState mDeviceState = new CameraDeviceState(); 6349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin private List<Surface> mConfiguredSurfaces; 64feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 65feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final ConditionVariable mIdle = new ConditionVariable(/*open*/true); 66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 67d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final HandlerThread mResultThread = new HandlerThread("ResultThread"); 68d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final HandlerThread mCallbackHandlerThread = new HandlerThread("CallbackThread"); 69feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final Handler mCallbackHandler; 70d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final Handler mResultHandler; 71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private static final int ILLEGAL_VALUE = -1; 72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 73feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) { 74feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (holder == null) { 75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, 7683159151f618c79040a2e800de8cc78f22bf760bZhijun He ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE); 77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(), 7983159151f618c79040a2e800de8cc78f22bf760bZhijun He /*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(), 8083159151f618c79040a2e800de8cc78f22bf760bZhijun He /*partialResultCount*/1); 81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 82feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 83feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 84feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Listener for the camera device state machine. Calls the appropriate 85feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link ICameraDeviceCallbacks} for each state transition. 86feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 87feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final CameraDeviceState.CameraDeviceStateListener mStateListener = 88feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk new CameraDeviceState.CameraDeviceStateListener() { 89feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 90feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onError(final int errorCode, RequestHolder holder) { 91feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.open(); 92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 93d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 94d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 95d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 963e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 973e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onError callback."); 983e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 99d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 100d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onCameraError(errorCode, extras); 101d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 102d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 103d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 104d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 105d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 106d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 107feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 108feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 109feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 110feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onConfiguring() { 111feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // Do nothing 1123e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1133e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onConfiguring callback."); 1143e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 115feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 116feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 117feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 118feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onIdle() { 119feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.open(); 120feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 121d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 122d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 123d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1243e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1253e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onIdle callback."); 1263e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 127d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 128d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onCameraIdle(); 129d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 130d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 131d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraIdle callback: ", e); 132d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 133d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 134d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 135feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 136feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 137feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 138feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onCaptureStarted(RequestHolder holder) { 139feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 140feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 141d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk final long timestamp = System.nanoTime(); 142d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 143d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 144d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1453e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1463e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onCaptureStarted callback."); 1473e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 148d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 149d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk // TODO: Don't fake timestamp 150d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onCaptureStarted(extras, timestamp); 151d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 152d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 153d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 154d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 155d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 156d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 157feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 158feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 159feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 160d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void onCaptureResult(final CameraMetadataNative result, RequestHolder holder) { 161feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 162feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 163d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 164d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 165d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1663e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1673e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onCaptureResult callback."); 1683e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 169d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 170d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk // TODO: Don't fake metadata 171d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onResultReceived(result, extras); 172d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 173d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 174d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 175d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 176d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 177d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 178feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 179feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk }; 180feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 181feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final RequestThreadManager mRequestThreadManager; 182feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 183feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 18491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * Check if a given surface uses {@link ImageFormat#YUV_420_888} or format that can be readily 18591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * converted to this; YV12 and NV21 are the two currently supported formats. 186feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 187feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param s the surface to check. 18891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * @return {@code true} if the surfaces uses {@link ImageFormat#YUV_420_888} or a compatible 18991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * format. 190feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 191ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static boolean needsConversion(Surface s) throws BufferQueueAbandonedException { 192ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int nativeType = detectSurfaceType(s); 19391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk return nativeType == ImageFormat.YUV_420_888 || nativeType == ImageFormat.YV12 || 19491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk nativeType == ImageFormat.NV21; 195feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 196feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 197feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 198feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Create a new emulated camera device from a given Camera 1 API camera. 199feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 200feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 201feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * The {@link Camera} provided to this constructor must already have been successfully opened, 202feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * and ownership of the provided camera is passed to this object. No further calls to the 203feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * camera methods should be made following this constructor. 204feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 205feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 206feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param cameraId the id of the camera. 207feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param camera an open {@link Camera} device. 208df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @param characteristics the static camera characteristics for this camera device 209feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param callbacks {@link ICameraDeviceCallbacks} callbacks to call for Camera2 API operations. 210feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 211df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin public LegacyCameraDevice(int cameraId, Camera camera, CameraCharacteristics characteristics, 212df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin ICameraDeviceCallbacks callbacks) { 213feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCameraId = cameraId; 214feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDeviceCallbacks = callbacks; 215feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk TAG = String.format("CameraDevice-%d-LE", mCameraId); 216feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 217d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.start(); 218d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler = new Handler(mResultThread.getLooper()); 219feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandlerThread.start(); 220feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandler = new Handler(mCallbackHandlerThread.getLooper()); 221feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDeviceState.setCameraDeviceCallbacks(mCallbackHandler, mStateListener); 222feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager = 223df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin new RequestThreadManager(cameraId, camera, characteristics, mDeviceState); 224feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.start(); 225feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 226feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 227feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 228feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Configure the device with a set of output surfaces. 229feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 23049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * <p>Using empty or {@code null} {@code outputs} is the same as unconfiguring.</p> 23149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * 23249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * <p>Every surface in {@code outputs} must be non-{@code null}.</p> 23349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * 234feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param outputs a list of surfaces to set. 23549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * @return an error code for this binder operation, or {@link NO_ERROR} 236feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * on success. 237feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 238feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public int configureOutputs(List<Surface> outputs) { 23949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (outputs != null) { 24049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (Surface output : outputs) { 24149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (output == null) { 24249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "configureOutputs - null outputs are not allowed"); 24349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 24449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 24549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 24649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 24749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 248feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int error = mDeviceState.setConfiguring(); 24949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (error == NO_ERROR) { 250feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.configure(outputs); 251feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk error = mDeviceState.setIdle(); 252feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 25349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 25449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin // TODO: May also want to check the surfaces more deeply (e.g. state, formats, sizes..) 25549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (error == NO_ERROR) { 25649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null; 25749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 25849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 259feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return error; 260feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 261feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 262feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 263feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit a burst of capture requests. 264feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 265feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestList a list of capture requests to execute. 266feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating {@code true} if this burst is repeating. 267feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param frameNumber an output argument that contains either the frame number of the last frame 268feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * that will be returned for this request, or the frame number of the last 269feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * frame that will be returned for the current repeating request if this 270feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * burst is set to be repeating. 271feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the request id. 272feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 273feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public int submitRequestList(List<CaptureRequest> requestList, boolean repeating, 274feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /*out*/LongParcelable frameNumber) { 27549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (requestList == null || requestList.isEmpty()) { 27649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - Empty/null requests are not allowed"); 27749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 27849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 27949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 2803c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk List<Long> surfaceIds = (mConfiguredSurfaces == null) ? new ArrayList<Long>() : 2813c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk getSurfaceIds(mConfiguredSurfaces); 2823c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 28349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin // Make sure that there all requests have at least 1 surface; all surfaces are non-null 28449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (CaptureRequest request : requestList) { 28549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (request.getTargets().isEmpty()) { 28649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - " 28749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin + "Each request must have at least one Surface target"); 28849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 28949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 29049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 29149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (Surface surface : request.getTargets()) { 29249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (surface == null) { 29349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - Null Surface targets are not allowed"); 29449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 29549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } else if (mConfiguredSurfaces == null) { 29649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - must configure " + 29749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin " device with valid surfaces before submitting requests"); 29849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return INVALID_OPERATION; 2993c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } else if (!containsSurfaceId(surface, surfaceIds)) { 30049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - cannot use a surface that wasn't configured"); 30149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 30249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 30349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 30449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 30549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 30649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin // TODO: further validation of request here 307feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.close(); 308feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return mRequestThreadManager.submitCaptureRequests(requestList, repeating, 309feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk frameNumber); 310feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 311feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 312feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 313feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit a single capture request. 314feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 315feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param request the capture request to execute. 316feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating {@code true} if this request is repeating. 317feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param frameNumber an output argument that contains either the frame number of the last frame 318feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * that will be returned for this request, or the frame number of the last 319feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * frame that will be returned for the current repeating request if this 320feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * request is set to be repeating. 321feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the request id. 322feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 323feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public int submitRequest(CaptureRequest request, boolean repeating, 324feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /*out*/LongParcelable frameNumber) { 325feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk ArrayList<CaptureRequest> requestList = new ArrayList<CaptureRequest>(); 326feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk requestList.add(request); 327feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return submitRequestList(requestList, repeating, frameNumber); 328feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 329feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 330feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 331feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Cancel the repeating request with the given request id. 332feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 333feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestId the request id of the request to cancel. 334feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the last frame number to be returned from the HAL for the given repeating request, or 335feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@code INVALID_FRAME} if none exists. 336feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 337feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public long cancelRequest(int requestId) { 338feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return mRequestThreadManager.cancelRepeating(requestId); 339feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 340feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 341feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 342feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Block until the {@link ICameraDeviceCallbacks#onCameraIdle()} callback is received. 343feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 344feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void waitUntilIdle() { 345feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.block(); 346feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 347feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 348feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 349feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void close() { 350feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.quit(); 351feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandlerThread.quitSafely(); 352d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.quitSafely(); 353d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 354d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 355d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mCallbackHandlerThread.join(); 356d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (InterruptedException e) { 357d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 358d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mCallbackHandlerThread.getName(), mCallbackHandlerThread.getId())); 359d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 360d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 361d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 362d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.join(); 363d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (InterruptedException e) { 364d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 365d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.getName(), mResultThread.getId())); 366d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 367d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 368feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // TODO: throw IllegalStateException in every method after close has been called 369feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 370feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 371feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 372feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk protected void finalize() throws Throwable { 373feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk try { 374feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk close(); 375feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } catch (CameraRuntimeException e) { 376feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage()); 377feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } finally { 378feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk super.finalize(); 379feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 380feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 381feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 382a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /** 383a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * Query the surface for its currently configured default buffer size. 384a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @param surface a non-{@code null} {@code Surface} 385a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @return the width and height of the surface 386a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * 387a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @throws NullPointerException if the {@code surface} was {@code null} 388a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @throws IllegalStateException if the {@code surface} was invalid 389a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin */ 390ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static Size getSurfaceSize(Surface surface) throws BufferQueueAbandonedException { 391a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin checkNotNull(surface); 392a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 393a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin int[] dimens = new int[2]; 394ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDimens(surface, /*out*/dimens)); 395a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 396a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin return new Size(dimens[0], dimens[1]); 397a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 398a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 399ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static int detectSurfaceType(Surface surface) throws BufferQueueAbandonedException { 400ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 401ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceType(surface)); 402ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 403ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 404ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void configureSurface(Surface surface, int width, int height, 405ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int pixelFormat) throws BufferQueueAbandonedException { 406ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 407ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 408ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 409ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 410ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeConfigureSurface(surface, width, height, 411ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk pixelFormat)); 412ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 413ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 414ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void produceFrame(Surface surface, byte[] pixelBuffer, int width, 415ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int height, int pixelFormat) 416ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 417ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 418ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(pixelBuffer); 419ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 420ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 421ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 422ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeProduceFrame(surface, pixelBuffer, width, height, 423ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk pixelFormat)); 424ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 425ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 426ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void setSurfaceFormat(Surface surface, int pixelFormat) 427ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 428ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 429ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 430ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceFormat(surface, pixelFormat)); 431ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 432ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 433ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void setSurfaceDimens(Surface surface, int width, int height) 434ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 435ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 436ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 437ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 438ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 439ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceDimens(surface, width, height)); 440ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 441ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 4423c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk static long getSurfaceId(Surface surface) { 4433c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk checkNotNull(surface); 4443c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return nativeGetSurfaceId(surface); 4453c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 4463c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 4473c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk static List<Long> getSurfaceIds(Collection<Surface> surfaces) { 4483c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk if (surfaces == null) { 4493c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk throw new NullPointerException("Null argument surfaces"); 4503c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 4513c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk List<Long> surfaceIds = new ArrayList<>(); 4523c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk for (Surface s : surfaces) { 4533c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk long id = getSurfaceId(s); 4543c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk if (id == 0) { 4553c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk throw new IllegalStateException( 4563c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk "Configured surface had null native GraphicBufferProducer pointer!"); 4573c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 4583c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk surfaceIds.add(id); 4593c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 4603c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return surfaceIds; 4613c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 4623c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 4633c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk static boolean containsSurfaceId(Surface s, List<Long> ids) { 4643c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk long id = getSurfaceId(s); 4653c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return ids.contains(id); 4663c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 4673c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 46828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk static void setSurfaceOrientation(Surface surface, int facing, int sensorOrientation) 46928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk throws BufferQueueAbandonedException { 47028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk checkNotNull(surface); 47128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceOrientation(surface, facing, 47228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk sensorOrientation)); 47328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk } 47428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 47528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk static Size getTextureSize(SurfaceTexture surfaceTexture) 47628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk throws BufferQueueAbandonedException { 47728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk checkNotNull(surfaceTexture); 47828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 47928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk int[] dimens = new int[2]; 48028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk LegacyExceptionUtils.throwOnError(nativeDetectTextureDimens(surfaceTexture, 48128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk /*out*/dimens)); 48228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 48328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk return new Size(dimens[0], dimens[1]); 48428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk } 48528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 486ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeDetectSurfaceType(Surface surface); 487feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 488ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeDetectSurfaceDimens(Surface surface, 489a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /*out*/int[/*2*/] dimens); 490feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 491ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeConfigureSurface(Surface surface, int width, int height, 492feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int pixelFormat); 493feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 494ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeProduceFrame(Surface surface, byte[] pixelBuffer, int width, 495feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int height, int pixelFormat); 496feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 497ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeSetSurfaceFormat(Surface surface, int pixelFormat); 498feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 499ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeSetSurfaceDimens(Surface surface, int width, int height); 500feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 5013c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk private static native long nativeGetSurfaceId(Surface surface); 50228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 50328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk private static native int nativeSetSurfaceOrientation(Surface surface, int facing, 50428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk int sensorOrientation); 50528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 50628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk private static native int nativeDetectTextureDimens(SurfaceTexture surfaceTexture, 50728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk /*out*/int[/*2*/] dimens); 50828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 509feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk} 510