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