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