CameraDeviceUserShim.java revision 2f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3
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.hardware.Camera;
20a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.hardware.Camera.CameraInfo;
21feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.CameraAccessException;
22a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.hardware.camera2.CameraCharacteristics;
23feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.CaptureRequest;
24feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.ICameraDeviceCallbacks;
25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.ICameraDeviceUser;
26feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.LongParcelable;
27feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CameraMetadataNative;
282f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvalaimport android.hardware.camera2.impl.CaptureResultExtras;
29feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.CameraBinderDecorator;
30feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.CameraRuntimeException;
31a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.os.ConditionVariable;
32feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.IBinder;
33a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.os.Looper;
342f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvalaimport android.os.Handler;
352f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvalaimport android.os.HandlerThread;
362f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvalaimport android.os.Message;
37feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.RemoteException;
38feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log;
39feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.SparseArray;
40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.view.Surface;
41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
42feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.ArrayList;
43feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.List;
44feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
45feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
46feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Compatibility implementation of the Camera2 API binder interface.
47feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
48feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p>
49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This is intended to be called from the same process as client
50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link android.hardware.camera2.CameraDevice}, and wraps a
51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link android.hardware.camera2.legacy.LegacyCameraDevice} that emulates Camera2 service using
52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * the Camera1 API.
53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p>
54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p>
56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Keep up to date with ICameraDeviceUser.aidl.
57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p>
58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class CameraDeviceUserShim implements ICameraDeviceUser {
60feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final String TAG = "CameraDeviceUserShim";
61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final boolean DEBUG = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.DEBUG);
63a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private static final int OPEN_CAMERA_TIMEOUT_MS = 5000; // 5 sec (same as api1 cts timeout)
64feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
65feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final LegacyCameraDevice mLegacyDevice;
66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final Object mConfigureLock = new Object();
68feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private int mSurfaceIdCounter;
69feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private boolean mConfiguring;
70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final SparseArray<Surface> mSurfaces;
71a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private final CameraCharacteristics mCameraCharacteristics;
72a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private final CameraLooper mCameraInit;
732f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    private final CameraCallbackThread mCameraCallbacks;
742f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
76a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    protected CameraDeviceUserShim(int cameraId, LegacyCameraDevice legacyCamera,
772f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            CameraCharacteristics characteristics, CameraLooper cameraInit,
782f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            CameraCallbackThread cameraCallbacks) {
79feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mLegacyDevice = legacyCamera;
80feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mConfiguring = false;
81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mSurfaces = new SparseArray<Surface>();
82a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        mCameraCharacteristics = characteristics;
83a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        mCameraInit = cameraInit;
842f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        mCameraCallbacks = cameraCallbacks;
85feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
86feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mSurfaceIdCounter = 0;
87feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
88feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
89a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    /**
90a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * Create a separate looper/thread for the camera to run on; open the camera.
91a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     *
92a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * <p>Since the camera automatically latches on to the current thread's looper,
93a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * it's important that we have our own thread with our own looper to guarantee
94a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * that the camera callbacks get correctly posted to our own thread.</p>
95a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     */
96a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private static class CameraLooper implements Runnable, AutoCloseable {
97a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final int mCameraId;
98a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private Looper mLooper;
99a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private volatile int mInitErrors;
100a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final Camera mCamera = Camera.openUninitialized();
101a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final ConditionVariable mStartDone = new ConditionVariable();
102a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final Thread mThread;
103a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
104a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /**
105a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Spin up a new thread, immediately open the camera in the background.
106a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
107a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * <p>Use {@link #waitForOpen} to block until the camera is finished opening.</p>
108a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
109a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @param cameraId numeric camera Id
110a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
111a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @see #waitForOpen
112a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
113a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public CameraLooper(int cameraId) {
114a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mCameraId = cameraId;
115a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
116a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mThread = new Thread(this);
117a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mThread.start();
118a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
119a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
120a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public Camera getCamera() {
121a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            return mCamera;
122a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
123a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
124a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        @Override
125a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public void run() {
126a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // Set up a looper to be used by camera.
127a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            Looper.prepare();
128a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
129a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // Save the looper so that we can terminate this thread
130a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // after we are done with it.
131a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLooper = Looper.myLooper();
132a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mInitErrors = mCamera.cameraInitUnspecified(mCameraId);
133a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
134a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mStartDone.open();
135a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            Looper.loop();  // Blocks forever until #close is called.
136a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
137a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
138a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /**
139a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Quit the looper safely; then join until the thread shuts down.
140a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
141a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        @Override
142a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public void close() {
143a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            if (mLooper == null) {
144a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                return;
145a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            }
146a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
147a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLooper.quitSafely();
148a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            try {
149a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                mThread.join();
150a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            } catch (InterruptedException e) {
151a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                throw new AssertionError(e);
152a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            }
153a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
154a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLooper = null;
155a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
156a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
157a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /**
158a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Block until the camera opens; then return its initialization error code (if any).
159a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
160a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @param timeoutMs timeout in milliseconds
161a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
162a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @return int error code
163a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
164a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @throws CameraRuntimeException if the camera open times out with ({@code CAMERA_ERROR})
165a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
166a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public int waitForOpen(int timeoutMs) {
167a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // Block until the camera is open asynchronously
168a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            if (!mStartDone.block(timeoutMs)) {
169a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                Log.e(TAG, "waitForOpen - Camera failed to open after timeout of "
170a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                        + OPEN_CAMERA_TIMEOUT_MS + " ms");
171a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                try {
172a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                    mCamera.release();
173a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                } catch (RuntimeException e) {
174a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                    Log.e(TAG, "connectBinderShim - Failed to release camera after timeout ", e);
175a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                }
176a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
177a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR);
178a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            }
179a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
180a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            return mInitErrors;
181a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
182a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    }
183a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
1842f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    /**
1852f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     * A thread to process callbacks to send back to the camera client.
1862f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     *
1872f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     * <p>This effectively emulates one-way binder semantics when in the same process as the
1882f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     * callee.</p>
1892f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     */
1902f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    private static class CameraCallbackThread implements ICameraDeviceCallbacks {
1912f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int CAMERA_ERROR = 0;
1922f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int CAMERA_IDLE = 1;
1932f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int CAPTURE_STARTED = 2;
1942f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int RESULT_RECEIVED = 3;
1952f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
1962f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private final HandlerThread mHandlerThread;
1972f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private Handler mHandler;
1982f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
1992f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private final ICameraDeviceCallbacks mCallbacks;
2002f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2012f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public CameraCallbackThread(ICameraDeviceCallbacks callbacks) {
2022f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mCallbacks = callbacks;
2032f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2042f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mHandlerThread = new HandlerThread("LegacyCameraCallback");
2052f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mHandlerThread.start();
2062f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2072f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2082f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void close() {
2092f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mHandlerThread.quitSafely();
2102f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2112f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2122f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
2132f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void onCameraError(final int errorCode, final CaptureResultExtras resultExtras) {
2142f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(CAMERA_ERROR,
2152f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                /*arg1*/ errorCode, /*arg2*/ 0,
2162f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                /*obj*/ resultExtras);
2172f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2182f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2192f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2202f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
2212f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void onCameraIdle() {
2222f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(CAMERA_IDLE);
2232f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2242f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2252f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2262f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
2272f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
2282f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(CAPTURE_STARTED,
2292f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*arg1*/ (int) (timestamp & 0xFFFFFFFFL),
2302f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*arg2*/ (int) ( (timestamp >> 32) & 0xFFFFFFFFL),
2312f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*obj*/ resultExtras);
2322f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2332f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2342f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2352f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
2362f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void onResultReceived(final CameraMetadataNative result,
2372f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                final CaptureResultExtras resultExtras) {
2382f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Object[] resultArray = new Object[] { result, resultExtras };
2392f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(RESULT_RECEIVED,
2402f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*obj*/ resultArray);
2412f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2422f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2432f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2442f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
2452f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public IBinder asBinder() {
2462f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            // This is solely intended to be used for in-process binding.
2472f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            return null;
2482f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2492f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2502f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private Handler getHandler() {
2512f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            if (mHandler == null) {
2522f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                mHandler = new CallbackHandler(mHandlerThread.getLooper());
2532f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            }
2542f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            return mHandler;
2552f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2562f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2572f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private class CallbackHandler extends Handler {
2582f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            public CallbackHandler(Looper l) {
2592f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                super(l);
2602f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            }
2612f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2622f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            public void handleMessage(Message msg) {
2632f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                try {
2642f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    switch (msg.what) {
2652f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case CAMERA_ERROR: {
2662f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            int errorCode = msg.arg1;
2672f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CaptureResultExtras resultExtras = (CaptureResultExtras) msg.obj;
2682f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            mCallbacks.onCameraError(errorCode, resultExtras);
2692f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
2702f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        }
2712f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case CAMERA_IDLE:
2722f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            mCallbacks.onCameraIdle();
2732f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
2742f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case CAPTURE_STARTED: {
2752f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            long timestamp = msg.arg2 & 0xFFFFFFFFL;
2762f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            timestamp = (timestamp << 32) | (msg.arg1 & 0xFFFFFFFFL);
2772f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CaptureResultExtras resultExtras = (CaptureResultExtras) msg.obj;
2782f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            mCallbacks.onCaptureStarted(resultExtras, timestamp);
2792f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
2802f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        }
2812f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case RESULT_RECEIVED: {
2822f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            Object[] resultArray = (Object[]) msg.obj;
2832f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CameraMetadataNative result = (CameraMetadataNative) resultArray[0];
2842f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CaptureResultExtras resultExtras = (CaptureResultExtras) resultArray[1];
2852f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            mCallbacks.onResultReceived(result, resultExtras);
2862f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
2872f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        }
2882f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        default:
2892f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            throw new IllegalArgumentException(
2902f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                                "Unknown callback message " + msg.what);
2912f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    }
2922f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                } catch (RemoteException e) {
2932f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    throw new IllegalStateException(
2942f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        "Received remote exception during camera callback " + msg.what, e);
2952f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                }
2962f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            }
2972f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2982f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    }
2992f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
300feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public static CameraDeviceUserShim connectBinderShim(ICameraDeviceCallbacks callbacks,
301feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                                         int cameraId) {
302feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
303feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "Opening shim Camera device");
304feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
305a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
306a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /*
307a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Put the camera open on a separate thread with its own looper; otherwise
308a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * if the main thread is used then the callbacks might never get delivered
309a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * (e.g. in CTS which run its own default looper only after tests)
310a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
311a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
312a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraLooper init = new CameraLooper(cameraId);
313a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
3142f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        CameraCallbackThread threadCallbacks = new CameraCallbackThread(callbacks);
3152f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
316a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        // TODO: Make this async instead of blocking
317a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        int initErrors = init.waitForOpen(OPEN_CAMERA_TIMEOUT_MS);
318a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        Camera legacyCamera = init.getCamera();
319a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin
320feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // Check errors old HAL initialization
321a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin        CameraBinderDecorator.throwOnError(initErrors);
322a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin
323a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraInfo info = new CameraInfo();
324a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        Camera.getCameraInfo(cameraId, info);
325a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
326a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraCharacteristics characteristics =
327a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                LegacyMetadataMapper.createCharacteristics(legacyCamera.getParameters(), info);
328df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin        LegacyCameraDevice device = new LegacyCameraDevice(
3292f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                cameraId, legacyCamera, characteristics, threadCallbacks);
3302f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        return new CameraDeviceUserShim(cameraId, device, characteristics, init, threadCallbacks);
331feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
332feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
333feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
334feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public void disconnect() {
335feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
336feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "disconnect called.");
337feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
338a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
339a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        try {
340a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLegacyDevice.close();
341a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        } finally {
342a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mCameraInit.close();
3432f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mCameraCallbacks.close();
344a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
345feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
346feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
347feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
348feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int submitRequest(CaptureRequest request, boolean streaming,
349feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                             /*out*/LongParcelable lastFrameNumber) {
350feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
351feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "submitRequest called.");
352feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
353feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
354feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
355feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot submit request, configuration change in progress.");
356feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
357feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
358feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
359feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return mLegacyDevice.submitRequest(request, streaming, lastFrameNumber);
360feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
361feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
362feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
363feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int submitRequestList(List<CaptureRequest> request, boolean streaming,
364feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 /*out*/LongParcelable lastFrameNumber) {
365feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
366feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "submitRequestList called.");
367feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
368feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
369feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
370feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot submit request, configuration change in progress.");
371feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
372feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
373feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
374feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return mLegacyDevice.submitRequestList(request, streaming, lastFrameNumber);
375feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
376feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
377feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
378feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int cancelRequest(int requestId, /*out*/LongParcelable lastFrameNumber) {
379feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
380feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "cancelRequest called.");
381feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
382feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
383feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
384feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot cancel request, configuration change in progress.");
385feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
386feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
387feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
388feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        long lastFrame = mLegacyDevice.cancelRequest(requestId);
389feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        lastFrameNumber.setNumber(lastFrame);
390feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
391feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
392feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
393feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
394feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int beginConfigure() {
395feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
396feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "beginConfigure called.");
397feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
398feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
399feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
400feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot begin configure, configuration change already in progress.");
401feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
402feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
403feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mConfiguring = true;
404feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
405feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
406feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
407feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
408feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
409feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int endConfigure() {
410feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
411feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "endConfigure called.");
412feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
413feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ArrayList<Surface> surfaces = null;
414feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
415feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (!mConfiguring) {
416feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot end configure, no configuration change in progress.");
417feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
418feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
419feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int numSurfaces = mSurfaces.size();
420feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (numSurfaces > 0) {
4215776aafc7e70c0b79c4bee2bc50f44121b37c962Ruben Brunk                surfaces = new ArrayList<>();
422feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                for (int i = 0; i < numSurfaces; ++i) {
423feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    surfaces.add(mSurfaces.valueAt(i));
424feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                }
425feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
426feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mConfiguring = false;
427feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
428feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return mLegacyDevice.configureOutputs(surfaces);
429feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
430feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
431feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
432feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int deleteStream(int streamId) {
433feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
434feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "deleteStream called.");
435feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
436feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
437feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (!mConfiguring) {
438feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot delete stream, beginConfigure hasn't been called yet.");
439feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
440feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
441feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int index = mSurfaces.indexOfKey(streamId);
442feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (index < 0) {
443feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot delete stream, stream id " + streamId + " doesn't exist.");
444feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.BAD_VALUE;
445feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
446feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mSurfaces.removeAt(index);
447feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
448feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
449feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
450feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
451feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
452feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int createStream(int width, int height, int format, Surface surface) {
453feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
454feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "createStream called.");
455feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
456feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
457feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (!mConfiguring) {
458feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot create stream, beginConfigure hasn't been called yet.");
459feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
460feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
461feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int id = ++mSurfaceIdCounter;
462feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mSurfaces.put(id, surface);
463feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return id;
464feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
465feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
466feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
467feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
468feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int createDefaultRequest(int templateId, /*out*/CameraMetadataNative request) {
469feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
470feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "createDefaultRequest called.");
471feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
472a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
473a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraMetadataNative template;
474a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        try {
475a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            template =
476a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                    LegacyMetadataMapper.createRequestTemplate(mCameraCharacteristics, templateId);
477a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        } catch (IllegalArgumentException e) {
478a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            Log.e(TAG, "createDefaultRequest - invalid templateId specified");
479a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            return CameraBinderDecorator.BAD_VALUE;
480a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
481a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
482a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        request.swap(template);
483feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
484feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
485feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
486feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
487feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int getCameraInfo(/*out*/CameraMetadataNative info) {
488feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
489feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "getCameraInfo called.");
490feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
491feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // TODO: implement getCameraInfo.
492feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        Log.e(TAG, "getCameraInfo unimplemented.");
493feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
494feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
495feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
496feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
497feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int waitUntilIdle() throws RemoteException {
498feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
499feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "waitUntilIdle called.");
500feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
501feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
502feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
503feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot wait until idle, configuration change in progress.");
504feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
505feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
506feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
507feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mLegacyDevice.waitUntilIdle();
508feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
509feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
510feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
511feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
512feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int flush(/*out*/LongParcelable lastFrameNumber) {
513feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
514feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "flush called.");
515feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
516feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
517feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
518feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot flush, configuration change in progress.");
519feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
520feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
521feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
522feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // TODO: implement flush.
523feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
524feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
525feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
526feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
527feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public IBinder asBinder() {
528feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // This is solely intended to be used for in-process binding.
529feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return null;
530feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
531feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
532