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; 2451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkinimport android.hardware.camera2.impl.CameraDeviceImpl; 25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CaptureResultExtras; 26feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.ICameraDeviceCallbacks; 27e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport android.hardware.camera2.params.StreamConfigurationMap; 28e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport android.hardware.camera2.utils.ArrayUtils; 295d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.hardware.camera2.utils.SubmitInfo; 30feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CameraMetadataNative; 31feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.ConditionVariable; 32feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.Handler; 33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.HandlerThread; 34feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.RemoteException; 355d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.os.ServiceSpecificException; 36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log; 37f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunkimport android.util.Pair; 38a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.util.Size; 39385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvalaimport android.util.SparseArray; 40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.view.Surface; 41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 42feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.ArrayList; 43e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport java.util.Arrays; 443c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkimport java.util.Collection; 45feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.List; 4649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 47ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkimport static android.hardware.camera2.legacy.LegacyExceptionUtils.*; 48a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport static com.android.internal.util.Preconditions.*; 49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/** 51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This class emulates the functionality of a Camera2 device using a the old Camera class. 52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * There are two main components that are used to implement this: 55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A state machine containing valid Camera2 device states ({@link CameraDeviceState}). 56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A message-queue based pipeline that manages an old Camera class, and executes capture and 57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * configuration requests. 58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 60feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class LegacyCameraDevice implements AutoCloseable { 61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final String TAG; 62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 63a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala private static final boolean DEBUG = false; 64feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final int mCameraId; 65e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private final CameraCharacteristics mStaticCharacteristics; 66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final ICameraDeviceCallbacks mDeviceCallbacks; 67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final CameraDeviceState mDeviceState = new CameraDeviceState(); 68385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala private SparseArray<Surface> mConfiguredSurfaces; 69e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private boolean mClosed = false; 70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final ConditionVariable mIdle = new ConditionVariable(/*open*/true); 72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 73d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final HandlerThread mResultThread = new HandlerThread("ResultThread"); 74d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final HandlerThread mCallbackHandlerThread = new HandlerThread("CallbackThread"); 75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final Handler mCallbackHandler; 76d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final Handler mResultHandler; 77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private static final int ILLEGAL_VALUE = -1; 78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 79f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk // Keep up to date with values in hardware/libhardware/include/hardware/gralloc.h 80f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private static final int GRALLOC_USAGE_RENDERSCRIPT = 0x00100000; 81f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private static final int GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003; 82f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private static final int GRALLOC_USAGE_HW_TEXTURE = 0x00000100; 83f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private static final int GRALLOC_USAGE_HW_COMPOSER = 0x00000800; 84a7677722304670dc07feef242156b97e6bb51bcdZhijun He private static final int GRALLOC_USAGE_HW_RENDER = 0x00000200; 85f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private static final int GRALLOC_USAGE_HW_VIDEO_ENCODER = 0x00010000; 86f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 8768e4fc8ca9b923bc6d053589329eab8509d625abRuben Brunk public static final int MAX_DIMEN_FOR_ROUNDING = 1920; // maximum allowed width for rounding 88f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 89a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk // Keep up to date with values in system/core/include/system/window.h 90a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk public static final int NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW = 1; 91a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk 92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) { 93385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala return getExtrasFromRequest(holder, 94385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala /*errorCode*/CameraDeviceState.NO_CAPTURE_ERROR, /*errorArg*/null); 95385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 96385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala 97385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala private CaptureResultExtras getExtrasFromRequest(RequestHolder holder, 98385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala int errorCode, Object errorArg) { 99385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala int errorStreamId = -1; 100385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala if (errorCode == CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER) { 101385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala Surface errorTarget = (Surface) errorArg; 102385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala int indexOfTarget = mConfiguredSurfaces.indexOfValue(errorTarget); 103385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala if (indexOfTarget < 0) { 104385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala Log.e(TAG, "Buffer drop error reported for unknown Surface"); 105385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } else { 106385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala errorStreamId = mConfiguredSurfaces.keyAt(indexOfTarget); 107385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 108385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 109feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (holder == null) { 110feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, 1113e0023ae89895f215791a8472f22b213f5a9ae93Eino-Ville Talvala ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE); 112feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 113feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(), 11483159151f618c79040a2e800de8cc78f22bf760bZhijun He /*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(), 115385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala /*partialResultCount*/1, errorStreamId); 116feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 117feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 118feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 119feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Listener for the camera device state machine. Calls the appropriate 120feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link ICameraDeviceCallbacks} for each state transition. 121feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 122feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final CameraDeviceState.CameraDeviceStateListener mStateListener = 123feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk new CameraDeviceState.CameraDeviceStateListener() { 124feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 125385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala public void onError(final int errorCode, final Object errorArg, final RequestHolder holder) { 12651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin if (DEBUG) { 127385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala Log.d(TAG, "onError called, errorCode = " + errorCode + ", errorArg = " + errorArg); 12851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 12951dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin switch (errorCode) { 13051dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin /* 13151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin * Only be considered idle if we hit a fatal error 13251dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin * and no further requests can be processed. 13351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin */ 13451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin case CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DISCONNECTED: 13551dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin case CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_SERVICE: 13651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin case CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE: { 13751dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin mIdle.open(); 13851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin 13951dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin if (DEBUG) { 14051dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin Log.d(TAG, "onError - opening idle"); 14151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 14251dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 14351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 14451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin 145385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala final CaptureResultExtras extras = getExtrasFromRequest(holder, errorCode, errorArg); 146d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 147d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 148d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1493e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 150e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "doing onError callback for request " + holder.getRequestId() + 151e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ", with error code " + errorCode); 1523e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 153d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 154acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala mDeviceCallbacks.onDeviceError(errorCode, extras); 155d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 156d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 157d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 158d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 159d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 160d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 161feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 162feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 163feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 164feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onConfiguring() { 165feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // Do nothing 1663e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1673e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onConfiguring callback."); 1683e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 169feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 170feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 171feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 172feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onIdle() { 17351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin if (DEBUG) { 17451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin Log.d(TAG, "onIdle called"); 17551dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 17651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin 177feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.open(); 178feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 179d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 180d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 181d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1823e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1833e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onIdle callback."); 1843e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 185d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 186acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala mDeviceCallbacks.onDeviceIdle(); 187d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 188d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 189d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraIdle callback: ", e); 190d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 191d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 192d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 193feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 194feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 195feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 19651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin public void onBusy() { 19751dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin mIdle.close(); 19851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin 19951dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin if (DEBUG) { 20051dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin Log.d(TAG, "onBusy called"); 20151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 20251dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 20351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin 20451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin @Override 205e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void onCaptureStarted(final RequestHolder holder, final long timestamp) { 206feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 207feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 208d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 209d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 210d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 2113e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 212e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "doing onCaptureStarted callback for request " + 213e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk holder.getRequestId()); 2143e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 215d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 216d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onCaptureStarted(extras, timestamp); 217d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 218d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 219d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 220d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 221d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 222d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 223feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 224feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 225feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 226234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang public void onRequestQueueEmpty() { 227234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang mResultHandler.post(new Runnable() { 228234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang @Override 229234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang public void run() { 230234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang if (DEBUG) { 231234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang Log.d(TAG, "doing onRequestQueueEmpty callback"); 232234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang } 233234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang try { 234234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang mDeviceCallbacks.onRequestQueueEmpty(); 235234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang } catch (RemoteException e) { 236234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang throw new IllegalStateException( 237234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang "Received remote exception during onRequestQueueEmpty callback: ", 238234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang e); 239234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang } 240234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang } 241234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang }); 242234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang } 243234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang 244234ba3ef752742e2f87094e67896a8bde5709d12Shuzhen Wang @Override 245e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void onCaptureResult(final CameraMetadataNative result, final RequestHolder holder) { 246feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 247feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 248d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 249d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 250d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 2513e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 252e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "doing onCaptureResult callback for request " + 253e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk holder.getRequestId()); 2543e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 255d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 256d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onResultReceived(result, extras); 257d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 258d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 259d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 260d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 261d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 262d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 263feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 2642da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen 2652da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen @Override 2668cd12e9b7cc73b1bbe5e478acdf463c5381f33efYin-Chia Yeh public void onRepeatingRequestError(final long lastFrameNumber, 2678cd12e9b7cc73b1bbe5e478acdf463c5381f33efYin-Chia Yeh final int repeatingRequestId) { 2682da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen mResultHandler.post(new Runnable() { 2692da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen @Override 2702da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen public void run() { 2712da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen if (DEBUG) { 2722da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen Log.d(TAG, "doing onRepeatingRequestError callback."); 2732da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 2742da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen try { 2758cd12e9b7cc73b1bbe5e478acdf463c5381f33efYin-Chia Yeh mDeviceCallbacks.onRepeatingRequestError(lastFrameNumber, 2768cd12e9b7cc73b1bbe5e478acdf463c5381f33efYin-Chia Yeh repeatingRequestId); 2772da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } catch (RemoteException e) { 2782da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen throw new IllegalStateException( 2792da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen "Received remote exception during onRepeatingRequestError " + 2802da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen "callback: ", e); 2812da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 2822da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 2832da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen }); 2842da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 285feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk }; 286feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 287feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final RequestThreadManager mRequestThreadManager; 288feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 289feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 29091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * Check if a given surface uses {@link ImageFormat#YUV_420_888} or format that can be readily 29191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * converted to this; YV12 and NV21 are the two currently supported formats. 292feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 293feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param s the surface to check. 29491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * @return {@code true} if the surfaces uses {@link ImageFormat#YUV_420_888} or a compatible 29591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * format. 296feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 297ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static boolean needsConversion(Surface s) throws BufferQueueAbandonedException { 298ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int nativeType = detectSurfaceType(s); 29991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk return nativeType == ImageFormat.YUV_420_888 || nativeType == ImageFormat.YV12 || 30091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk nativeType == ImageFormat.NV21; 301feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 302feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 303feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 304feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Create a new emulated camera device from a given Camera 1 API camera. 305feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 306feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 307feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * The {@link Camera} provided to this constructor must already have been successfully opened, 308feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * and ownership of the provided camera is passed to this object. No further calls to the 309feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * camera methods should be made following this constructor. 310feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 311feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 312feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param cameraId the id of the camera. 313feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param camera an open {@link Camera} device. 314df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @param characteristics the static camera characteristics for this camera device 315feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param callbacks {@link ICameraDeviceCallbacks} callbacks to call for Camera2 API operations. 316feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 317df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin public LegacyCameraDevice(int cameraId, Camera camera, CameraCharacteristics characteristics, 318df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin ICameraDeviceCallbacks callbacks) { 319feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCameraId = cameraId; 320feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDeviceCallbacks = callbacks; 321feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk TAG = String.format("CameraDevice-%d-LE", mCameraId); 322feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 323d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.start(); 324d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler = new Handler(mResultThread.getLooper()); 325feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandlerThread.start(); 326feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandler = new Handler(mCallbackHandlerThread.getLooper()); 327feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDeviceState.setCameraDeviceCallbacks(mCallbackHandler, mStateListener); 328e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mStaticCharacteristics = characteristics; 329feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager = 330df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin new RequestThreadManager(cameraId, camera, characteristics, mDeviceState); 331feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.start(); 332feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 333feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 334feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 335feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Configure the device with a set of output surfaces. 336feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 33749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * <p>Using empty or {@code null} {@code outputs} is the same as unconfiguring.</p> 33849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * 33949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * <p>Every surface in {@code outputs} must be non-{@code null}.</p> 34049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * 341385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala * @param outputs a list of surfaces to set. LegacyCameraDevice will take ownership of this 342385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala * list; it must not be modified by the caller once it's passed in. 34349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * @return an error code for this binder operation, or {@link NO_ERROR} 344feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * on success. 345feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 346385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala public int configureOutputs(SparseArray<Surface> outputs) { 347f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk List<Pair<Surface, Size>> sizedSurfaces = new ArrayList<>(); 34849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (outputs != null) { 349385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala int count = outputs.size(); 350385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala for (int i = 0; i < count; i++) { 351385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala Surface output = outputs.valueAt(i); 35249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (output == null) { 35349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "configureOutputs - null outputs are not allowed"); 35449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 35549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 356443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk if (!output.isValid()) { 357443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk Log.e(TAG, "configureOutputs - invalid output surfaces are not allowed"); 358443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk return BAD_VALUE; 359443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk } 360e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk StreamConfigurationMap streamConfigurations = mStaticCharacteristics. 361e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 362e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 363e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Validate surface size and format. 364e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk try { 365e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Size s = getSurfaceSize(output); 366e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk int surfaceType = detectSurfaceType(output); 367e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 368fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala boolean flexibleConsumer = isFlexibleConsumer(output); 369f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 370f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Size[] sizes = streamConfigurations.getOutputSizes(surfaceType); 371e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (sizes == null) { 37271e6d62d232cce042ae1f98328b628aaca108850Shuzhen Wang if (surfaceType == ImageFormat.PRIVATE) { 373e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 374f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk // YUV_420_888 is always present in LEGACY for all 375f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk // IMPLEMENTATION_DEFINED output sizes, and is publicly visible in the 376f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk // API (i.e. {@code #getOutputSizes} works here). 377e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk sizes = streamConfigurations.getOutputSizes(ImageFormat.YUV_420_888); 378e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } else if (surfaceType == LegacyMetadataMapper.HAL_PIXEL_FORMAT_BLOB) { 379e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk sizes = streamConfigurations.getOutputSizes(ImageFormat.JPEG); 380e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 381e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 382e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 383e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (!ArrayUtils.contains(sizes, s)) { 384f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk if (flexibleConsumer && (s = findClosestSize(s, sizes)) != null) { 385f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk sizedSurfaces.add(new Pair<>(output, s)); 386f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } else { 387f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk String reason = (sizes == null) ? "format is invalid." : 388f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk ("size not in valid set: " + Arrays.toString(sizes)); 389f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Log.e(TAG, String.format("Surface with size (w=%d, h=%d) and format " + 390f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk "0x%x is not valid, %s", s.getWidth(), s.getHeight(), 391f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk surfaceType, reason)); 392f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk return BAD_VALUE; 393f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 394f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } else { 395f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk sizedSurfaces.add(new Pair<>(output, s)); 396e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 397315bc0971539f97aaf424c6b21b789a7c8ca9e04Eino-Ville Talvala // Lock down the size before configuration 398315bc0971539f97aaf424c6b21b789a7c8ca9e04Eino-Ville Talvala setSurfaceDimens(output, s.getWidth(), s.getHeight()); 399e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } catch (BufferQueueAbandonedException e) { 400e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, "Surface bufferqueue is abandoned, cannot configure as output: ", e); 401e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return BAD_VALUE; 402e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 403e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 40449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 40549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 40649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 4074aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk boolean success = false; 4084aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk if (mDeviceState.setConfiguring()) { 409f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk mRequestThreadManager.configure(sizedSurfaces); 4104aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk success = mDeviceState.setIdle(); 411feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 41249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 4134aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk if (success) { 414385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala mConfiguredSurfaces = outputs; 4154aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk } else { 4165d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala return LegacyExceptionUtils.INVALID_OPERATION; 41749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 4185d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala return LegacyExceptionUtils.NO_ERROR; 419feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 420feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 421feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 422feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit a burst of capture requests. 423feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 424feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestList a list of capture requests to execute. 425feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating {@code true} if this burst is repeating. 4265d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * @return the submission info, including the new request id, and the last frame number, which 4275d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * contains either the frame number of the last frame that will be returned for this request, 4285d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * or the frame number of the last frame that will be returned for the current repeating 4295d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * request if this burst is set to be repeating. 430feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 4315d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala public SubmitInfo submitRequestList(CaptureRequest[] requestList, boolean repeating) { 4325d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala if (requestList == null || requestList.length == 0) { 43349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - Empty/null requests are not allowed"); 4345d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new ServiceSpecificException(BAD_VALUE, 4355d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "submitRequestList - Empty/null requests are not allowed"); 43649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 43749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 4382da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen List<Long> surfaceIds; 4392da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen 4402da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen try { 4412da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen surfaceIds = (mConfiguredSurfaces == null) ? new ArrayList<Long>() : 4422da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen getSurfaceIds(mConfiguredSurfaces); 4432da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } catch (BufferQueueAbandonedException e) { 4442da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen throw new ServiceSpecificException(BAD_VALUE, 4452da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen "submitRequestList - configured surface is abandoned."); 4462da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 4473c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 44849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin // Make sure that there all requests have at least 1 surface; all surfaces are non-null 44949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (CaptureRequest request : requestList) { 45049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (request.getTargets().isEmpty()) { 45149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - " 45249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin + "Each request must have at least one Surface target"); 4535d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new ServiceSpecificException(BAD_VALUE, 4545d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "submitRequestList - " 4555d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala + "Each request must have at least one Surface target"); 45649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 45749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 45849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (Surface surface : request.getTargets()) { 45949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (surface == null) { 46049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - Null Surface targets are not allowed"); 4615d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new ServiceSpecificException(BAD_VALUE, 4625d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "submitRequestList - Null Surface targets are not allowed"); 46349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } else if (mConfiguredSurfaces == null) { 46449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - must configure " + 46549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin " device with valid surfaces before submitting requests"); 4665d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new ServiceSpecificException(INVALID_OPERATION, 4675d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "submitRequestList - must configure " + 4685d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala " device with valid surfaces before submitting requests"); 4693c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } else if (!containsSurfaceId(surface, surfaceIds)) { 47049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - cannot use a surface that wasn't configured"); 4715d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new ServiceSpecificException(BAD_VALUE, 4725d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "submitRequestList - cannot use a surface that wasn't configured"); 47349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 47449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 47549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 47649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 47749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin // TODO: further validation of request here 478feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.close(); 4795d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala return mRequestThreadManager.submitCaptureRequests(requestList, repeating); 480feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 481feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 482feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 483feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit a single capture request. 484feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 485feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param request the capture request to execute. 486feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating {@code true} if this request is repeating. 4875d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * @return the submission info, including the new request id, and the last frame number, which 4885d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * contains either the frame number of the last frame that will be returned for this request, 4895d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * or the frame number of the last frame that will be returned for the current repeating 4905d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * request if this burst is set to be repeating. 491feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 4925d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala public SubmitInfo submitRequest(CaptureRequest request, boolean repeating) { 4935d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala CaptureRequest[] requestList = { request }; 4945d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala return submitRequestList(requestList, repeating); 495feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 496feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 497feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 498feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Cancel the repeating request with the given request id. 499feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 500feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestId the request id of the request to cancel. 501feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the last frame number to be returned from the HAL for the given repeating request, or 502feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@code INVALID_FRAME} if none exists. 503feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 504feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public long cancelRequest(int requestId) { 505feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return mRequestThreadManager.cancelRepeating(requestId); 506feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 507feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 508feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 509feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Block until the {@link ICameraDeviceCallbacks#onCameraIdle()} callback is received. 510feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 511feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void waitUntilIdle() { 512feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.block(); 513feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 514feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 515e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /** 516e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * Flush any pending requests. 517e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * 518e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * @return the last frame number. 519e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk */ 520e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public long flush() { 521e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk long lastFrame = mRequestThreadManager.flush(); 522e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk waitUntilIdle(); 523e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return lastFrame; 524e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 525e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 526e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /** 527e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * Return {@code true} if the device has been closed. 528e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk */ 529e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public boolean isClosed() { 530e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return mClosed; 531e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 532e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 533feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 534feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void close() { 535feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.quit(); 536feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandlerThread.quitSafely(); 537d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.quitSafely(); 538d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 539d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 540d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mCallbackHandlerThread.join(); 541d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (InterruptedException e) { 542d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 543d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mCallbackHandlerThread.getName(), mCallbackHandlerThread.getId())); 544d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 545d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 546d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 547d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.join(); 548d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (InterruptedException e) { 549d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 550d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.getName(), mResultThread.getId())); 551d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 552d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 553e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mClosed = true; 554feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 555feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 556feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 557feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk protected void finalize() throws Throwable { 558feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk try { 559feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk close(); 5605d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } catch (ServiceSpecificException e) { 561feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage()); 562feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } finally { 563feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk super.finalize(); 564feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 565feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 566feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 567f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk static long findEuclidDistSquare(Size a, Size b) { 568f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk long d0 = a.getWidth() - b.getWidth(); 569f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk long d1 = a.getHeight() - b.getHeight(); 570f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk return d0 * d0 + d1 * d1; 571f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 572f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 573f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk // Keep up to date with rounding behavior in 574f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk // frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp 575f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk static Size findClosestSize(Size size, Size[] supportedSizes) { 576f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk if (size == null || supportedSizes == null) { 577f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk return null; 578f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 579f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Size bestSize = null; 580f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk for (Size s : supportedSizes) { 581f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk if (s.equals(size)) { 582f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk return size; 583f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } else if (s.getWidth() <= MAX_DIMEN_FOR_ROUNDING && (bestSize == null || 584f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk LegacyCameraDevice.findEuclidDistSquare(size, s) < 585f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk LegacyCameraDevice.findEuclidDistSquare(bestSize, s))) { 586f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk bestSize = s; 587f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 588f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 589f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk return bestSize; 590f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 591f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 592a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /** 593a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * Query the surface for its currently configured default buffer size. 594a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @param surface a non-{@code null} {@code Surface} 595a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @return the width and height of the surface 596a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * 597a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @throws NullPointerException if the {@code surface} was {@code null} 598443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk * @throws BufferQueueAbandonedException if the {@code surface} was invalid 599a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin */ 600fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala public static Size getSurfaceSize(Surface surface) throws BufferQueueAbandonedException { 601a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin checkNotNull(surface); 602a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 603a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin int[] dimens = new int[2]; 604ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDimens(surface, /*out*/dimens)); 605a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 606a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin return new Size(dimens[0], dimens[1]); 607a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 608a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 609fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala public static boolean isFlexibleConsumer(Surface output) { 610fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala int usageFlags = detectSurfaceUsageFlags(output); 611fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala 612fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala // Keep up to date with allowed consumer types in 613fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala // frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp 614fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala int disallowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_RENDERSCRIPT; 615fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala int allowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN | 616fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala GRALLOC_USAGE_HW_COMPOSER; 617fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala boolean flexibleConsumer = ((usageFlags & disallowedFlags) == 0 && 618fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala (usageFlags & allowedFlags) != 0); 619fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala return flexibleConsumer; 620fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala } 621fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala 622a7677722304670dc07feef242156b97e6bb51bcdZhijun He public static boolean isPreviewConsumer(Surface output) { 623a7677722304670dc07feef242156b97e6bb51bcdZhijun He int usageFlags = detectSurfaceUsageFlags(output); 624a7677722304670dc07feef242156b97e6bb51bcdZhijun He int disallowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_RENDERSCRIPT | 625a7677722304670dc07feef242156b97e6bb51bcdZhijun He GRALLOC_USAGE_SW_READ_OFTEN; 626a7677722304670dc07feef242156b97e6bb51bcdZhijun He int allowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER | 627a7677722304670dc07feef242156b97e6bb51bcdZhijun He GRALLOC_USAGE_HW_RENDER; 628a7677722304670dc07feef242156b97e6bb51bcdZhijun He boolean previewConsumer = ((usageFlags & disallowedFlags) == 0 && 629a7677722304670dc07feef242156b97e6bb51bcdZhijun He (usageFlags & allowedFlags) != 0); 630a7677722304670dc07feef242156b97e6bb51bcdZhijun He int surfaceFormat = ImageFormat.UNKNOWN; 631a7677722304670dc07feef242156b97e6bb51bcdZhijun He try { 632a7677722304670dc07feef242156b97e6bb51bcdZhijun He surfaceFormat = detectSurfaceType(output); 633a7677722304670dc07feef242156b97e6bb51bcdZhijun He } catch(BufferQueueAbandonedException e) { 634a7677722304670dc07feef242156b97e6bb51bcdZhijun He throw new IllegalArgumentException("Surface was abandoned", e); 635a7677722304670dc07feef242156b97e6bb51bcdZhijun He } 636a7677722304670dc07feef242156b97e6bb51bcdZhijun He 63747ac34997b34002a81cfaac3fdf429fdf329220cZhijun He return previewConsumer; 638a7677722304670dc07feef242156b97e6bb51bcdZhijun He } 639a7677722304670dc07feef242156b97e6bb51bcdZhijun He 640a7677722304670dc07feef242156b97e6bb51bcdZhijun He public static boolean isVideoEncoderConsumer(Surface output) { 641a7677722304670dc07feef242156b97e6bb51bcdZhijun He int usageFlags = detectSurfaceUsageFlags(output); 642a7677722304670dc07feef242156b97e6bb51bcdZhijun He int disallowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER | 643a7677722304670dc07feef242156b97e6bb51bcdZhijun He GRALLOC_USAGE_RENDERSCRIPT | GRALLOC_USAGE_SW_READ_OFTEN; 644a7677722304670dc07feef242156b97e6bb51bcdZhijun He int allowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER; 645a7677722304670dc07feef242156b97e6bb51bcdZhijun He boolean videoEncoderConsumer = ((usageFlags & disallowedFlags) == 0 && 646a7677722304670dc07feef242156b97e6bb51bcdZhijun He (usageFlags & allowedFlags) != 0); 647a7677722304670dc07feef242156b97e6bb51bcdZhijun He 648a7677722304670dc07feef242156b97e6bb51bcdZhijun He int surfaceFormat = ImageFormat.UNKNOWN; 649a7677722304670dc07feef242156b97e6bb51bcdZhijun He try { 650a7677722304670dc07feef242156b97e6bb51bcdZhijun He surfaceFormat = detectSurfaceType(output); 651a7677722304670dc07feef242156b97e6bb51bcdZhijun He } catch(BufferQueueAbandonedException e) { 652a7677722304670dc07feef242156b97e6bb51bcdZhijun He throw new IllegalArgumentException("Surface was abandoned", e); 653a7677722304670dc07feef242156b97e6bb51bcdZhijun He } 654a7677722304670dc07feef242156b97e6bb51bcdZhijun He 65547ac34997b34002a81cfaac3fdf429fdf329220cZhijun He return videoEncoderConsumer; 656a7677722304670dc07feef242156b97e6bb51bcdZhijun He } 657a7677722304670dc07feef242156b97e6bb51bcdZhijun He 658fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala /** 659fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala * Query the surface for its currently configured usage flags 660fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala */ 661f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk static int detectSurfaceUsageFlags(Surface surface) { 662f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk checkNotNull(surface); 663f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk return nativeDetectSurfaceUsageFlags(surface); 664f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 665f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 666fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala /** 667fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala * Query the surface for its currently configured format 668fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala */ 669fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala public static int detectSurfaceType(Surface surface) throws BufferQueueAbandonedException { 670ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 67171e6d62d232cce042ae1f98328b628aaca108850Shuzhen Wang int surfaceType = nativeDetectSurfaceType(surface); 67271e6d62d232cce042ae1f98328b628aaca108850Shuzhen Wang 67371e6d62d232cce042ae1f98328b628aaca108850Shuzhen Wang // TODO: remove this override since the default format should be 67471e6d62d232cce042ae1f98328b628aaca108850Shuzhen Wang // ImageFormat.PRIVATE. b/9487482 67571e6d62d232cce042ae1f98328b628aaca108850Shuzhen Wang if ((surfaceType >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 && 67671e6d62d232cce042ae1f98328b628aaca108850Shuzhen Wang surfaceType <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) { 67771e6d62d232cce042ae1f98328b628aaca108850Shuzhen Wang surfaceType = ImageFormat.PRIVATE; 67871e6d62d232cce042ae1f98328b628aaca108850Shuzhen Wang } 67971e6d62d232cce042ae1f98328b628aaca108850Shuzhen Wang 68071e6d62d232cce042ae1f98328b628aaca108850Shuzhen Wang return LegacyExceptionUtils.throwOnError(surfaceType); 681ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 682ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 683e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala /** 684e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala * Query the surface for its currently configured dataspace 685e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala */ 686e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala public static int detectSurfaceDataspace(Surface surface) throws BufferQueueAbandonedException { 687e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala checkNotNull(surface); 688e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDataspace(surface)); 689e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala } 690e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala 69129c3630563452c9635f0510d071839c112d3017dChien-Yu Chen static void connectSurface(Surface surface) throws BufferQueueAbandonedException { 692ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 693ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 69429c3630563452c9635f0510d071839c112d3017dChien-Yu Chen LegacyExceptionUtils.throwOnError(nativeConnectSurface(surface)); 69529c3630563452c9635f0510d071839c112d3017dChien-Yu Chen } 69629c3630563452c9635f0510d071839c112d3017dChien-Yu Chen 69729c3630563452c9635f0510d071839c112d3017dChien-Yu Chen static void disconnectSurface(Surface surface) throws BufferQueueAbandonedException { 69829c3630563452c9635f0510d071839c112d3017dChien-Yu Chen if (surface == null) return; 69929c3630563452c9635f0510d071839c112d3017dChien-Yu Chen 70029c3630563452c9635f0510d071839c112d3017dChien-Yu Chen LegacyExceptionUtils.throwOnError(nativeDisconnectSurface(surface)); 701ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 702ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 703ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void produceFrame(Surface surface, byte[] pixelBuffer, int width, 704ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int height, int pixelFormat) 705ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 706ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 707ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(pixelBuffer); 708ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 709ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 710ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 711ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeProduceFrame(surface, pixelBuffer, width, height, 712ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk pixelFormat)); 713ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 714ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 715ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void setSurfaceFormat(Surface surface, int pixelFormat) 716ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 717ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 718ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 719ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceFormat(surface, pixelFormat)); 720ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 721ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 722ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void setSurfaceDimens(Surface surface, int width, int height) 723ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 724ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 725ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 726ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 727ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 728ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceDimens(surface, width, height)); 729ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 730ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 7312da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen static long getSurfaceId(Surface surface) throws BufferQueueAbandonedException { 7323c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk checkNotNull(surface); 7332da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen try { 7342da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen return nativeGetSurfaceId(surface); 7352da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } catch (IllegalArgumentException e) { 7362da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen throw new BufferQueueAbandonedException(); 7372da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 7383c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 7393c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 7402da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen static List<Long> getSurfaceIds(SparseArray<Surface> surfaces) 7412da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen throws BufferQueueAbandonedException { 742385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala if (surfaces == null) { 743385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala throw new NullPointerException("Null argument surfaces"); 744385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 745385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala List<Long> surfaceIds = new ArrayList<>(); 746385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala int count = surfaces.size(); 747385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala for (int i = 0; i < count; i++) { 748385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala long id = getSurfaceId(surfaces.valueAt(i)); 749385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala if (id == 0) { 750385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala throw new IllegalStateException( 751385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala "Configured surface had null native GraphicBufferProducer pointer!"); 752385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 753385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala surfaceIds.add(id); 754385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 755385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala return surfaceIds; 756385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 757385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala 7582da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen static List<Long> getSurfaceIds(Collection<Surface> surfaces) 7592da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen throws BufferQueueAbandonedException { 7603c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk if (surfaces == null) { 7613c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk throw new NullPointerException("Null argument surfaces"); 7623c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 7633c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk List<Long> surfaceIds = new ArrayList<>(); 7643c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk for (Surface s : surfaces) { 7653c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk long id = getSurfaceId(s); 7663c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk if (id == 0) { 7673c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk throw new IllegalStateException( 7683c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk "Configured surface had null native GraphicBufferProducer pointer!"); 7693c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 7703c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk surfaceIds.add(id); 7713c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 7723c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return surfaceIds; 7733c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 7743c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 7750fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk static boolean containsSurfaceId(Surface s, Collection<Long> ids) { 7762da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen long id = 0; 7772da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen try { 7782da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen id = getSurfaceId(s); 7792da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } catch (BufferQueueAbandonedException e) { 7802da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen // If surface is abandoned, return false. 7812da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen return false; 7822da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 7833c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return ids.contains(id); 7843c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 7853c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 78628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk static void setSurfaceOrientation(Surface surface, int facing, int sensorOrientation) 78728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk throws BufferQueueAbandonedException { 78828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk checkNotNull(surface); 78928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceOrientation(surface, facing, 79028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk sensorOrientation)); 79128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk } 79228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 79328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk static Size getTextureSize(SurfaceTexture surfaceTexture) 79428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk throws BufferQueueAbandonedException { 79528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk checkNotNull(surfaceTexture); 79628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 79728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk int[] dimens = new int[2]; 79828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk LegacyExceptionUtils.throwOnError(nativeDetectTextureDimens(surfaceTexture, 79928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk /*out*/dimens)); 80028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 80128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk return new Size(dimens[0], dimens[1]); 80228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk } 80328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 80491838ded36131525312739c0929913b215519c2aRuben Brunk static void setNextTimestamp(Surface surface, long timestamp) 80591838ded36131525312739c0929913b215519c2aRuben Brunk throws BufferQueueAbandonedException { 80691838ded36131525312739c0929913b215519c2aRuben Brunk checkNotNull(surface); 80791838ded36131525312739c0929913b215519c2aRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetNextTimestamp(surface, timestamp)); 80891838ded36131525312739c0929913b215519c2aRuben Brunk } 80991838ded36131525312739c0929913b215519c2aRuben Brunk 810a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk static void setScalingMode(Surface surface, int mode) 811a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk throws BufferQueueAbandonedException { 812a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk checkNotNull(surface); 813a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk LegacyExceptionUtils.throwOnError(nativeSetScalingMode(surface, mode)); 814a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk } 815a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk 816a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk 817ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeDetectSurfaceType(Surface surface); 818feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 819e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala private static native int nativeDetectSurfaceDataspace(Surface surface); 820e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala 821ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeDetectSurfaceDimens(Surface surface, 822a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /*out*/int[/*2*/] dimens); 823feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 82429c3630563452c9635f0510d071839c112d3017dChien-Yu Chen private static native int nativeConnectSurface(Surface surface); 825feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 826ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeProduceFrame(Surface surface, byte[] pixelBuffer, int width, 827feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int height, int pixelFormat); 828feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 829ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeSetSurfaceFormat(Surface surface, int pixelFormat); 830feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 831ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeSetSurfaceDimens(Surface surface, int width, int height); 832feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 8333c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk private static native long nativeGetSurfaceId(Surface surface); 83428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 83528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk private static native int nativeSetSurfaceOrientation(Surface surface, int facing, 83628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk int sensorOrientation); 83728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 83828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk private static native int nativeDetectTextureDimens(SurfaceTexture surfaceTexture, 83928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk /*out*/int[/*2*/] dimens); 84028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 84191838ded36131525312739c0929913b215519c2aRuben Brunk private static native int nativeSetNextTimestamp(Surface surface, long timestamp); 8421dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk 843f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private static native int nativeDetectSurfaceUsageFlags(Surface surface); 844f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 845a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk private static native int nativeSetScalingMode(Surface surface, int scalingMode); 846a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk 84729c3630563452c9635f0510d071839c112d3017dChien-Yu Chen private static native int nativeDisconnectSurface(Surface surface); 84829c3630563452c9635f0510d071839c112d3017dChien-Yu Chen 8491dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk static native int nativeGetJpegFooterSize(); 850feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk} 851