CameraDeviceUserShim.java revision 385f9e2146d2600ae9fd20053aab8ee5abcac9a6
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
195d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.hardware.ICameraService;
20feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.Camera;
21a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.hardware.Camera.CameraInfo;
22feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.CameraAccessException;
23a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.hardware.camera2.CameraCharacteristics;
24feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.CaptureRequest;
25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.ICameraDeviceCallbacks;
26feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.ICameraDeviceUser;
27feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CameraMetadataNative;
282f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvalaimport android.hardware.camera2.impl.CaptureResultExtras;
29bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yehimport android.hardware.camera2.params.OutputConfiguration;
305d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.hardware.camera2.utils.SubmitInfo;
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;
385d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.os.ServiceSpecificException;
39feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log;
40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.SparseArray;
41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.view.Surface;
42feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
43feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.ArrayList;
44feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.List;
45feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
468ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsicimport static android.system.OsConstants.EACCES;
478ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsicimport static android.system.OsConstants.ENODEV;
488ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic
49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Compatibility implementation of the Camera2 API binder interface.
51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p>
53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This is intended to be called from the same process as client
54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link android.hardware.camera2.CameraDevice}, and wraps a
55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link android.hardware.camera2.legacy.LegacyCameraDevice} that emulates Camera2 service using
56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * the Camera1 API.
57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p>
58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p>
60feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Keep up to date with ICameraDeviceUser.aidl.
61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p>
62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
636653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin@SuppressWarnings("deprecation")
64feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class CameraDeviceUserShim implements ICameraDeviceUser {
65feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final String TAG = "CameraDeviceUserShim";
66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
67a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala    private static final boolean DEBUG = false;
68a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private static final int OPEN_CAMERA_TIMEOUT_MS = 5000; // 5 sec (same as api1 cts timeout)
69feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final LegacyCameraDevice mLegacyDevice;
71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final Object mConfigureLock = new Object();
73feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private int mSurfaceIdCounter;
74feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private boolean mConfiguring;
75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final SparseArray<Surface> mSurfaces;
76a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private final CameraCharacteristics mCameraCharacteristics;
77a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private final CameraLooper mCameraInit;
782f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    private final CameraCallbackThread mCameraCallbacks;
792f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
80feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
81a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    protected CameraDeviceUserShim(int cameraId, LegacyCameraDevice legacyCamera,
822f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            CameraCharacteristics characteristics, CameraLooper cameraInit,
832f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            CameraCallbackThread cameraCallbacks) {
84feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mLegacyDevice = legacyCamera;
85feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mConfiguring = false;
86feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mSurfaces = new SparseArray<Surface>();
87a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        mCameraCharacteristics = characteristics;
88a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        mCameraInit = cameraInit;
892f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        mCameraCallbacks = cameraCallbacks;
90feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
91feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mSurfaceIdCounter = 0;
92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
93feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
948ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic    private static int translateErrorsFromCamera1(int errorCode) {
958ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic        if (errorCode == -EACCES) {
965d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            return ICameraService.ERROR_PERMISSION_DENIED;
978ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic        }
988ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic
998ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic        return errorCode;
1008ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic    }
1018ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic
102a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    /**
103a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * Create a separate looper/thread for the camera to run on; open the camera.
104a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     *
105a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * <p>Since the camera automatically latches on to the current thread's looper,
106a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * it's important that we have our own thread with our own looper to guarantee
107a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * that the camera callbacks get correctly posted to our own thread.</p>
108a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     */
109a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private static class CameraLooper implements Runnable, AutoCloseable {
110a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final int mCameraId;
111a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private Looper mLooper;
112a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private volatile int mInitErrors;
113a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final Camera mCamera = Camera.openUninitialized();
114a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final ConditionVariable mStartDone = new ConditionVariable();
115a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final Thread mThread;
116a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
117a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /**
118a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Spin up a new thread, immediately open the camera in the background.
119a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
120a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * <p>Use {@link #waitForOpen} to block until the camera is finished opening.</p>
121a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
122a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @param cameraId numeric camera Id
123a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
124a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @see #waitForOpen
125a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
126a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public CameraLooper(int cameraId) {
127a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mCameraId = cameraId;
128a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
129a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mThread = new Thread(this);
130a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mThread.start();
131a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
132a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
133a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public Camera getCamera() {
134a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            return mCamera;
135a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
136a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
137a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        @Override
138a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public void run() {
139a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // Set up a looper to be used by camera.
140a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            Looper.prepare();
141a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
142a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // Save the looper so that we can terminate this thread
143a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // after we are done with it.
144a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLooper = Looper.myLooper();
145db70a9785315a29c1d0d1233d883062b8d07c46fEino-Ville Talvala            mInitErrors = mCamera.cameraInitUnspecified(mCameraId);
146a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mStartDone.open();
147a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            Looper.loop();  // Blocks forever until #close is called.
148a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
149a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
150a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /**
151a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Quit the looper safely; then join until the thread shuts down.
152a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
153a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        @Override
154a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public void close() {
155a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            if (mLooper == null) {
156a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                return;
157a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            }
158a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
159a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLooper.quitSafely();
160a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            try {
161a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                mThread.join();
162a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            } catch (InterruptedException e) {
163a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                throw new AssertionError(e);
164a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            }
165a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
166a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLooper = null;
167a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
168a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
169a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /**
170a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Block until the camera opens; then return its initialization error code (if any).
171a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
172a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @param timeoutMs timeout in milliseconds
173a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
174a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @return int error code
175a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
1765d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala         * @throws ServiceSpecificException if the camera open times out with ({@code CAMERA_ERROR})
177a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
178a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public int waitForOpen(int timeoutMs) {
179a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // Block until the camera is open asynchronously
180a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            if (!mStartDone.block(timeoutMs)) {
181a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                Log.e(TAG, "waitForOpen - Camera failed to open after timeout of "
182a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                        + OPEN_CAMERA_TIMEOUT_MS + " ms");
183a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                try {
184a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                    mCamera.release();
185a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                } catch (RuntimeException e) {
186a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                    Log.e(TAG, "connectBinderShim - Failed to release camera after timeout ", e);
187a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                }
188a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
1895d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION);
190a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            }
191a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
192a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            return mInitErrors;
193a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
194a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    }
195a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
1962f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    /**
1972f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     * A thread to process callbacks to send back to the camera client.
1982f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     *
1992f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     * <p>This effectively emulates one-way binder semantics when in the same process as the
2002f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     * callee.</p>
2012f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     */
2022f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    private static class CameraCallbackThread implements ICameraDeviceCallbacks {
2032f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int CAMERA_ERROR = 0;
2042f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int CAMERA_IDLE = 1;
2052f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int CAPTURE_STARTED = 2;
2062f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int RESULT_RECEIVED = 3;
207be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala        private static final int PREPARED = 4;
2082f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2092f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private final HandlerThread mHandlerThread;
2102f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private Handler mHandler;
2112f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2122f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private final ICameraDeviceCallbacks mCallbacks;
2132f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2142f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public CameraCallbackThread(ICameraDeviceCallbacks callbacks) {
2152f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mCallbacks = callbacks;
2162f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2172f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mHandlerThread = new HandlerThread("LegacyCameraCallback");
2182f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mHandlerThread.start();
2192f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2202f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2212f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void close() {
2222f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mHandlerThread.quitSafely();
2232f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2242f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2252f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
226acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala        public void onDeviceError(final int errorCode, final CaptureResultExtras resultExtras) {
2272f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(CAMERA_ERROR,
2282f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                /*arg1*/ errorCode, /*arg2*/ 0,
2292f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                /*obj*/ resultExtras);
2302f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2312f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2322f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2332f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
234acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala        public void onDeviceIdle() {
2352f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(CAMERA_IDLE);
2362f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2372f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2382f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2392f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
2402f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
2412f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(CAPTURE_STARTED,
2422f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*arg1*/ (int) (timestamp & 0xFFFFFFFFL),
2432f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*arg2*/ (int) ( (timestamp >> 32) & 0xFFFFFFFFL),
2442f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*obj*/ resultExtras);
2452f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2462f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2472f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2482f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
2492f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void onResultReceived(final CameraMetadataNative result,
2502f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                final CaptureResultExtras resultExtras) {
2512f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Object[] resultArray = new Object[] { result, resultExtras };
2522f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(RESULT_RECEIVED,
2532f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*obj*/ resultArray);
2542f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2552f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2562f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2572f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
258ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        public void onPrepared(int streamId) {
259be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala            Message msg = getHandler().obtainMessage(PREPARED,
260be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala                    /*arg1*/ streamId, /*arg2*/ 0);
261be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala            getHandler().sendMessage(msg);
262ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        }
263ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala
264ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        @Override
2652f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public IBinder asBinder() {
2662f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            // This is solely intended to be used for in-process binding.
2672f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            return null;
2682f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2692f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2702f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private Handler getHandler() {
2712f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            if (mHandler == null) {
2722f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                mHandler = new CallbackHandler(mHandlerThread.getLooper());
2732f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            }
2742f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            return mHandler;
2752f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2762f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2772f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private class CallbackHandler extends Handler {
2782f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            public CallbackHandler(Looper l) {
2792f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                super(l);
2802f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            }
2812f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2826653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin            @Override
2832f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            public void handleMessage(Message msg) {
2842f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                try {
2852f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    switch (msg.what) {
2862f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case CAMERA_ERROR: {
2872f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            int errorCode = msg.arg1;
2882f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CaptureResultExtras resultExtras = (CaptureResultExtras) msg.obj;
289acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala                            mCallbacks.onDeviceError(errorCode, resultExtras);
2902f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
2912f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        }
2922f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case CAMERA_IDLE:
293acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala                            mCallbacks.onDeviceIdle();
2942f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
2952f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case CAPTURE_STARTED: {
2962f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            long timestamp = msg.arg2 & 0xFFFFFFFFL;
2972f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            timestamp = (timestamp << 32) | (msg.arg1 & 0xFFFFFFFFL);
2982f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CaptureResultExtras resultExtras = (CaptureResultExtras) msg.obj;
2992f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            mCallbacks.onCaptureStarted(resultExtras, timestamp);
3002f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
3012f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        }
3022f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case RESULT_RECEIVED: {
3032f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            Object[] resultArray = (Object[]) msg.obj;
3042f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CameraMetadataNative result = (CameraMetadataNative) resultArray[0];
3052f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CaptureResultExtras resultExtras = (CaptureResultExtras) resultArray[1];
3062f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            mCallbacks.onResultReceived(result, resultExtras);
3072f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
3082f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        }
309be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala                        case PREPARED: {
310be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala                            int streamId = msg.arg1;
311be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala                            mCallbacks.onPrepared(streamId);
312be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala                            break;
313be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala                        }
3142f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        default:
3152f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            throw new IllegalArgumentException(
3162f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                                "Unknown callback message " + msg.what);
3172f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    }
3182f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                } catch (RemoteException e) {
3192f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    throw new IllegalStateException(
3202f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        "Received remote exception during camera callback " + msg.what, e);
3212f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                }
3222f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            }
3232f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
3242f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    }
3252f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
326feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public static CameraDeviceUserShim connectBinderShim(ICameraDeviceCallbacks callbacks,
327feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                                         int cameraId) {
328feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
329feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "Opening shim Camera device");
330feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
331a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
332a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /*
333a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Put the camera open on a separate thread with its own looper; otherwise
334a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * if the main thread is used then the callbacks might never get delivered
335a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * (e.g. in CTS which run its own default looper only after tests)
336a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
337a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
338a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraLooper init = new CameraLooper(cameraId);
339a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
3402f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        CameraCallbackThread threadCallbacks = new CameraCallbackThread(callbacks);
3412f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
342a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        // TODO: Make this async instead of blocking
343a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        int initErrors = init.waitForOpen(OPEN_CAMERA_TIMEOUT_MS);
344a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        Camera legacyCamera = init.getCamera();
345a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin
346feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // Check errors old HAL initialization
3475d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        LegacyExceptionUtils.throwOnServiceError(initErrors);
348a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin
3496653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin        // Disable shutter sounds (this will work unconditionally) for api2 clients
3506653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin        legacyCamera.disableShutterSound();
3516653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin
352a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraInfo info = new CameraInfo();
353a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        Camera.getCameraInfo(cameraId, info);
354a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
355eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala        Camera.Parameters legacyParameters = null;
356eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala        try {
357eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala            legacyParameters = legacyCamera.getParameters();
358eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala        } catch (RuntimeException e) {
3595d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION,
3605d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                    "Unable to get initial parameters: " + e.getMessage());
361eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala        }
362eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala
363a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraCharacteristics characteristics =
364eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala                LegacyMetadataMapper.createCharacteristics(legacyParameters, info);
365df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin        LegacyCameraDevice device = new LegacyCameraDevice(
3662f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                cameraId, legacyCamera, characteristics, threadCallbacks);
3672f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        return new CameraDeviceUserShim(cameraId, device, characteristics, init, threadCallbacks);
368feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
369feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
370feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
371feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public void disconnect() {
372feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
373feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "disconnect called.");
374feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
375a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
376e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
377e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.w(TAG, "Cannot disconnect, device has already been closed.");
378e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
379e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
380a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        try {
381a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLegacyDevice.close();
382a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        } finally {
383a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mCameraInit.close();
3842f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mCameraCallbacks.close();
385a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
386feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
387feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
388feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
3895d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public SubmitInfo submitRequest(CaptureRequest request, boolean streaming) {
390feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
391feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "submitRequest called.");
392feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
393e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
3945d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot submit request, device has been closed.";
3955d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
3965d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
397e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
398e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
399feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
400feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
4015d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot submit request, configuration change in progress.";
4025d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
4035d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
404feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
405feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
4065d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return mLegacyDevice.submitRequest(request, streaming);
407feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
408feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
409feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
4105d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public SubmitInfo submitRequestList(CaptureRequest[] request, boolean streaming) {
411feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
412feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "submitRequestList called.");
413feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
414e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
4155d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot submit request list, device has been closed.";
4165d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
4175d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
418e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
419e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
420feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
421feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
4225d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot submit request, configuration change in progress.";
4235d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
4245d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
425feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
426feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
4275d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return mLegacyDevice.submitRequestList(request, streaming);
428feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
429feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
430feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
4315d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public long cancelRequest(int requestId) {
432feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
433feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "cancelRequest called.");
434feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
435e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
4365d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot cancel request, device has been closed.";
4375d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
4385d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
439e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
440e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
441feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
442feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
4435d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot cancel request, configuration change in progress.";
4445d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
4455d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
446feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
447feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
4485d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return mLegacyDevice.cancelRequest(requestId);
449feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
450feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
451feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
4525d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void beginConfigure() {
453feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
454feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "beginConfigure called.");
455feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
456e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
4575d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot begin configure, device has been closed.";
4585d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
4595d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
460e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
461e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
462feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
463feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
4645d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot begin configure, configuration change already in progress.";
4655d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
4665d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
467feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
468feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mConfiguring = true;
469feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
470feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
471feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
472feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
4735d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void endConfigure(boolean isConstrainedHighSpeed) {
474feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
475feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "endConfigure called.");
476feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
477e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
4785d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot end configure, device has been closed.";
4795d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
4805d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
481e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
482e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
483385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala        SparseArray<Surface> surfaces = null;
484feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
485feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (!mConfiguring) {
4865d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot end configure, no configuration change in progress.";
4875d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
4885d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
489feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
490385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala            if (mSurfaces != null) {
491385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala                surfaces = mSurfaces.clone();
492feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
493feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mConfiguring = false;
494feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
4955d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        mLegacyDevice.configureOutputs(surfaces);
496feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
497feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
498feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
4995d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void deleteStream(int streamId) {
500feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
501feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "deleteStream called.");
502feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
503e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
5045d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot delete stream, device has been closed.";
5055d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
5065d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
507e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
508e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
509feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
510feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (!mConfiguring) {
5115d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot delete stream, no configuration change in progress.";
5125d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
5135d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
514feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
515feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int index = mSurfaces.indexOfKey(streamId);
516feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (index < 0) {
5175d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot delete stream, stream id " + streamId + " doesn't exist.";
5185d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
5195d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
520feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
521feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mSurfaces.removeAt(index);
522feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
523feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
524feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
525feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
526bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh    public int createStream(OutputConfiguration outputConfiguration) {
527feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
528feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "createStream called.");
529feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
530e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
5315d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot create stream, device has been closed.";
5325d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
5335d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
534e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
535e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
536feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
537feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (!mConfiguring) {
5385d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot create stream, beginConfigure hasn't been called yet.";
5395d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
5405d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
541feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
542bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh            if (outputConfiguration.getRotation() != OutputConfiguration.ROTATION_0) {
5435d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot create stream, stream rotation is not supported.";
5445d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
5455d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
546bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh            }
547feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int id = ++mSurfaceIdCounter;
548bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh            mSurfaces.put(id, outputConfiguration.getSurface());
549feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return id;
550feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
551feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
552feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
553feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
5545398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    public int createInputStream(int width, int height, int format) {
5555d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        String err = "Creating input stream is not supported on legacy devices";
5565d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        Log.e(TAG, err);
5575d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
5585398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    }
5595398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen
5605398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    @Override
5615d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public Surface getInputSurface() {
5625d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        String err = "Getting input surface is not supported on legacy devices";
5635d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        Log.e(TAG, err);
5645d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
5655398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    }
5665398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen
5675398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    @Override
5685d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public CameraMetadataNative createDefaultRequest(int templateId) {
569feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
570feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "createDefaultRequest called.");
571feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
572e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
5735d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot create default request, device has been closed.";
5745d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
5755d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
576e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
577a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
578a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraMetadataNative template;
579a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        try {
580a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            template =
581a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                    LegacyMetadataMapper.createRequestTemplate(mCameraCharacteristics, templateId);
582a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        } catch (IllegalArgumentException e) {
5835d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "createDefaultRequest - invalid templateId specified";
5845d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
5855d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
586a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
587a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
5885d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return template;
589feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
590feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
591feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
5925d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public CameraMetadataNative getCameraInfo() {
593feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
594feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "getCameraInfo called.");
595feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
596feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // TODO: implement getCameraInfo.
597feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        Log.e(TAG, "getCameraInfo unimplemented.");
5985d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return null;
599feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
600feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
601feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
6025d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void waitUntilIdle() throws RemoteException {
603feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
604feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "waitUntilIdle called.");
605feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
606e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
6075d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot wait until idle, device has been closed.";
6085d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
6095d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
610e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
611e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
612feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
613feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
6145d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot wait until idle, configuration change in progress.";
6155d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
6165d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
617feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
618feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
619feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mLegacyDevice.waitUntilIdle();
620feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
621feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
622feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
6235d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public long flush() {
624feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
625feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "flush called.");
626feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
627e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
6285d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot flush, device has been closed.";
6295d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
6305d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
631e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
632e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
633feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
634feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
6355d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot flush, configuration change in progress.";
6365d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
6375d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
638feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
639feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
6405d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return mLegacyDevice.flush();
641feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
642feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
6435d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void prepare(int streamId) {
644ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        if (DEBUG) {
645ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala            Log.d(TAG, "prepare called.");
646ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        }
647ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        if (mLegacyDevice.isClosed()) {
6485d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot prepare stream, device has been closed.";
6495d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
6505d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
651ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        }
652ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala
653be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala        // LEGACY doesn't support actual prepare, just signal success right away
654be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala        mCameraCallbacks.onPrepared(streamId);
655ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala    }
656ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala
6575d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void prepare2(int maxCount, int streamId) {
6587ed1aaa369b6a459c776a9a6e96c33014b30f278Ruben Brunk        // We don't support this in LEGACY mode.
6595d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        prepare(streamId);
6607ed1aaa369b6a459c776a9a6e96c33014b30f278Ruben Brunk    }
6617ed1aaa369b6a459c776a9a6e96c33014b30f278Ruben Brunk
6625d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void tearDown(int streamId) {
66314c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala        if (DEBUG) {
66414c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala            Log.d(TAG, "tearDown called.");
66514c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala        }
66614c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala        if (mLegacyDevice.isClosed()) {
6675d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot tear down stream, device has been closed.";
6685d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
6695d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
67014c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala        }
67114c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala
67214c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala        // LEGACY doesn't support actual teardown, so just a no-op
67314c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala    }
67414c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala
675feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
676feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public IBinder asBinder() {
677feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // This is solely intended to be used for in-process binding.
678feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return null;
679feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
680feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
681