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;
290960fb462b1afc50e4fca5dab9e95a7c455378c4Shuzhen Wangimport android.hardware.camera2.impl.PhysicalCaptureResultInfo;
30bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yehimport android.hardware.camera2.params.OutputConfiguration;
315d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.hardware.camera2.utils.SubmitInfo;
32a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.os.ConditionVariable;
33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.IBinder;
34a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.os.Looper;
352f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvalaimport android.os.Handler;
362f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvalaimport android.os.HandlerThread;
372f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvalaimport android.os.Message;
38feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.RemoteException;
395d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.os.ServiceSpecificException;
40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log;
41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.SparseArray;
42feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.view.Surface;
43feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
44feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.ArrayList;
45feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.List;
46feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
478ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsicimport static android.system.OsConstants.EACCES;
488ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsicimport static android.system.OsConstants.ENODEV;
498ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic
50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Compatibility implementation of the Camera2 API binder interface.
52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p>
54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This is intended to be called from the same process as client
55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link android.hardware.camera2.CameraDevice}, and wraps a
56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link android.hardware.camera2.legacy.LegacyCameraDevice} that emulates Camera2 service using
57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * the Camera1 API.
58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p>
59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
60feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p>
61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Keep up to date with ICameraDeviceUser.aidl.
62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p>
63feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
646653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin@SuppressWarnings("deprecation")
65feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class CameraDeviceUserShim implements ICameraDeviceUser {
66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final String TAG = "CameraDeviceUserShim";
67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
68a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala    private static final boolean DEBUG = false;
69a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private static final int OPEN_CAMERA_TIMEOUT_MS = 5000; // 5 sec (same as api1 cts timeout)
70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final LegacyCameraDevice mLegacyDevice;
72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
73feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final Object mConfigureLock = new Object();
74feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private int mSurfaceIdCounter;
75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private boolean mConfiguring;
76feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final SparseArray<Surface> mSurfaces;
77a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private final CameraCharacteristics mCameraCharacteristics;
78a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private final CameraLooper mCameraInit;
792f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    private final CameraCallbackThread mCameraCallbacks;
802f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
82a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    protected CameraDeviceUserShim(int cameraId, LegacyCameraDevice legacyCamera,
832f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            CameraCharacteristics characteristics, CameraLooper cameraInit,
842f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            CameraCallbackThread cameraCallbacks) {
85feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mLegacyDevice = legacyCamera;
86feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mConfiguring = false;
87feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mSurfaces = new SparseArray<Surface>();
88a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        mCameraCharacteristics = characteristics;
89a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        mCameraInit = cameraInit;
902f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        mCameraCallbacks = cameraCallbacks;
91feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mSurfaceIdCounter = 0;
93feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
94feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
958ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic    private static int translateErrorsFromCamera1(int errorCode) {
968ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic        if (errorCode == -EACCES) {
975d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            return ICameraService.ERROR_PERMISSION_DENIED;
988ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic        }
998ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic
1008ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic        return errorCode;
1018ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic    }
1028ea56f68517ffa42bd5f43ab67f4ebfcfcb0cd23Lazar Trsic
103a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    /**
104a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * Create a separate looper/thread for the camera to run on; open the camera.
105a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     *
106a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * <p>Since the camera automatically latches on to the current thread's looper,
107a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * it's important that we have our own thread with our own looper to guarantee
108a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * that the camera callbacks get correctly posted to our own thread.</p>
109a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     */
110a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private static class CameraLooper implements Runnable, AutoCloseable {
111a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final int mCameraId;
112a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private Looper mLooper;
113a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private volatile int mInitErrors;
114a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final Camera mCamera = Camera.openUninitialized();
115a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final ConditionVariable mStartDone = new ConditionVariable();
116a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final Thread mThread;
117a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
118a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /**
119a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Spin up a new thread, immediately open the camera in the background.
120a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
121a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * <p>Use {@link #waitForOpen} to block until the camera is finished opening.</p>
122a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
123a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @param cameraId numeric camera Id
124a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
125a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @see #waitForOpen
126a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
127a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public CameraLooper(int cameraId) {
128a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mCameraId = cameraId;
129a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
130a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mThread = new Thread(this);
131a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mThread.start();
132a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
133a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
134a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public Camera getCamera() {
135a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            return mCamera;
136a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
137a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
138a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        @Override
139a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public void run() {
140a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // Set up a looper to be used by camera.
141a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            Looper.prepare();
142a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
143a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // Save the looper so that we can terminate this thread
144a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // after we are done with it.
145a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLooper = Looper.myLooper();
146db70a9785315a29c1d0d1233d883062b8d07c46fEino-Ville Talvala            mInitErrors = mCamera.cameraInitUnspecified(mCameraId);
147a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mStartDone.open();
148a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            Looper.loop();  // Blocks forever until #close is called.
149a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
150a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
151a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /**
152a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Quit the looper safely; then join until the thread shuts down.
153a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
154a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        @Override
155a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public void close() {
156a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            if (mLooper == null) {
157a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                return;
158a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            }
159a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
160a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLooper.quitSafely();
161a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            try {
162a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                mThread.join();
163a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            } catch (InterruptedException e) {
164a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                throw new AssertionError(e);
165a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            }
166a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
167a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLooper = null;
168a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
169a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
170a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /**
171a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Block until the camera opens; then return its initialization error code (if any).
172a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
173a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @param timeoutMs timeout in milliseconds
174a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
175a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @return int error code
176a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
1775d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala         * @throws ServiceSpecificException if the camera open times out with ({@code CAMERA_ERROR})
178a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
179a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public int waitForOpen(int timeoutMs) {
180a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // Block until the camera is open asynchronously
181a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            if (!mStartDone.block(timeoutMs)) {
182a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                Log.e(TAG, "waitForOpen - Camera failed to open after timeout of "
183a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                        + OPEN_CAMERA_TIMEOUT_MS + " ms");
184a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                try {
185a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                    mCamera.release();
186a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                } catch (RuntimeException e) {
187a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                    Log.e(TAG, "connectBinderShim - Failed to release camera after timeout ", e);
188a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                }
189a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
1905d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION);
191a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            }
192a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
193a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            return mInitErrors;
194a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
195a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    }
196a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
1972f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    /**
1982f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     * A thread to process callbacks to send back to the camera client.
1992f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     *
2002f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     * <p>This effectively emulates one-way binder semantics when in the same process as the
2012f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     * callee.</p>
2022f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     */
2032f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    private static class CameraCallbackThread implements ICameraDeviceCallbacks {
2042f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int CAMERA_ERROR = 0;
2052f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int CAMERA_IDLE = 1;
2062f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int CAPTURE_STARTED = 2;
2072f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int RESULT_RECEIVED = 3;
208be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala        private static final int PREPARED = 4;
2092da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen        private static final int REPEATING_REQUEST_ERROR = 5;
21088f1af241045d446358c692e183e5ecb152bad91Shuzhen Wang        private static final int REQUEST_QUEUE_EMPTY = 6;
2112f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2122f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private final HandlerThread mHandlerThread;
2132f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private Handler mHandler;
2142f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2152f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private final ICameraDeviceCallbacks mCallbacks;
2162f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2172f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public CameraCallbackThread(ICameraDeviceCallbacks callbacks) {
2182f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mCallbacks = callbacks;
2192f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2202f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mHandlerThread = new HandlerThread("LegacyCameraCallback");
2212f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mHandlerThread.start();
2222f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2232f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2242f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void close() {
2252f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mHandlerThread.quitSafely();
2262f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2272f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2282f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
229acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala        public void onDeviceError(final int errorCode, final CaptureResultExtras resultExtras) {
2302f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(CAMERA_ERROR,
2312f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                /*arg1*/ errorCode, /*arg2*/ 0,
2322f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                /*obj*/ resultExtras);
2332f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2342f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2352f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2362f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
237acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala        public void onDeviceIdle() {
2382f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(CAMERA_IDLE);
2392f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2402f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2412f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2422f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
2432f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
2442f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(CAPTURE_STARTED,
2452f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*arg1*/ (int) (timestamp & 0xFFFFFFFFL),
2462f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*arg2*/ (int) ( (timestamp >> 32) & 0xFFFFFFFFL),
2472f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*obj*/ resultExtras);
2482f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2492f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2502f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2512f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
2522f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void onResultReceived(final CameraMetadataNative result,
2530960fb462b1afc50e4fca5dab9e95a7c455378c4Shuzhen Wang                final CaptureResultExtras resultExtras,
2540960fb462b1afc50e4fca5dab9e95a7c455378c4Shuzhen Wang                PhysicalCaptureResultInfo physicalResults[]) {
2552f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Object[] resultArray = new Object[] { result, resultExtras };
2562f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(RESULT_RECEIVED,
2572f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*obj*/ resultArray);
2582f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2592f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2602f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2612f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
262ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        public void onPrepared(int streamId) {
263be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala            Message msg = getHandler().obtainMessage(PREPARED,
264be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala                    /*arg1*/ streamId, /*arg2*/ 0);
265be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala            getHandler().sendMessage(msg);
266ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        }
267ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala
2682da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen        @Override
2698cd12e9b7cc73b1bbe5e478acdf463c5381f33efYin-Chia Yeh        public void onRepeatingRequestError(long lastFrameNumber, int repeatingRequestId) {
2708cd12e9b7cc73b1bbe5e478acdf463c5381f33efYin-Chia Yeh            Object[] objArray = new Object[] { lastFrameNumber, repeatingRequestId };
2712da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen            Message msg = getHandler().obtainMessage(REPEATING_REQUEST_ERROR,
2728cd12e9b7cc73b1bbe5e478acdf463c5381f33efYin-Chia Yeh                    /*obj*/ objArray);
2732da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen            getHandler().sendMessage(msg);
2742da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen        }
2752da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen
276ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        @Override
27788f1af241045d446358c692e183e5ecb152bad91Shuzhen Wang        public void onRequestQueueEmpty() {
27888f1af241045d446358c692e183e5ecb152bad91Shuzhen Wang            Message msg = getHandler().obtainMessage(REQUEST_QUEUE_EMPTY,
27988f1af241045d446358c692e183e5ecb152bad91Shuzhen Wang                    /* arg1 */ 0, /* arg2 */ 0);
28088f1af241045d446358c692e183e5ecb152bad91Shuzhen Wang            getHandler().sendMessage(msg);
28188f1af241045d446358c692e183e5ecb152bad91Shuzhen Wang        }
28288f1af241045d446358c692e183e5ecb152bad91Shuzhen Wang
28388f1af241045d446358c692e183e5ecb152bad91Shuzhen Wang        @Override
2842f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public IBinder asBinder() {
2852f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            // This is solely intended to be used for in-process binding.
2862f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            return null;
2872f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2882f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2892f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private Handler getHandler() {
2902f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            if (mHandler == null) {
2912f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                mHandler = new CallbackHandler(mHandlerThread.getLooper());
2922f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            }
2932f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            return mHandler;
2942f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2952f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2962f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private class CallbackHandler extends Handler {
2972f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            public CallbackHandler(Looper l) {
2982f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                super(l);
2992f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            }
3002f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
3016653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin            @Override
3022f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            public void handleMessage(Message msg) {
3032f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                try {
3042f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    switch (msg.what) {
3052f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case CAMERA_ERROR: {
3062f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            int errorCode = msg.arg1;
3072f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CaptureResultExtras resultExtras = (CaptureResultExtras) msg.obj;
308acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala                            mCallbacks.onDeviceError(errorCode, resultExtras);
3092f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
3102f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        }
3112f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case CAMERA_IDLE:
312acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala                            mCallbacks.onDeviceIdle();
3132f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
3142f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case CAPTURE_STARTED: {
3152f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            long timestamp = msg.arg2 & 0xFFFFFFFFL;
3162f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            timestamp = (timestamp << 32) | (msg.arg1 & 0xFFFFFFFFL);
3172f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CaptureResultExtras resultExtras = (CaptureResultExtras) msg.obj;
3182f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            mCallbacks.onCaptureStarted(resultExtras, timestamp);
3192f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
3202f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        }
3212f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case RESULT_RECEIVED: {
3222f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            Object[] resultArray = (Object[]) msg.obj;
3232f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CameraMetadataNative result = (CameraMetadataNative) resultArray[0];
3242f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CaptureResultExtras resultExtras = (CaptureResultExtras) resultArray[1];
3250960fb462b1afc50e4fca5dab9e95a7c455378c4Shuzhen Wang                            mCallbacks.onResultReceived(result, resultExtras,
3260960fb462b1afc50e4fca5dab9e95a7c455378c4Shuzhen Wang                                    new PhysicalCaptureResultInfo[0]);
3272f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
3282f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        }
329be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala                        case PREPARED: {
330be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala                            int streamId = msg.arg1;
331be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala                            mCallbacks.onPrepared(streamId);
332be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala                            break;
333be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala                        }
3342da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen                        case REPEATING_REQUEST_ERROR: {
3358cd12e9b7cc73b1bbe5e478acdf463c5381f33efYin-Chia Yeh                            Object[] objArray = (Object[]) msg.obj;
3368cd12e9b7cc73b1bbe5e478acdf463c5381f33efYin-Chia Yeh                            long lastFrameNumber = (Long) objArray[0];
3378cd12e9b7cc73b1bbe5e478acdf463c5381f33efYin-Chia Yeh                            int repeatingRequestId = (Integer) objArray[1];
3388cd12e9b7cc73b1bbe5e478acdf463c5381f33efYin-Chia Yeh                            mCallbacks.onRepeatingRequestError(lastFrameNumber, repeatingRequestId);
3392da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen                            break;
3402da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen                        }
34188f1af241045d446358c692e183e5ecb152bad91Shuzhen Wang                        case REQUEST_QUEUE_EMPTY: {
34288f1af241045d446358c692e183e5ecb152bad91Shuzhen Wang                            mCallbacks.onRequestQueueEmpty();
34388f1af241045d446358c692e183e5ecb152bad91Shuzhen Wang                            break;
34488f1af241045d446358c692e183e5ecb152bad91Shuzhen Wang                        }
3452f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        default:
3462f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            throw new IllegalArgumentException(
3472f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                                "Unknown callback message " + msg.what);
3482f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    }
3492f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                } catch (RemoteException e) {
3502f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    throw new IllegalStateException(
3512f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        "Received remote exception during camera callback " + msg.what, e);
3522f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                }
3532f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            }
3542f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
3552f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    }
3562f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
357feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public static CameraDeviceUserShim connectBinderShim(ICameraDeviceCallbacks callbacks,
358feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                                         int cameraId) {
359feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
360feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "Opening shim Camera device");
361feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
362a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
363a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /*
364a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Put the camera open on a separate thread with its own looper; otherwise
365a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * if the main thread is used then the callbacks might never get delivered
366a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * (e.g. in CTS which run its own default looper only after tests)
367a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
368a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
369a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraLooper init = new CameraLooper(cameraId);
370a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
3712f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        CameraCallbackThread threadCallbacks = new CameraCallbackThread(callbacks);
3722f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
373a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        // TODO: Make this async instead of blocking
374a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        int initErrors = init.waitForOpen(OPEN_CAMERA_TIMEOUT_MS);
375a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        Camera legacyCamera = init.getCamera();
376a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin
377feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // Check errors old HAL initialization
3785d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        LegacyExceptionUtils.throwOnServiceError(initErrors);
379a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin
3806653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin        // Disable shutter sounds (this will work unconditionally) for api2 clients
3816653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin        legacyCamera.disableShutterSound();
3826653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin
383a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraInfo info = new CameraInfo();
384a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        Camera.getCameraInfo(cameraId, info);
385a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
386eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala        Camera.Parameters legacyParameters = null;
387eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala        try {
388eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala            legacyParameters = legacyCamera.getParameters();
389eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala        } catch (RuntimeException e) {
3905d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION,
3915d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                    "Unable to get initial parameters: " + e.getMessage());
392eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala        }
393eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala
394a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraCharacteristics characteristics =
395eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala                LegacyMetadataMapper.createCharacteristics(legacyParameters, info);
396df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin        LegacyCameraDevice device = new LegacyCameraDevice(
3972f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                cameraId, legacyCamera, characteristics, threadCallbacks);
3982f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        return new CameraDeviceUserShim(cameraId, device, characteristics, init, threadCallbacks);
399feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
400feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
401feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
402feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public void disconnect() {
403feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
404feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "disconnect called.");
405feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
406a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
407e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
408e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.w(TAG, "Cannot disconnect, device has already been closed.");
409e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
410e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
411a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        try {
412a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLegacyDevice.close();
413a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        } finally {
414a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mCameraInit.close();
4152f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mCameraCallbacks.close();
416a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
417feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
418feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
419feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
4205d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public SubmitInfo submitRequest(CaptureRequest request, boolean streaming) {
421feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
422feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "submitRequest called.");
423feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
424e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
4255d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot submit request, device has been closed.";
4265d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
4275d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
428e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
429e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
430feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
431feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
4325d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot submit request, configuration change in progress.";
4335d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
4345d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
435feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
436feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
4375d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return mLegacyDevice.submitRequest(request, streaming);
438feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
439feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
440feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
4415d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public SubmitInfo submitRequestList(CaptureRequest[] request, boolean streaming) {
442feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
443feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "submitRequestList called.");
444feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
445e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
4465d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot submit request list, device has been closed.";
4475d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
4485d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
449e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
450e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
451feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
452feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
4535d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot submit request, configuration change in progress.";
4545d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
4555d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
456feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
457feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
4585d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return mLegacyDevice.submitRequestList(request, streaming);
459feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
460feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
461feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
4625d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public long cancelRequest(int requestId) {
463feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
464feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "cancelRequest called.");
465feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
466e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
4675d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot cancel request, device has been closed.";
4685d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
4695d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
470e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
471e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
472feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
473feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
4745d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot cancel request, configuration change in progress.";
4755d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
4765d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
477feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
478feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
4795d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return mLegacyDevice.cancelRequest(requestId);
480feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
481feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
482feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
4835d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void beginConfigure() {
484feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
485feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "beginConfigure called.");
486feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
487e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
4885d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot begin configure, device has been closed.";
4895d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
4905d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
491e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
492e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
493feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
494feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
4955d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot begin configure, configuration change already in progress.";
4965d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
4975d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
498feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
499feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mConfiguring = true;
500feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
501feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
502feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
503feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
50475a5570f7db6990e12100afbd3985c09fcff8d32Emilian Peev    public void endConfigure(int operatingMode, CameraMetadataNative sessionParams) {
505feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
506feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "endConfigure called.");
507feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
508e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
5095d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot end configure, device has been closed.";
5105d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
511daf20731ca75b829302ad3dc81fc6df431959475Yin-Chia Yeh            synchronized(mConfigureLock) {
512daf20731ca75b829302ad3dc81fc6df431959475Yin-Chia Yeh                mConfiguring = false;
513daf20731ca75b829302ad3dc81fc6df431959475Yin-Chia Yeh            }
5145d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
515e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
516e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
5170e04e910a6b0d8a7464df9721535dfba21527c37Eino-Ville Talvala        if (operatingMode != ICameraDeviceUser.NORMAL_MODE) {
5180e04e910a6b0d8a7464df9721535dfba21527c37Eino-Ville Talvala            String err = "LEGACY devices do not support this operating mode";
5190e04e910a6b0d8a7464df9721535dfba21527c37Eino-Ville Talvala            Log.e(TAG, err);
520daf20731ca75b829302ad3dc81fc6df431959475Yin-Chia Yeh            synchronized(mConfigureLock) {
521daf20731ca75b829302ad3dc81fc6df431959475Yin-Chia Yeh                mConfiguring = false;
522daf20731ca75b829302ad3dc81fc6df431959475Yin-Chia Yeh            }
5230e04e910a6b0d8a7464df9721535dfba21527c37Eino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
5240e04e910a6b0d8a7464df9721535dfba21527c37Eino-Ville Talvala        }
5250e04e910a6b0d8a7464df9721535dfba21527c37Eino-Ville Talvala
526385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala        SparseArray<Surface> surfaces = null;
527feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
528feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (!mConfiguring) {
5295d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot end configure, no configuration change in progress.";
5305d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
5315d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
532feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
533385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala            if (mSurfaces != null) {
534385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala                surfaces = mSurfaces.clone();
535feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
536feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mConfiguring = false;
537feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
5385d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        mLegacyDevice.configureOutputs(surfaces);
539feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
540feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
541feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
5425d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void deleteStream(int streamId) {
543feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
544feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "deleteStream called.");
545feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
546e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
5475d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot delete stream, device has been closed.";
5485d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
5495d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
550e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
551e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
552feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
553feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (!mConfiguring) {
5545d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot delete stream, no configuration change in progress.";
5555d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
5565d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
557feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
558feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int index = mSurfaces.indexOfKey(streamId);
559feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (index < 0) {
5605d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot delete stream, stream id " + streamId + " doesn't exist.";
5615d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
5625d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
563feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
564feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mSurfaces.removeAt(index);
565feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
566feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
567feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
568feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
569bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh    public int createStream(OutputConfiguration outputConfiguration) {
570feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
571feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "createStream called.");
572feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
573e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
5745d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot create stream, device has been closed.";
5755d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
5765d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
577e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
578e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
579feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
580feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (!mConfiguring) {
5815d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot create stream, beginConfigure hasn't been called yet.";
5825d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
5835d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
584feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
585bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh            if (outputConfiguration.getRotation() != OutputConfiguration.ROTATION_0) {
5865d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot create stream, stream rotation is not supported.";
5875d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
5885d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
589bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh            }
590feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int id = ++mSurfaceIdCounter;
591bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh            mSurfaces.put(id, outputConfiguration.getSurface());
592feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return id;
593feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
594feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
595feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
596feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
5974bd7abe72a647ceb2175a4fe66aa640815c116f8Shuzhen Wang    public void finalizeOutputConfigurations(int steamId, OutputConfiguration config) {
5984bd7abe72a647ceb2175a4fe66aa640815c116f8Shuzhen Wang        String err = "Finalizing output configuration is not supported on legacy devices";
599c8b181e95d17c00f9fe4a8338c4cdd0eeac3a0dcZhijun He        Log.e(TAG, err);
600c8b181e95d17c00f9fe4a8338c4cdd0eeac3a0dcZhijun He        throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
601c8b181e95d17c00f9fe4a8338c4cdd0eeac3a0dcZhijun He    }
602c8b181e95d17c00f9fe4a8338c4cdd0eeac3a0dcZhijun He
603c8b181e95d17c00f9fe4a8338c4cdd0eeac3a0dcZhijun He    @Override
6045398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    public int createInputStream(int width, int height, int format) {
6055d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        String err = "Creating input stream is not supported on legacy devices";
6065d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        Log.e(TAG, err);
6075d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
6085398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    }
6095398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen
6105398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    @Override
6115d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public Surface getInputSurface() {
6125d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        String err = "Getting input surface is not supported on legacy devices";
6135d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        Log.e(TAG, err);
6145d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
6155398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    }
6165398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen
6175398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    @Override
6185d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public CameraMetadataNative createDefaultRequest(int templateId) {
619feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
620feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "createDefaultRequest called.");
621feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
622e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
6235d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot create default request, device has been closed.";
6245d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
6255d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
626e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
627a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
628a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraMetadataNative template;
629a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        try {
630a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            template =
631a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                    LegacyMetadataMapper.createRequestTemplate(mCameraCharacteristics, templateId);
632a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        } catch (IllegalArgumentException e) {
6335d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "createDefaultRequest - invalid templateId specified";
6345d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
6355d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
636a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
637a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
6385d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return template;
639feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
640feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
641feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
6425d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public CameraMetadataNative getCameraInfo() {
643feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
644feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "getCameraInfo called.");
645feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
646feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // TODO: implement getCameraInfo.
647feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        Log.e(TAG, "getCameraInfo unimplemented.");
6485d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return null;
649feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
650feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
651feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
652032331578c78886d2b0a6012dc2a083837c5e79fEmilian Peev    public void updateOutputConfiguration(int streamId, OutputConfiguration config) {
653032331578c78886d2b0a6012dc2a083837c5e79fEmilian Peev        // TODO: b/63912484 implement updateOutputConfiguration.
654032331578c78886d2b0a6012dc2a083837c5e79fEmilian Peev    }
655032331578c78886d2b0a6012dc2a083837c5e79fEmilian Peev
656032331578c78886d2b0a6012dc2a083837c5e79fEmilian Peev    @Override
6575d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void waitUntilIdle() throws RemoteException {
658feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
659feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "waitUntilIdle called.");
660feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
661e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
6625d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot wait until idle, device has been closed.";
6635d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
6645d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
665e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
666e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
667feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
668feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
6695d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot wait until idle, configuration change in progress.";
6705d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
6715d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
672feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
673feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
674feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mLegacyDevice.waitUntilIdle();
675feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
676feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
677feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
6785d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public long flush() {
679feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
680feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "flush called.");
681feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
682e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
6835d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot flush, device has been closed.";
6845d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
6855d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
686e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
687e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
688feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
689feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
6905d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                String err = "Cannot flush, configuration change in progress.";
6915d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                Log.e(TAG, err);
6925d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
693feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
694feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
6955d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return mLegacyDevice.flush();
696feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
697feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
6985d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void prepare(int streamId) {
699ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        if (DEBUG) {
700ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala            Log.d(TAG, "prepare called.");
701ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        }
702ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        if (mLegacyDevice.isClosed()) {
7035d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot prepare stream, device has been closed.";
7045d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
7055d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
706ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala        }
707ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala
708be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala        // LEGACY doesn't support actual prepare, just signal success right away
709be6d98526988f914365a2999b8d3ca11e24e5aebEino-Ville Talvala        mCameraCallbacks.onPrepared(streamId);
710ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala    }
711ad916f7fd3fbb202f2993fea04b0bdad3dcd6de6Eino-Ville Talvala
7125d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void prepare2(int maxCount, int streamId) {
7137ed1aaa369b6a459c776a9a6e96c33014b30f278Ruben Brunk        // We don't support this in LEGACY mode.
7145d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        prepare(streamId);
7157ed1aaa369b6a459c776a9a6e96c33014b30f278Ruben Brunk    }
7167ed1aaa369b6a459c776a9a6e96c33014b30f278Ruben Brunk
7175d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    public void tearDown(int streamId) {
71814c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala        if (DEBUG) {
71914c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala            Log.d(TAG, "tearDown called.");
72014c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala        }
72114c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala        if (mLegacyDevice.isClosed()) {
7225d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            String err = "Cannot tear down stream, device has been closed.";
7235d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            Log.e(TAG, err);
7245d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
72514c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala        }
72614c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala
72714c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala        // LEGACY doesn't support actual teardown, so just a no-op
72814c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala    }
72914c09fa3c5371b977c77e5813eabb81941040627Eino-Ville Talvala
730feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
731feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public IBinder asBinder() {
732feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // This is solely intended to be used for in-process binding.
733feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return null;
734feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
735feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
736