LegacyCameraDevice.java revision 29c3630563452c9635f0510d071839c112d3017d
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;
294aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunkimport android.hardware.camera2.utils.CameraBinderDecorator;
30feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.LongParcelable;
31feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CameraMetadataNative;
32feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.CameraRuntimeException;
33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.ConditionVariable;
34feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.Handler;
35feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.HandlerThread;
36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.RemoteException;
37feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log;
38f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunkimport android.util.Pair;
39a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.util.Size;
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.*;
4849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkinimport static android.hardware.camera2.utils.CameraBinderDecorator.*;
49a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport static com.android.internal.util.Preconditions.*;
50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This class emulates the functionality of a Camera2 device using a the old Camera class.
53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p>
55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * There are two main components that are used to implement this:
56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A state machine containing valid Camera2 device states ({@link CameraDeviceState}).
57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A message-queue based pipeline that manages an old Camera class, and executes capture and
58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *   configuration requests.
59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p>
60feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class LegacyCameraDevice implements AutoCloseable {
62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final String TAG;
63feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
64a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala    private static final boolean DEBUG = false;
65feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final int mCameraId;
66e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    private final CameraCharacteristics mStaticCharacteristics;
67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final ICameraDeviceCallbacks mDeviceCallbacks;
68feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final CameraDeviceState mDeviceState = new CameraDeviceState();
6949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin    private List<Surface> mConfiguredSurfaces;
70e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    private boolean mClosed = false;
71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final ConditionVariable mIdle = new ConditionVariable(/*open*/true);
73feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
74d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk    private final HandlerThread mResultThread = new HandlerThread("ResultThread");
75d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk    private final HandlerThread mCallbackHandlerThread = new HandlerThread("CallbackThread");
76feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final Handler mCallbackHandler;
77d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk    private final Handler mResultHandler;
78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final int ILLEGAL_VALUE = -1;
79feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
80f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    // Keep up to date with values in hardware/libhardware/include/hardware/gralloc.h
81f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    private static final int GRALLOC_USAGE_RENDERSCRIPT = 0x00100000;
82f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    private static final int GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003;
83f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    private static final int GRALLOC_USAGE_HW_TEXTURE = 0x00000100;
84f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    private static final int GRALLOC_USAGE_HW_COMPOSER = 0x00000800;
85a7677722304670dc07feef242156b97e6bb51bcdZhijun He    private static final int GRALLOC_USAGE_HW_RENDER = 0x00000200;
86f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    private static final int GRALLOC_USAGE_HW_VIDEO_ENCODER = 0x00010000;
87f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
8868e4fc8ca9b923bc6d053589329eab8509d625abRuben Brunk    public static final int MAX_DIMEN_FOR_ROUNDING = 1920; // maximum allowed width for rounding
89f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
90a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    // Keep up to date with values in system/core/include/system/window.h
91a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    public static final int NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW = 1;
92a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk
93feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) {
94feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (holder == null) {
95feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE,
9683159151f618c79040a2e800de8cc78f22bf760bZhijun He                    ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE);
97feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
98feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(),
9983159151f618c79040a2e800de8cc78f22bf760bZhijun He                /*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(),
10083159151f618c79040a2e800de8cc78f22bf760bZhijun He                /*partialResultCount*/1);
101feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
102feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
103feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
104feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Listener for the camera device state machine.  Calls the appropriate
105feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * {@link ICameraDeviceCallbacks} for each state transition.
106feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
107feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final CameraDeviceState.CameraDeviceStateListener mStateListener =
108feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            new CameraDeviceState.CameraDeviceStateListener() {
109feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        @Override
110e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        public void onError(final int errorCode, final RequestHolder holder) {
11151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin            if (DEBUG) {
11251dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                Log.d(TAG, "onError called, errorCode = " + errorCode);
11351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin            }
11451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin            switch (errorCode) {
11551dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                /*
11651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                 * Only be considered idle if we hit a fatal error
11751dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                 * and no further requests can be processed.
11851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                 */
11951dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                case CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DISCONNECTED:
12051dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                case CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_SERVICE:
12151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                case CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE: {
12251dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                    mIdle.open();
12351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin
12451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                    if (DEBUG) {
12551dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                        Log.d(TAG, "onError - opening idle");
12651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                    }
12751dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                }
12851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin            }
12951dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin
130feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            final CaptureResultExtras extras = getExtrasFromRequest(holder);
131d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk            mResultHandler.post(new Runnable() {
132d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                @Override
133d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                public void run() {
1343e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk                    if (DEBUG) {
135e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        Log.d(TAG, "doing onError callback for request " + holder.getRequestId() +
136e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                                ", with error code " + errorCode);
1373e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk                    }
138d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    try {
139acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala                        mDeviceCallbacks.onDeviceError(errorCode, extras);
140d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    } catch (RemoteException e) {
141d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                        throw new IllegalStateException(
142d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                                "Received remote exception during onCameraError callback: ", e);
143d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    }
144d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                }
145d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk            });
146feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
147feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
148feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        @Override
149feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        public void onConfiguring() {
150feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // Do nothing
1513e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk            if (DEBUG) {
1523e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk                Log.d(TAG, "doing onConfiguring callback.");
1533e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk            }
154feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
155feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
156feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        @Override
157feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        public void onIdle() {
15851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin            if (DEBUG) {
15951dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                Log.d(TAG, "onIdle called");
16051dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin            }
16151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin
162feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mIdle.open();
163feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
164d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk            mResultHandler.post(new Runnable() {
165d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                @Override
166d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                public void run() {
1673e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk                    if (DEBUG) {
1683e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk                        Log.d(TAG, "doing onIdle callback.");
1693e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk                    }
170d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    try {
171acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala                        mDeviceCallbacks.onDeviceIdle();
172d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    } catch (RemoteException e) {
173d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                        throw new IllegalStateException(
174d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                                "Received remote exception during onCameraIdle callback: ", e);
175d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    }
176d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                }
177d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk            });
178feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
179feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
180feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        @Override
18151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin        public void onBusy() {
18251dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin            mIdle.close();
18351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin
18451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin            if (DEBUG) {
18551dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                Log.d(TAG, "onBusy called");
18651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin            }
18751dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin        }
18851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin
18951dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin        @Override
190e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        public void onCaptureStarted(final RequestHolder holder, final long timestamp) {
191feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            final CaptureResultExtras extras = getExtrasFromRequest(holder);
192feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
193d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk            mResultHandler.post(new Runnable() {
194d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                @Override
195d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                public void run() {
1963e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk                    if (DEBUG) {
197e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        Log.d(TAG, "doing onCaptureStarted callback for request " +
198e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                                holder.getRequestId());
1993e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk                    }
200d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    try {
201d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                        mDeviceCallbacks.onCaptureStarted(extras, timestamp);
202d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    } catch (RemoteException e) {
203d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                        throw new IllegalStateException(
204d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                                "Received remote exception during onCameraError callback: ", e);
205d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    }
206d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                }
207d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk            });
208feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
209feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
210feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        @Override
211e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        public void onCaptureResult(final CameraMetadataNative result, final RequestHolder holder) {
212feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            final CaptureResultExtras extras = getExtrasFromRequest(holder);
213feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
214d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk            mResultHandler.post(new Runnable() {
215d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                @Override
216d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                public void run() {
2173e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk                    if (DEBUG) {
218e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        Log.d(TAG, "doing onCaptureResult callback for request " +
219e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                                holder.getRequestId());
2203e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk                    }
221d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    try {
222d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                        mDeviceCallbacks.onResultReceived(result, extras);
223d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    } catch (RemoteException e) {
224d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                        throw new IllegalStateException(
225d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                                "Received remote exception during onCameraError callback: ", e);
226d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    }
227d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                }
228d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk            });
229feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
230feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    };
231feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
232feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final RequestThreadManager mRequestThreadManager;
233feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
234feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
23591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk     * Check if a given surface uses {@link ImageFormat#YUV_420_888} or format that can be readily
23691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk     * converted to this; YV12 and NV21 are the two currently supported formats.
237feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
238feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param s the surface to check.
23991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk     * @return {@code true} if the surfaces uses {@link ImageFormat#YUV_420_888} or a compatible
24091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk     *          format.
241feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
242ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    static boolean needsConversion(Surface s) throws BufferQueueAbandonedException {
243ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        int nativeType = detectSurfaceType(s);
24491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk        return nativeType == ImageFormat.YUV_420_888 || nativeType == ImageFormat.YV12 ||
24591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                nativeType == ImageFormat.NV21;
246feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
247feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
248feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
249feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Create a new emulated camera device from a given Camera 1 API camera.
250feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
251feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * <p>
252feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * The {@link Camera} provided to this constructor must already have been successfully opened,
253feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * and ownership of the provided camera is passed to this object.  No further calls to the
254feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * camera methods should be made following this constructor.
255feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * </p>
256feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
257feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param cameraId the id of the camera.
258feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param camera an open {@link Camera} device.
259df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin     * @param characteristics the static camera characteristics for this camera device
260feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param callbacks {@link ICameraDeviceCallbacks} callbacks to call for Camera2 API operations.
261feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
262df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin    public LegacyCameraDevice(int cameraId, Camera camera, CameraCharacteristics characteristics,
263df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin            ICameraDeviceCallbacks callbacks) {
264feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mCameraId = cameraId;
265feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mDeviceCallbacks = callbacks;
266feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        TAG = String.format("CameraDevice-%d-LE", mCameraId);
267feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
268d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk        mResultThread.start();
269d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk        mResultHandler = new Handler(mResultThread.getLooper());
270feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mCallbackHandlerThread.start();
271feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mCallbackHandler = new Handler(mCallbackHandlerThread.getLooper());
272feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mDeviceState.setCameraDeviceCallbacks(mCallbackHandler, mStateListener);
273e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        mStaticCharacteristics = characteristics;
274feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mRequestThreadManager =
275df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin                new RequestThreadManager(cameraId, camera, characteristics, mDeviceState);
276feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mRequestThreadManager.start();
277feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
278feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
279feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
280feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Configure the device with a set of output surfaces.
281feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
28249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin     * <p>Using empty or {@code null} {@code outputs} is the same as unconfiguring.</p>
28349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin     *
28449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin     * <p>Every surface in {@code outputs} must be non-{@code null}.</p>
28549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin     *
286feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param outputs a list of surfaces to set.
28749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin     * @return an error code for this binder operation, or {@link NO_ERROR}
288feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *          on success.
289feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
290feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int configureOutputs(List<Surface> outputs) {
291f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        List<Pair<Surface, Size>> sizedSurfaces = new ArrayList<>();
29249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin        if (outputs != null) {
29349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin            for (Surface output : outputs) {
29449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                if (output == null) {
29549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                    Log.e(TAG, "configureOutputs - null outputs are not allowed");
29649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                    return BAD_VALUE;
29749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                }
298443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk                if (!output.isValid()) {
299443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk                    Log.e(TAG, "configureOutputs - invalid output surfaces are not allowed");
300443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk                    return BAD_VALUE;
301443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk                }
302e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                StreamConfigurationMap streamConfigurations = mStaticCharacteristics.
303e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
304e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
305e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                // Validate surface size and format.
306e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                try {
307e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    Size s = getSurfaceSize(output);
308e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    int surfaceType = detectSurfaceType(output);
309e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
310fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala                    boolean flexibleConsumer = isFlexibleConsumer(output);
311f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
312f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                    Size[] sizes = streamConfigurations.getOutputSizes(surfaceType);
313e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    if (sizes == null) {
314e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        // WAR: Override default format to IMPLEMENTATION_DEFINED for b/9487482
315e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        if ((surfaceType >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 &&
316e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                            surfaceType <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) {
317e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
318f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                            // YUV_420_888 is always present in LEGACY for all
319f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                            // IMPLEMENTATION_DEFINED output sizes, and is publicly visible in the
320f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                            // API (i.e. {@code #getOutputSizes} works here).
321e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                            sizes = streamConfigurations.getOutputSizes(ImageFormat.YUV_420_888);
322e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        } else if (surfaceType == LegacyMetadataMapper.HAL_PIXEL_FORMAT_BLOB) {
323e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                            sizes = streamConfigurations.getOutputSizes(ImageFormat.JPEG);
324e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        }
325e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    }
326e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
327e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    if (!ArrayUtils.contains(sizes, s)) {
328f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                        if (flexibleConsumer && (s = findClosestSize(s, sizes)) != null) {
329f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                            sizedSurfaces.add(new Pair<>(output, s));
330f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                        } else {
331f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                            String reason = (sizes == null) ? "format is invalid." :
332f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                                    ("size not in valid set: " + Arrays.toString(sizes));
333f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                            Log.e(TAG, String.format("Surface with size (w=%d, h=%d) and format " +
334f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                                    "0x%x is not valid, %s", s.getWidth(), s.getHeight(),
335f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                                    surfaceType, reason));
336f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                            return BAD_VALUE;
337f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                        }
338f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                    } else {
339f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                        sizedSurfaces.add(new Pair<>(output, s));
340e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    }
341315bc0971539f97aaf424c6b21b789a7c8ca9e04Eino-Ville Talvala                    // Lock down the size before configuration
342315bc0971539f97aaf424c6b21b789a7c8ca9e04Eino-Ville Talvala                    setSurfaceDimens(output, s.getWidth(), s.getHeight());
343e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                } catch (BufferQueueAbandonedException e) {
344e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    Log.e(TAG, "Surface bufferqueue is abandoned, cannot configure as output: ", e);
345e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    return BAD_VALUE;
346e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                }
347e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
34849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin            }
34949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin        }
35049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin
3514aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk        boolean success = false;
3524aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk        if (mDeviceState.setConfiguring()) {
353f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk            mRequestThreadManager.configure(sizedSurfaces);
3544aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk            success = mDeviceState.setIdle();
355feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
35649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin
3574aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk        if (success) {
35849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin            mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null;
3594aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk        } else {
3604aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk            return CameraBinderDecorator.INVALID_OPERATION;
36149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin        }
3624aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk        return CameraBinderDecorator.NO_ERROR;
363feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
364feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
365feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
366feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Submit a burst of capture requests.
367feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
368feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param requestList a list of capture requests to execute.
369feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param repeating {@code true} if this burst is repeating.
370feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param frameNumber an output argument that contains either the frame number of the last frame
371feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *                    that will be returned for this request, or the frame number of the last
372feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *                    frame that will be returned for the current repeating request if this
373feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *                    burst is set to be repeating.
374feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @return the request id.
375feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
376feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int submitRequestList(List<CaptureRequest> requestList, boolean repeating,
377feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            /*out*/LongParcelable frameNumber) {
37849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin        if (requestList == null || requestList.isEmpty()) {
37949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin            Log.e(TAG, "submitRequestList - Empty/null requests are not allowed");
38049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin            return BAD_VALUE;
38149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin        }
38249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin
3833c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        List<Long> surfaceIds = (mConfiguredSurfaces == null) ? new ArrayList<Long>() :
3843c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk                getSurfaceIds(mConfiguredSurfaces);
3853c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
38649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin        // Make sure that there all requests have at least 1 surface; all surfaces are non-null
38749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin        for (CaptureRequest request : requestList) {
38849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin            if (request.getTargets().isEmpty()) {
38949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                Log.e(TAG, "submitRequestList - "
39049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                        + "Each request must have at least one Surface target");
39149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                return BAD_VALUE;
39249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin            }
39349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin
39449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin            for (Surface surface : request.getTargets()) {
39549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                if (surface == null) {
39649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                    Log.e(TAG, "submitRequestList - Null Surface targets are not allowed");
39749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                    return BAD_VALUE;
39849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                } else if (mConfiguredSurfaces == null) {
39949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                    Log.e(TAG, "submitRequestList - must configure " +
40049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                            " device with valid surfaces before submitting requests");
40149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                    return INVALID_OPERATION;
4023c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk                } else if (!containsSurfaceId(surface, surfaceIds)) {
40349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                    Log.e(TAG, "submitRequestList - cannot use a surface that wasn't configured");
40449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                    return BAD_VALUE;
40549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin                }
40649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin            }
40749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin        }
40849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin
40949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin        // TODO: further validation of request here
410feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mIdle.close();
411feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return mRequestThreadManager.submitCaptureRequests(requestList, repeating,
412feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                frameNumber);
413feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
414feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
415feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
416feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Submit a single capture request.
417feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
418feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param request the capture request to execute.
419feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param repeating {@code true} if this request is repeating.
420feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param frameNumber an output argument that contains either the frame number of the last frame
421feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *                    that will be returned for this request, or the frame number of the last
422feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *                    frame that will be returned for the current repeating request if this
423feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *                    request is set to be repeating.
424feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @return the request id.
425feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
426feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int submitRequest(CaptureRequest request, boolean repeating,
427feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            /*out*/LongParcelable frameNumber) {
428feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ArrayList<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
429feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        requestList.add(request);
430feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return submitRequestList(requestList, repeating, frameNumber);
431feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
432feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
433feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
434feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Cancel the repeating request with the given request id.
435feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
436feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param requestId the request id of the request to cancel.
437feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @return the last frame number to be returned from the HAL for the given repeating request, or
438feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *          {@code INVALID_FRAME} if none exists.
439feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
440feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public long cancelRequest(int requestId) {
441feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return mRequestThreadManager.cancelRepeating(requestId);
442feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
443feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
444feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
445feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Block until the {@link ICameraDeviceCallbacks#onCameraIdle()} callback is received.
446feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
447feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public void waitUntilIdle()  {
448feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mIdle.block();
449feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
450feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
451e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    /**
452e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     * Flush any pending requests.
453e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     *
454e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     * @return the last frame number.
455e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     */
456e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    public long flush() {
457e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        long lastFrame = mRequestThreadManager.flush();
458e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        waitUntilIdle();
459e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        return lastFrame;
460e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    }
461e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
462e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    /**
463e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     * Return {@code true} if the device has been closed.
464e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     */
465e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    public boolean isClosed() {
466e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        return mClosed;
467e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    }
468e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
469feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
470feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public void close() {
471feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mRequestThreadManager.quit();
472feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mCallbackHandlerThread.quitSafely();
473d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk        mResultThread.quitSafely();
474d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk
475d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk        try {
476d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk            mCallbackHandlerThread.join();
477d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk        } catch (InterruptedException e) {
478d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk            Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.",
479d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    mCallbackHandlerThread.getName(), mCallbackHandlerThread.getId()));
480d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk        }
481d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk
482d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk        try {
483d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk            mResultThread.join();
484d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk        } catch (InterruptedException e) {
485d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk            Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.",
486d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    mResultThread.getName(), mResultThread.getId()));
487d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk        }
488d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk
489e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        mClosed = true;
490feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
491feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
492feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
493feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    protected void finalize() throws Throwable {
494feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        try {
495feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            close();
496feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        } catch (CameraRuntimeException e) {
497feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage());
498feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        } finally {
499feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            super.finalize();
500feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
501feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
502feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
503f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    static long findEuclidDistSquare(Size a, Size b) {
504f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        long d0 = a.getWidth() - b.getWidth();
505f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        long d1 = a.getHeight() - b.getHeight();
506f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        return d0 * d0 + d1 * d1;
507f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    }
508f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
509f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    // Keep up to date with rounding behavior in
510f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    // frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
511f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    static Size findClosestSize(Size size, Size[] supportedSizes) {
512f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        if (size == null || supportedSizes == null) {
513f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk            return null;
514f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        }
515f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        Size bestSize = null;
516f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        for (Size s : supportedSizes) {
517f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk            if (s.equals(size)) {
518f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                return size;
519f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk            } else if (s.getWidth() <= MAX_DIMEN_FOR_ROUNDING && (bestSize == null ||
520f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                    LegacyCameraDevice.findEuclidDistSquare(size, s) <
521f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                    LegacyCameraDevice.findEuclidDistSquare(bestSize, s))) {
522f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk                bestSize = s;
523f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk            }
524f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        }
525f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        return bestSize;
526f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    }
527f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
528a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    /**
529a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * Query the surface for its currently configured default buffer size.
530a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * @param surface a non-{@code null} {@code Surface}
531a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * @return the width and height of the surface
532a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     *
533a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * @throws NullPointerException if the {@code surface} was {@code null}
534443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk     * @throws BufferQueueAbandonedException if the {@code surface} was invalid
535a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     */
536fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala    public static Size getSurfaceSize(Surface surface) throws BufferQueueAbandonedException {
537a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        checkNotNull(surface);
538a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
539a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        int[] dimens = new int[2];
540ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDimens(surface, /*out*/dimens));
541a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
542a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        return new Size(dimens[0], dimens[1]);
543a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    }
544a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
545fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala    public static boolean isFlexibleConsumer(Surface output) {
546fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        int usageFlags = detectSurfaceUsageFlags(output);
547fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala
548fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        // Keep up to date with allowed consumer types in
549fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        // frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
550fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        int disallowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_RENDERSCRIPT;
551fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        int allowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN |
552fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala            GRALLOC_USAGE_HW_COMPOSER;
553fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        boolean flexibleConsumer = ((usageFlags & disallowedFlags) == 0 &&
554fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala                (usageFlags & allowedFlags) != 0);
555fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        return flexibleConsumer;
556fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala    }
557fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala
558a7677722304670dc07feef242156b97e6bb51bcdZhijun He    public static boolean isPreviewConsumer(Surface output) {
559a7677722304670dc07feef242156b97e6bb51bcdZhijun He        int usageFlags = detectSurfaceUsageFlags(output);
560a7677722304670dc07feef242156b97e6bb51bcdZhijun He        int disallowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_RENDERSCRIPT |
561a7677722304670dc07feef242156b97e6bb51bcdZhijun He                GRALLOC_USAGE_SW_READ_OFTEN;
562a7677722304670dc07feef242156b97e6bb51bcdZhijun He        int allowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER |
563a7677722304670dc07feef242156b97e6bb51bcdZhijun He                GRALLOC_USAGE_HW_RENDER;
564a7677722304670dc07feef242156b97e6bb51bcdZhijun He        boolean previewConsumer = ((usageFlags & disallowedFlags) == 0 &&
565a7677722304670dc07feef242156b97e6bb51bcdZhijun He                (usageFlags & allowedFlags) != 0);
566a7677722304670dc07feef242156b97e6bb51bcdZhijun He        int surfaceFormat = ImageFormat.UNKNOWN;
567a7677722304670dc07feef242156b97e6bb51bcdZhijun He        try {
568a7677722304670dc07feef242156b97e6bb51bcdZhijun He            surfaceFormat = detectSurfaceType(output);
569a7677722304670dc07feef242156b97e6bb51bcdZhijun He        } catch(BufferQueueAbandonedException e) {
570a7677722304670dc07feef242156b97e6bb51bcdZhijun He            throw new IllegalArgumentException("Surface was abandoned", e);
571a7677722304670dc07feef242156b97e6bb51bcdZhijun He        }
572a7677722304670dc07feef242156b97e6bb51bcdZhijun He
57347ac34997b34002a81cfaac3fdf429fdf329220cZhijun He        return previewConsumer;
574a7677722304670dc07feef242156b97e6bb51bcdZhijun He    }
575a7677722304670dc07feef242156b97e6bb51bcdZhijun He
576a7677722304670dc07feef242156b97e6bb51bcdZhijun He    public static boolean isVideoEncoderConsumer(Surface output) {
577a7677722304670dc07feef242156b97e6bb51bcdZhijun He        int usageFlags = detectSurfaceUsageFlags(output);
578a7677722304670dc07feef242156b97e6bb51bcdZhijun He        int disallowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER |
579a7677722304670dc07feef242156b97e6bb51bcdZhijun He                GRALLOC_USAGE_RENDERSCRIPT | GRALLOC_USAGE_SW_READ_OFTEN;
580a7677722304670dc07feef242156b97e6bb51bcdZhijun He        int allowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER;
581a7677722304670dc07feef242156b97e6bb51bcdZhijun He        boolean videoEncoderConsumer = ((usageFlags & disallowedFlags) == 0 &&
582a7677722304670dc07feef242156b97e6bb51bcdZhijun He                (usageFlags & allowedFlags) != 0);
583a7677722304670dc07feef242156b97e6bb51bcdZhijun He
584a7677722304670dc07feef242156b97e6bb51bcdZhijun He        int surfaceFormat = ImageFormat.UNKNOWN;
585a7677722304670dc07feef242156b97e6bb51bcdZhijun He        try {
586a7677722304670dc07feef242156b97e6bb51bcdZhijun He            surfaceFormat = detectSurfaceType(output);
587a7677722304670dc07feef242156b97e6bb51bcdZhijun He        } catch(BufferQueueAbandonedException e) {
588a7677722304670dc07feef242156b97e6bb51bcdZhijun He            throw new IllegalArgumentException("Surface was abandoned", e);
589a7677722304670dc07feef242156b97e6bb51bcdZhijun He        }
590a7677722304670dc07feef242156b97e6bb51bcdZhijun He
59147ac34997b34002a81cfaac3fdf429fdf329220cZhijun He        return videoEncoderConsumer;
592a7677722304670dc07feef242156b97e6bb51bcdZhijun He    }
593a7677722304670dc07feef242156b97e6bb51bcdZhijun He
594fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala    /**
595fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     * Query the surface for its currently configured usage flags
596fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     */
597f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    static int detectSurfaceUsageFlags(Surface surface) {
598f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        checkNotNull(surface);
599f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk        return nativeDetectSurfaceUsageFlags(surface);
600f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    }
601f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
602fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala    /**
603fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     * Query the surface for its currently configured format
604fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     */
605fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala    public static int detectSurfaceType(Surface surface) throws BufferQueueAbandonedException {
606ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        checkNotNull(surface);
607ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceType(surface));
608ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    }
609ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk
610e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    /**
611e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala     * Query the surface for its currently configured dataspace
612e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala     */
613e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    public static int detectSurfaceDataspace(Surface surface) throws BufferQueueAbandonedException {
614e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala        checkNotNull(surface);
615e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala        return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDataspace(surface));
616e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    }
617e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala
61829c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    static void connectSurface(Surface surface) throws BufferQueueAbandonedException {
619ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        checkNotNull(surface);
620ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk
62129c3630563452c9635f0510d071839c112d3017dChien-Yu Chen        LegacyExceptionUtils.throwOnError(nativeConnectSurface(surface));
62229c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    }
62329c3630563452c9635f0510d071839c112d3017dChien-Yu Chen
62429c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    static void disconnectSurface(Surface surface) throws BufferQueueAbandonedException {
62529c3630563452c9635f0510d071839c112d3017dChien-Yu Chen        if (surface == null) return;
62629c3630563452c9635f0510d071839c112d3017dChien-Yu Chen
62729c3630563452c9635f0510d071839c112d3017dChien-Yu Chen        LegacyExceptionUtils.throwOnError(nativeDisconnectSurface(surface));
628ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    }
629ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk
630ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    static void produceFrame(Surface surface, byte[] pixelBuffer, int width,
631ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                             int height, int pixelFormat)
632ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk            throws BufferQueueAbandonedException {
633ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        checkNotNull(surface);
634ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        checkNotNull(pixelBuffer);
635ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        checkArgumentPositive(width, "width must be positive.");
636ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        checkArgumentPositive(height, "height must be positive.");
637ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk
638ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        LegacyExceptionUtils.throwOnError(nativeProduceFrame(surface, pixelBuffer, width, height,
639ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                pixelFormat));
640ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    }
641ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk
642ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    static void setSurfaceFormat(Surface surface, int pixelFormat)
643ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk            throws BufferQueueAbandonedException {
644ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        checkNotNull(surface);
645ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk
646ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        LegacyExceptionUtils.throwOnError(nativeSetSurfaceFormat(surface, pixelFormat));
647ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    }
648ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk
649ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    static void setSurfaceDimens(Surface surface, int width, int height)
650ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk            throws BufferQueueAbandonedException {
651ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        checkNotNull(surface);
652ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        checkArgumentPositive(width, "width must be positive.");
653ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        checkArgumentPositive(height, "height must be positive.");
654ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk
655ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        LegacyExceptionUtils.throwOnError(nativeSetSurfaceDimens(surface, width, height));
656ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    }
657ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk
6583c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    static long getSurfaceId(Surface surface) {
6593c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        checkNotNull(surface);
6603c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return nativeGetSurfaceId(surface);
6613c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6623c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
6633c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    static List<Long> getSurfaceIds(Collection<Surface> surfaces) {
6643c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        if (surfaces == null) {
6653c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk            throw new NullPointerException("Null argument surfaces");
6663c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        }
6673c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        List<Long> surfaceIds = new ArrayList<>();
6683c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        for (Surface s : surfaces) {
6693c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk            long id = getSurfaceId(s);
6703c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk            if (id == 0) {
6713c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk                throw new IllegalStateException(
6723c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk                        "Configured surface had null native GraphicBufferProducer pointer!");
6733c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk            }
6743c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk            surfaceIds.add(id);
6753c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        }
6763c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return surfaceIds;
6773c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6783c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
6790fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk    static boolean containsSurfaceId(Surface s, Collection<Long> ids) {
6803c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        long id = getSurfaceId(s);
6813c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return ids.contains(id);
6823c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6833c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
68428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    static void setSurfaceOrientation(Surface surface, int facing, int sensorOrientation)
68528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk            throws BufferQueueAbandonedException {
68628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        checkNotNull(surface);
68728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        LegacyExceptionUtils.throwOnError(nativeSetSurfaceOrientation(surface, facing,
68828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                sensorOrientation));
68928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
69028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
69128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    static Size getTextureSize(SurfaceTexture surfaceTexture)
69228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk            throws BufferQueueAbandonedException {
69328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        checkNotNull(surfaceTexture);
69428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
69528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        int[] dimens = new int[2];
69628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        LegacyExceptionUtils.throwOnError(nativeDetectTextureDimens(surfaceTexture,
69728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                /*out*/dimens));
69828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
69928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return new Size(dimens[0], dimens[1]);
70028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
70128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
70291838ded36131525312739c0929913b215519c2aRuben Brunk    static void setNextTimestamp(Surface surface, long timestamp)
70391838ded36131525312739c0929913b215519c2aRuben Brunk            throws BufferQueueAbandonedException {
70491838ded36131525312739c0929913b215519c2aRuben Brunk        checkNotNull(surface);
70591838ded36131525312739c0929913b215519c2aRuben Brunk        LegacyExceptionUtils.throwOnError(nativeSetNextTimestamp(surface, timestamp));
70691838ded36131525312739c0929913b215519c2aRuben Brunk    }
70791838ded36131525312739c0929913b215519c2aRuben Brunk
708a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    static void setScalingMode(Surface surface, int mode)
709a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk            throws BufferQueueAbandonedException {
710a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk        checkNotNull(surface);
711a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk        LegacyExceptionUtils.throwOnError(nativeSetScalingMode(surface, mode));
712a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    }
713a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk
714a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk
715ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    private static native int nativeDetectSurfaceType(Surface surface);
716feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
717e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala    private static native int nativeDetectSurfaceDataspace(Surface surface);
718e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala
719ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    private static native int nativeDetectSurfaceDimens(Surface surface,
720a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            /*out*/int[/*2*/] dimens);
721feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
72229c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    private static native int nativeConnectSurface(Surface surface);
723feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
724ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    private static native int nativeProduceFrame(Surface surface, byte[] pixelBuffer, int width,
725feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                                    int height, int pixelFormat);
726feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
727ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    private static native int nativeSetSurfaceFormat(Surface surface, int pixelFormat);
728feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
729ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    private static native int nativeSetSurfaceDimens(Surface surface, int width, int height);
730feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
7313c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    private static native long nativeGetSurfaceId(Surface surface);
73228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
73328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    private static native int nativeSetSurfaceOrientation(Surface surface, int facing,
73428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                                                             int sensorOrientation);
73528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
73628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    private static native int nativeDetectTextureDimens(SurfaceTexture surfaceTexture,
73728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk            /*out*/int[/*2*/] dimens);
73828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
73991838ded36131525312739c0929913b215519c2aRuben Brunk    private static native int nativeSetNextTimestamp(Surface surface, long timestamp);
7401dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk
741f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk    private static native int nativeDetectSurfaceUsageFlags(Surface surface);
742f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk
743a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk    private static native int nativeSetScalingMode(Surface surface, int scalingMode);
744a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk
74529c3630563452c9635f0510d071839c112d3017dChien-Yu Chen    private static native int nativeDisconnectSurface(Surface surface);
74629c3630563452c9635f0510d071839c112d3017dChien-Yu Chen
7471dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    static native int nativeGetJpegFooterSize();
748feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
749