CameraDeviceUserShim.java revision 5398a676809faaf3c6c2875edc1907ad6b8e1c89
1feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/*
2feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Copyright (C) 2014 The Android Open Source Project
3feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
4feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
5feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * you may not use this file except in compliance with the License.
6feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * You may obtain a copy of the License at
7feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
8feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
9feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
10feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Unless required by applicable law or agreed to in writing, software
11feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
12feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * See the License for the specific language governing permissions and
14feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * limitations under the License.
15feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
16feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
17feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpackage android.hardware.camera2.legacy;
18feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
19feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.Camera;
20a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.hardware.Camera.CameraInfo;
21feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.CameraAccessException;
22a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.hardware.camera2.CameraCharacteristics;
23feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.CaptureRequest;
24feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.ICameraDeviceCallbacks;
25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.ICameraDeviceUser;
26feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.LongParcelable;
27feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CameraMetadataNative;
282f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvalaimport android.hardware.camera2.impl.CaptureResultExtras;
29bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yehimport android.hardware.camera2.params.OutputConfiguration;
30feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.CameraBinderDecorator;
31feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.CameraRuntimeException;
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;
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
46feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
47feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Compatibility implementation of the Camera2 API binder interface.
48feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p>
50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This is intended to be called from the same process as client
51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link android.hardware.camera2.CameraDevice}, and wraps a
52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link android.hardware.camera2.legacy.LegacyCameraDevice} that emulates Camera2 service using
53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * the Camera1 API.
54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p>
55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p>
57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Keep up to date with ICameraDeviceUser.aidl.
58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p>
59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
606653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin@SuppressWarnings("deprecation")
61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class CameraDeviceUserShim implements ICameraDeviceUser {
62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final String TAG = "CameraDeviceUserShim";
63feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
64feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final boolean DEBUG = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.DEBUG);
65a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private static final int OPEN_CAMERA_TIMEOUT_MS = 5000; // 5 sec (same as api1 cts timeout)
66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final LegacyCameraDevice mLegacyDevice;
68feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
69feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final Object mConfigureLock = new Object();
70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private int mSurfaceIdCounter;
71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private boolean mConfiguring;
72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final SparseArray<Surface> mSurfaces;
73a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private final CameraCharacteristics mCameraCharacteristics;
74a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private final CameraLooper mCameraInit;
752f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    private final CameraCallbackThread mCameraCallbacks;
762f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
78a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    protected CameraDeviceUserShim(int cameraId, LegacyCameraDevice legacyCamera,
792f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            CameraCharacteristics characteristics, CameraLooper cameraInit,
802f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            CameraCallbackThread cameraCallbacks) {
81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mLegacyDevice = legacyCamera;
82feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mConfiguring = false;
83feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mSurfaces = new SparseArray<Surface>();
84a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        mCameraCharacteristics = characteristics;
85a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        mCameraInit = cameraInit;
862f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        mCameraCallbacks = cameraCallbacks;
87feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
88feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mSurfaceIdCounter = 0;
89feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
90feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
913084c2f5191e560c10a0011f2f77e6d0e3396f92Ruben Brunk    private static int translateErrorsFromCamera1(int errorCode) {
923084c2f5191e560c10a0011f2f77e6d0e3396f92Ruben Brunk        switch (errorCode) {
933084c2f5191e560c10a0011f2f77e6d0e3396f92Ruben Brunk            case CameraBinderDecorator.EACCES:
943084c2f5191e560c10a0011f2f77e6d0e3396f92Ruben Brunk                return CameraBinderDecorator.PERMISSION_DENIED;
953084c2f5191e560c10a0011f2f77e6d0e3396f92Ruben Brunk            default:
963084c2f5191e560c10a0011f2f77e6d0e3396f92Ruben Brunk                return errorCode;
973084c2f5191e560c10a0011f2f77e6d0e3396f92Ruben Brunk        }
983084c2f5191e560c10a0011f2f77e6d0e3396f92Ruben Brunk    }
993084c2f5191e560c10a0011f2f77e6d0e3396f92Ruben Brunk
100a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    /**
101a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * Create a separate looper/thread for the camera to run on; open the camera.
102a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     *
103a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * <p>Since the camera automatically latches on to the current thread's looper,
104a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * it's important that we have our own thread with our own looper to guarantee
105a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     * that the camera callbacks get correctly posted to our own thread.</p>
106a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin     */
107a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    private static class CameraLooper implements Runnable, AutoCloseable {
108a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final int mCameraId;
109a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private Looper mLooper;
110a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private volatile int mInitErrors;
111a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final Camera mCamera = Camera.openUninitialized();
112a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final ConditionVariable mStartDone = new ConditionVariable();
113a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        private final Thread mThread;
114a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
115a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /**
116a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Spin up a new thread, immediately open the camera in the background.
117a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
118a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * <p>Use {@link #waitForOpen} to block until the camera is finished opening.</p>
119a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
120a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @param cameraId numeric camera Id
121a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
122a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @see #waitForOpen
123a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
124a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public CameraLooper(int cameraId) {
125a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mCameraId = cameraId;
126a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
127a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mThread = new Thread(this);
128a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mThread.start();
129a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
130a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
131a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public Camera getCamera() {
132a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            return mCamera;
133a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
134a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
135a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        @Override
136a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public void run() {
137a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // Set up a looper to be used by camera.
138a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            Looper.prepare();
139a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
140a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // Save the looper so that we can terminate this thread
141a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // after we are done with it.
142a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLooper = Looper.myLooper();
1433084c2f5191e560c10a0011f2f77e6d0e3396f92Ruben Brunk            mInitErrors = translateErrorsFromCamera1(mCamera.cameraInitUnspecified(mCameraId));
144a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mStartDone.open();
145a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            Looper.loop();  // Blocks forever until #close is called.
146a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
147a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
148a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /**
149a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Quit the looper safely; then join until the thread shuts down.
150a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
151a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        @Override
152a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public void close() {
153a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            if (mLooper == null) {
154a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                return;
155a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            }
156a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
157a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLooper.quitSafely();
158a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            try {
159a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                mThread.join();
160a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            } catch (InterruptedException e) {
161a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                throw new AssertionError(e);
162a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            }
163a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
164a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLooper = null;
165a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
166a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
167a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /**
168a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Block until the camera opens; then return its initialization error code (if any).
169a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
170a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @param timeoutMs timeout in milliseconds
171a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
172a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @return int error code
173a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         *
174a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * @throws CameraRuntimeException if the camera open times out with ({@code CAMERA_ERROR})
175a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
176a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        public int waitForOpen(int timeoutMs) {
177a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            // Block until the camera is open asynchronously
178a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            if (!mStartDone.block(timeoutMs)) {
179a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                Log.e(TAG, "waitForOpen - Camera failed to open after timeout of "
180a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                        + OPEN_CAMERA_TIMEOUT_MS + " ms");
181a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                try {
182a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                    mCamera.release();
183a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                } catch (RuntimeException e) {
184a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                    Log.e(TAG, "connectBinderShim - Failed to release camera after timeout ", e);
185a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                }
186a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
187a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR);
188a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            }
189a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
190a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            return mInitErrors;
191a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
192a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin    }
193a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
1942f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    /**
1952f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     * A thread to process callbacks to send back to the camera client.
1962f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     *
1972f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     * <p>This effectively emulates one-way binder semantics when in the same process as the
1982f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     * callee.</p>
1992f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala     */
2002f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    private static class CameraCallbackThread implements ICameraDeviceCallbacks {
2012f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int CAMERA_ERROR = 0;
2022f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int CAMERA_IDLE = 1;
2032f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int CAPTURE_STARTED = 2;
2042f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private static final int RESULT_RECEIVED = 3;
2052f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2062f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private final HandlerThread mHandlerThread;
2072f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private Handler mHandler;
2082f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2092f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private final ICameraDeviceCallbacks mCallbacks;
2102f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2112f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public CameraCallbackThread(ICameraDeviceCallbacks callbacks) {
2122f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mCallbacks = callbacks;
2132f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2142f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mHandlerThread = new HandlerThread("LegacyCameraCallback");
2152f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mHandlerThread.start();
2162f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2172f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2182f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void close() {
2192f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mHandlerThread.quitSafely();
2202f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2212f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2222f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
223acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala        public void onDeviceError(final int errorCode, final CaptureResultExtras resultExtras) {
2242f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(CAMERA_ERROR,
2252f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                /*arg1*/ errorCode, /*arg2*/ 0,
2262f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                /*obj*/ resultExtras);
2272f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2282f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2292f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2302f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
231acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala        public void onDeviceIdle() {
2322f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(CAMERA_IDLE);
2332f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2342f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2352f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2362f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
2372f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
2382f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(CAPTURE_STARTED,
2392f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*arg1*/ (int) (timestamp & 0xFFFFFFFFL),
2402f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*arg2*/ (int) ( (timestamp >> 32) & 0xFFFFFFFFL),
2412f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*obj*/ resultExtras);
2422f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2432f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2442f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2452f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
2462f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public void onResultReceived(final CameraMetadataNative result,
2472f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                final CaptureResultExtras resultExtras) {
2482f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Object[] resultArray = new Object[] { result, resultExtras };
2492f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            Message msg = getHandler().obtainMessage(RESULT_RECEIVED,
2502f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    /*obj*/ resultArray);
2512f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            getHandler().sendMessage(msg);
2522f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2532f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2542f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        @Override
2552f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        public IBinder asBinder() {
2562f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            // This is solely intended to be used for in-process binding.
2572f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            return null;
2582f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2592f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2602f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private Handler getHandler() {
2612f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            if (mHandler == null) {
2622f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                mHandler = new CallbackHandler(mHandlerThread.getLooper());
2632f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            }
2642f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            return mHandler;
2652f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
2662f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2672f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        private class CallbackHandler extends Handler {
2682f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            public CallbackHandler(Looper l) {
2692f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                super(l);
2702f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            }
2712f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
2726653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin            @Override
2732f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            public void handleMessage(Message msg) {
2742f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                try {
2752f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    switch (msg.what) {
2762f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case CAMERA_ERROR: {
2772f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            int errorCode = msg.arg1;
2782f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CaptureResultExtras resultExtras = (CaptureResultExtras) msg.obj;
279acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala                            mCallbacks.onDeviceError(errorCode, resultExtras);
2802f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
2812f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        }
2822f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case CAMERA_IDLE:
283acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala                            mCallbacks.onDeviceIdle();
2842f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
2852f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case CAPTURE_STARTED: {
2862f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            long timestamp = msg.arg2 & 0xFFFFFFFFL;
2872f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            timestamp = (timestamp << 32) | (msg.arg1 & 0xFFFFFFFFL);
2882f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CaptureResultExtras resultExtras = (CaptureResultExtras) msg.obj;
2892f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            mCallbacks.onCaptureStarted(resultExtras, timestamp);
2902f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
2912f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        }
2922f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        case RESULT_RECEIVED: {
2932f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            Object[] resultArray = (Object[]) msg.obj;
2942f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CameraMetadataNative result = (CameraMetadataNative) resultArray[0];
2952f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            CaptureResultExtras resultExtras = (CaptureResultExtras) resultArray[1];
2962f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            mCallbacks.onResultReceived(result, resultExtras);
2972f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            break;
2982f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        }
2992f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        default:
3002f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                            throw new IllegalArgumentException(
3012f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                                "Unknown callback message " + msg.what);
3022f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    }
3032f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                } catch (RemoteException e) {
3042f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                    throw new IllegalStateException(
3052f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                        "Received remote exception during camera callback " + msg.what, e);
3062f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                }
3072f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            }
3082f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        }
3092f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala    }
3102f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
311feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public static CameraDeviceUserShim connectBinderShim(ICameraDeviceCallbacks callbacks,
312feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                                         int cameraId) {
313feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
314feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "Opening shim Camera device");
315feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
316a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
317a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        /*
318a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * Put the camera open on a separate thread with its own looper; otherwise
319a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * if the main thread is used then the callbacks might never get delivered
320a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         * (e.g. in CTS which run its own default looper only after tests)
321a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin         */
322a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
323a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraLooper init = new CameraLooper(cameraId);
324a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
3252f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        CameraCallbackThread threadCallbacks = new CameraCallbackThread(callbacks);
3262f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala
327a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        // TODO: Make this async instead of blocking
328a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        int initErrors = init.waitForOpen(OPEN_CAMERA_TIMEOUT_MS);
329a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        Camera legacyCamera = init.getCamera();
330a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin
331feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // Check errors old HAL initialization
332a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin        CameraBinderDecorator.throwOnError(initErrors);
333a1d662716b3da384dfe3a758f079e0cbd089784aIgor Murashkin
3346653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin        // Disable shutter sounds (this will work unconditionally) for api2 clients
3356653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin        legacyCamera.disableShutterSound();
3366653362f6b5c5854bd88244bcecad72d11bf9404Igor Murashkin
337a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraInfo info = new CameraInfo();
338a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        Camera.getCameraInfo(cameraId, info);
339a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
340eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala        Camera.Parameters legacyParameters = null;
341eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala        try {
342eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala            legacyParameters = legacyCamera.getParameters();
343eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala        } catch (RuntimeException e) {
344eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala            throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR,
345eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala                    "Unable to get initial parameters", e);
346eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala        }
347eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala
348a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraCharacteristics characteristics =
349eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala                LegacyMetadataMapper.createCharacteristics(legacyParameters, info);
350df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin        LegacyCameraDevice device = new LegacyCameraDevice(
3512f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala                cameraId, legacyCamera, characteristics, threadCallbacks);
3522f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala        return new CameraDeviceUserShim(cameraId, device, characteristics, init, threadCallbacks);
353feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
354feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
355feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
356feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public void disconnect() {
357feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
358feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "disconnect called.");
359feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
360a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
361e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
362e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.w(TAG, "Cannot disconnect, device has already been closed.");
363e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
364e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
365a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        try {
366a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mLegacyDevice.close();
367a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        } finally {
368a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            mCameraInit.close();
3692f75e7d7ef2ef29ac4b1287dc44cf62cfbaf50b3Eino-Ville Talvala            mCameraCallbacks.close();
370a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
371feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
372feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
373feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
374feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int submitRequest(CaptureRequest request, boolean streaming,
375feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                             /*out*/LongParcelable lastFrameNumber) {
376feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
377feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "submitRequest called.");
378feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
379e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
380e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.e(TAG, "Cannot submit request, device has been closed.");
381e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            return CameraBinderDecorator.ENODEV;
382e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
383e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
384feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
385feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
386feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot submit request, configuration change in progress.");
387feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
388feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
389feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
390feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return mLegacyDevice.submitRequest(request, streaming, lastFrameNumber);
391feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
392feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
393feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
394feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int submitRequestList(List<CaptureRequest> request, boolean streaming,
395feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 /*out*/LongParcelable lastFrameNumber) {
396feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
397feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "submitRequestList called.");
398feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
399e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
400e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.e(TAG, "Cannot submit request list, device has been closed.");
401e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            return CameraBinderDecorator.ENODEV;
402e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
403e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
404feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
405feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
406feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot submit request, configuration change in progress.");
407feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
408feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
409feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
410feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return mLegacyDevice.submitRequestList(request, streaming, lastFrameNumber);
411feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
412feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
413feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
414feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int cancelRequest(int requestId, /*out*/LongParcelable lastFrameNumber) {
415feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
416feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "cancelRequest called.");
417feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
418e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
419e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.e(TAG, "Cannot cancel request, device has been closed.");
420e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            return CameraBinderDecorator.ENODEV;
421e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
422e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
423feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
424feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
425feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot cancel request, configuration change in progress.");
426feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
427feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
428feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
429feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        long lastFrame = mLegacyDevice.cancelRequest(requestId);
430feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        lastFrameNumber.setNumber(lastFrame);
431feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
432feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
433feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
434feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
435feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int beginConfigure() {
436feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
437feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "beginConfigure called.");
438feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
439e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
440e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.e(TAG, "Cannot begin configure, device has been closed.");
441e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            return CameraBinderDecorator.ENODEV;
442e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
443e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
444feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
445feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
446feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot begin configure, configuration change already in progress.");
447feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
448feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
449feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mConfiguring = true;
450feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
451feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
452feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
453feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
454feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
455feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int endConfigure() {
456feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
457feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "endConfigure called.");
458feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
459e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
460e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.e(TAG, "Cannot end configure, device has been closed.");
461e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            return CameraBinderDecorator.ENODEV;
462e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
463e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
464feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ArrayList<Surface> surfaces = null;
465feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
466feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (!mConfiguring) {
467feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot end configure, no configuration change in progress.");
468feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
469feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
470feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int numSurfaces = mSurfaces.size();
471feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (numSurfaces > 0) {
4725776aafc7e70c0b79c4bee2bc50f44121b37c962Ruben Brunk                surfaces = new ArrayList<>();
473feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                for (int i = 0; i < numSurfaces; ++i) {
474feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    surfaces.add(mSurfaces.valueAt(i));
475feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                }
476feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
477feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mConfiguring = false;
478feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
479feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return mLegacyDevice.configureOutputs(surfaces);
480feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
481feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
482feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
483feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int deleteStream(int streamId) {
484feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
485feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "deleteStream called.");
486feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
487e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
488e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.e(TAG, "Cannot delete stream, device has been closed.");
489e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            return CameraBinderDecorator.ENODEV;
490e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
491e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
492feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
493feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (!mConfiguring) {
494feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot delete stream, beginConfigure hasn't been called yet.");
495feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
496feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
497feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int index = mSurfaces.indexOfKey(streamId);
498feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (index < 0) {
499feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot delete stream, stream id " + streamId + " doesn't exist.");
500feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.BAD_VALUE;
501feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
502feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mSurfaces.removeAt(index);
503feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
504feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
505feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
506feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
507feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
508bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh    public int createStream(OutputConfiguration outputConfiguration) {
509feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
510feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "createStream called.");
511feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
512e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
513e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.e(TAG, "Cannot create stream, device has been closed.");
514e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            return CameraBinderDecorator.ENODEV;
515e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
516e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
517feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
518feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (!mConfiguring) {
519feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot create stream, beginConfigure hasn't been called yet.");
520feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
521feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
522bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh            if (outputConfiguration.getRotation() != OutputConfiguration.ROTATION_0) {
523bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh                Log.e(TAG, "Cannot create stream, stream rotation is not supported.");
524bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh                return CameraBinderDecorator.INVALID_OPERATION;
525bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh            }
526feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int id = ++mSurfaceIdCounter;
527bfbbee756663aeeb38706bb1bd4841dcd050f91bYin-Chia Yeh            mSurfaces.put(id, outputConfiguration.getSurface());
528feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return id;
529feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
530feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
531feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
532feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
5335398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    public int createInputStream(int width, int height, int format) {
5345398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen        Log.e(TAG, "creating input stream is not supported on legacy devices");
5355398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen        return CameraBinderDecorator.INVALID_OPERATION;
5365398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    }
5375398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen
5385398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    @Override
5395398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    public int getInputSurface(/*out*/ Surface surface) {
5405398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen        Log.e(TAG, "getting input surface is not supported on legacy devices");
5415398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen        return CameraBinderDecorator.INVALID_OPERATION;
5425398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    }
5435398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen
5445398a676809faaf3c6c2875edc1907ad6b8e1c89Chien-Yu Chen    @Override
545feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int createDefaultRequest(int templateId, /*out*/CameraMetadataNative request) {
546feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
547feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "createDefaultRequest called.");
548feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
549e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
550e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.e(TAG, "Cannot create default request, device has been closed.");
551e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            return CameraBinderDecorator.ENODEV;
552e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
553a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
554a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        CameraMetadataNative template;
555a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        try {
556a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            template =
557a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin                    LegacyMetadataMapper.createRequestTemplate(mCameraCharacteristics, templateId);
558a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        } catch (IllegalArgumentException e) {
559a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            Log.e(TAG, "createDefaultRequest - invalid templateId specified");
560a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin            return CameraBinderDecorator.BAD_VALUE;
561a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        }
562a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin
563a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin        request.swap(template);
564feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
565feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
566feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
567feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
568feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int getCameraInfo(/*out*/CameraMetadataNative info) {
569feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
570feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "getCameraInfo called.");
571feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
572feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // TODO: implement getCameraInfo.
573feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        Log.e(TAG, "getCameraInfo unimplemented.");
574feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
575feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
576feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
577feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
578feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int waitUntilIdle() throws RemoteException {
579feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
580feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "waitUntilIdle called.");
581feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
582e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
583e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.e(TAG, "Cannot wait until idle, device has been closed.");
584e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            return CameraBinderDecorator.ENODEV;
585e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
586e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
587feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
588feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
589feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot wait until idle, configuration change in progress.");
590feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
591feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
592feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
593feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mLegacyDevice.waitUntilIdle();
594feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
595feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
596feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
597feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
598feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public int flush(/*out*/LongParcelable lastFrameNumber) {
599feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (DEBUG) {
600feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.d(TAG, "flush called.");
601feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
602e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mLegacyDevice.isClosed()) {
603e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.e(TAG, "Cannot flush, device has been closed.");
604e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            return CameraBinderDecorator.ENODEV;
605e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
606e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
607feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        synchronized(mConfigureLock) {
608feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mConfiguring) {
609feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                Log.e(TAG, "Cannot flush, configuration change in progress.");
610feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return CameraBinderDecorator.INVALID_OPERATION;
611feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
612feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
613e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        long lastFrame = mLegacyDevice.flush();
614e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (lastFrameNumber != null) {
615e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            lastFrameNumber.setNumber(lastFrame);
616e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
617feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return CameraBinderDecorator.NO_ERROR;
618feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
619feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
620feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    @Override
621feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public IBinder asBinder() {
622feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        // This is solely intended to be used for in-process binding.
623feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return null;
624feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
625feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
626