blob: eccab7500abfea01faf1c7bc7926a25438f91b1f [file] [log] [blame]
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.hardware.camera2.legacy;
18
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -080019import android.hardware.ICameraService;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070020import android.hardware.Camera;
Igor Murashkina296fec2014-06-23 14:44:09 -070021import android.hardware.Camera.CameraInfo;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070022import android.hardware.camera2.CameraAccessException;
Igor Murashkina296fec2014-06-23 14:44:09 -070023import android.hardware.camera2.CameraCharacteristics;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070024import android.hardware.camera2.CaptureRequest;
25import android.hardware.camera2.ICameraDeviceCallbacks;
26import android.hardware.camera2.ICameraDeviceUser;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070027import android.hardware.camera2.impl.CameraMetadataNative;
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -070028import android.hardware.camera2.impl.CaptureResultExtras;
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -070029import android.hardware.camera2.params.OutputConfiguration;
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -080030import android.hardware.camera2.utils.SubmitInfo;
Igor Murashkina296fec2014-06-23 14:44:09 -070031import android.os.ConditionVariable;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070032import android.os.IBinder;
Igor Murashkina296fec2014-06-23 14:44:09 -070033import android.os.Looper;
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -070034import android.os.Handler;
35import android.os.HandlerThread;
36import android.os.Message;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070037import android.os.RemoteException;
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -080038import android.os.ServiceSpecificException;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070039import android.util.Log;
40import android.util.SparseArray;
41import android.view.Surface;
42
43import java.util.ArrayList;
44import java.util.List;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070045
Lazar Trsic8ea56f62015-07-07 17:31:20 +020046import static android.system.OsConstants.EACCES;
47import static android.system.OsConstants.ENODEV;
48
Ruben Brunkfeb50af2014-05-09 19:58:49 -070049/**
50 * Compatibility implementation of the Camera2 API binder interface.
51 *
52 * <p>
53 * This is intended to be called from the same process as client
54 * {@link android.hardware.camera2.CameraDevice}, and wraps a
55 * {@link android.hardware.camera2.legacy.LegacyCameraDevice} that emulates Camera2 service using
56 * the Camera1 API.
57 * </p>
58 *
59 * <p>
60 * Keep up to date with ICameraDeviceUser.aidl.
61 * </p>
62 */
Igor Murashkin66533622014-08-19 14:51:47 -070063@SuppressWarnings("deprecation")
Ruben Brunkfeb50af2014-05-09 19:58:49 -070064public class CameraDeviceUserShim implements ICameraDeviceUser {
65 private static final String TAG = "CameraDeviceUserShim";
66
Eino-Ville Talvalaa78791f2015-06-01 12:39:54 -070067 private static final boolean DEBUG = false;
Igor Murashkina296fec2014-06-23 14:44:09 -070068 private static final int OPEN_CAMERA_TIMEOUT_MS = 5000; // 5 sec (same as api1 cts timeout)
Ruben Brunkfeb50af2014-05-09 19:58:49 -070069
70 private final LegacyCameraDevice mLegacyDevice;
71
72 private final Object mConfigureLock = new Object();
73 private int mSurfaceIdCounter;
74 private boolean mConfiguring;
75 private final SparseArray<Surface> mSurfaces;
Igor Murashkina296fec2014-06-23 14:44:09 -070076 private final CameraCharacteristics mCameraCharacteristics;
77 private final CameraLooper mCameraInit;
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -070078 private final CameraCallbackThread mCameraCallbacks;
79
Ruben Brunkfeb50af2014-05-09 19:58:49 -070080
Igor Murashkina296fec2014-06-23 14:44:09 -070081 protected CameraDeviceUserShim(int cameraId, LegacyCameraDevice legacyCamera,
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -070082 CameraCharacteristics characteristics, CameraLooper cameraInit,
83 CameraCallbackThread cameraCallbacks) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -070084 mLegacyDevice = legacyCamera;
85 mConfiguring = false;
86 mSurfaces = new SparseArray<Surface>();
Igor Murashkina296fec2014-06-23 14:44:09 -070087 mCameraCharacteristics = characteristics;
88 mCameraInit = cameraInit;
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -070089 mCameraCallbacks = cameraCallbacks;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070090
91 mSurfaceIdCounter = 0;
92 }
93
Lazar Trsic8ea56f62015-07-07 17:31:20 +020094 private static int translateErrorsFromCamera1(int errorCode) {
95 if (errorCode == -EACCES) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -080096 return ICameraService.ERROR_PERMISSION_DENIED;
Lazar Trsic8ea56f62015-07-07 17:31:20 +020097 }
98
99 return errorCode;
100 }
101
Igor Murashkina296fec2014-06-23 14:44:09 -0700102 /**
103 * Create a separate looper/thread for the camera to run on; open the camera.
104 *
105 * <p>Since the camera automatically latches on to the current thread's looper,
106 * it's important that we have our own thread with our own looper to guarantee
107 * that the camera callbacks get correctly posted to our own thread.</p>
108 */
109 private static class CameraLooper implements Runnable, AutoCloseable {
110 private final int mCameraId;
111 private Looper mLooper;
112 private volatile int mInitErrors;
113 private final Camera mCamera = Camera.openUninitialized();
114 private final ConditionVariable mStartDone = new ConditionVariable();
115 private final Thread mThread;
116
117 /**
118 * Spin up a new thread, immediately open the camera in the background.
119 *
120 * <p>Use {@link #waitForOpen} to block until the camera is finished opening.</p>
121 *
122 * @param cameraId numeric camera Id
123 *
124 * @see #waitForOpen
125 */
126 public CameraLooper(int cameraId) {
127 mCameraId = cameraId;
128
129 mThread = new Thread(this);
130 mThread.start();
131 }
132
133 public Camera getCamera() {
134 return mCamera;
135 }
136
137 @Override
138 public void run() {
139 // Set up a looper to be used by camera.
140 Looper.prepare();
141
142 // Save the looper so that we can terminate this thread
143 // after we are done with it.
144 mLooper = Looper.myLooper();
Eino-Ville Talvaladb70a972015-06-03 16:27:11 -0700145 mInitErrors = mCamera.cameraInitUnspecified(mCameraId);
Igor Murashkina296fec2014-06-23 14:44:09 -0700146 mStartDone.open();
147 Looper.loop(); // Blocks forever until #close is called.
148 }
149
150 /**
151 * Quit the looper safely; then join until the thread shuts down.
152 */
153 @Override
154 public void close() {
155 if (mLooper == null) {
156 return;
157 }
158
159 mLooper.quitSafely();
160 try {
161 mThread.join();
162 } catch (InterruptedException e) {
163 throw new AssertionError(e);
164 }
165
166 mLooper = null;
167 }
168
169 /**
170 * Block until the camera opens; then return its initialization error code (if any).
171 *
172 * @param timeoutMs timeout in milliseconds
173 *
174 * @return int error code
175 *
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800176 * @throws ServiceSpecificException if the camera open times out with ({@code CAMERA_ERROR})
Igor Murashkina296fec2014-06-23 14:44:09 -0700177 */
178 public int waitForOpen(int timeoutMs) {
179 // Block until the camera is open asynchronously
180 if (!mStartDone.block(timeoutMs)) {
181 Log.e(TAG, "waitForOpen - Camera failed to open after timeout of "
182 + OPEN_CAMERA_TIMEOUT_MS + " ms");
183 try {
184 mCamera.release();
185 } catch (RuntimeException e) {
186 Log.e(TAG, "connectBinderShim - Failed to release camera after timeout ", e);
187 }
188
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800189 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION);
Igor Murashkina296fec2014-06-23 14:44:09 -0700190 }
191
192 return mInitErrors;
193 }
194 }
195
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -0700196 /**
197 * A thread to process callbacks to send back to the camera client.
198 *
199 * <p>This effectively emulates one-way binder semantics when in the same process as the
200 * callee.</p>
201 */
202 private static class CameraCallbackThread implements ICameraDeviceCallbacks {
203 private static final int CAMERA_ERROR = 0;
204 private static final int CAMERA_IDLE = 1;
205 private static final int CAPTURE_STARTED = 2;
206 private static final int RESULT_RECEIVED = 3;
Eino-Ville Talvalabe6d9852015-04-29 11:37:00 -0700207 private static final int PREPARED = 4;
Chien-Yu Chen2da496f2016-04-14 13:33:00 -0700208 private static final int REPEATING_REQUEST_ERROR = 5;
Shuzhen Wang88f1af22016-09-30 10:29:28 -0700209 private static final int REQUEST_QUEUE_EMPTY = 6;
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -0700210
211 private final HandlerThread mHandlerThread;
212 private Handler mHandler;
213
214 private final ICameraDeviceCallbacks mCallbacks;
215
216 public CameraCallbackThread(ICameraDeviceCallbacks callbacks) {
217 mCallbacks = callbacks;
218
219 mHandlerThread = new HandlerThread("LegacyCameraCallback");
220 mHandlerThread.start();
221 }
222
223 public void close() {
224 mHandlerThread.quitSafely();
225 }
226
227 @Override
Eino-Ville Talvalaacc00952014-08-06 14:31:08 -0700228 public void onDeviceError(final int errorCode, final CaptureResultExtras resultExtras) {
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -0700229 Message msg = getHandler().obtainMessage(CAMERA_ERROR,
230 /*arg1*/ errorCode, /*arg2*/ 0,
231 /*obj*/ resultExtras);
232 getHandler().sendMessage(msg);
233 }
234
235 @Override
Eino-Ville Talvalaacc00952014-08-06 14:31:08 -0700236 public void onDeviceIdle() {
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -0700237 Message msg = getHandler().obtainMessage(CAMERA_IDLE);
238 getHandler().sendMessage(msg);
239 }
240
241 @Override
242 public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
243 Message msg = getHandler().obtainMessage(CAPTURE_STARTED,
244 /*arg1*/ (int) (timestamp & 0xFFFFFFFFL),
245 /*arg2*/ (int) ( (timestamp >> 32) & 0xFFFFFFFFL),
246 /*obj*/ resultExtras);
247 getHandler().sendMessage(msg);
248 }
249
250 @Override
251 public void onResultReceived(final CameraMetadataNative result,
252 final CaptureResultExtras resultExtras) {
253 Object[] resultArray = new Object[] { result, resultExtras };
254 Message msg = getHandler().obtainMessage(RESULT_RECEIVED,
255 /*obj*/ resultArray);
256 getHandler().sendMessage(msg);
257 }
258
259 @Override
Eino-Ville Talvalaad916f72015-04-11 12:09:11 -0700260 public void onPrepared(int streamId) {
Eino-Ville Talvalabe6d9852015-04-29 11:37:00 -0700261 Message msg = getHandler().obtainMessage(PREPARED,
262 /*arg1*/ streamId, /*arg2*/ 0);
263 getHandler().sendMessage(msg);
Eino-Ville Talvalaad916f72015-04-11 12:09:11 -0700264 }
265
Chien-Yu Chen2da496f2016-04-14 13:33:00 -0700266 @Override
Yin-Chia Yeh8cd12e92017-09-05 18:14:21 -0700267 public void onRepeatingRequestError(long lastFrameNumber, int repeatingRequestId) {
268 Object[] objArray = new Object[] { lastFrameNumber, repeatingRequestId };
Chien-Yu Chen2da496f2016-04-14 13:33:00 -0700269 Message msg = getHandler().obtainMessage(REPEATING_REQUEST_ERROR,
Yin-Chia Yeh8cd12e92017-09-05 18:14:21 -0700270 /*obj*/ objArray);
Chien-Yu Chen2da496f2016-04-14 13:33:00 -0700271 getHandler().sendMessage(msg);
272 }
273
Eino-Ville Talvalaad916f72015-04-11 12:09:11 -0700274 @Override
Shuzhen Wang88f1af22016-09-30 10:29:28 -0700275 public void onRequestQueueEmpty() {
276 Message msg = getHandler().obtainMessage(REQUEST_QUEUE_EMPTY,
277 /* arg1 */ 0, /* arg2 */ 0);
278 getHandler().sendMessage(msg);
279 }
280
281 @Override
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -0700282 public IBinder asBinder() {
283 // This is solely intended to be used for in-process binding.
284 return null;
285 }
286
287 private Handler getHandler() {
288 if (mHandler == null) {
289 mHandler = new CallbackHandler(mHandlerThread.getLooper());
290 }
291 return mHandler;
292 }
293
294 private class CallbackHandler extends Handler {
295 public CallbackHandler(Looper l) {
296 super(l);
297 }
298
Igor Murashkin66533622014-08-19 14:51:47 -0700299 @Override
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -0700300 public void handleMessage(Message msg) {
301 try {
302 switch (msg.what) {
303 case CAMERA_ERROR: {
304 int errorCode = msg.arg1;
305 CaptureResultExtras resultExtras = (CaptureResultExtras) msg.obj;
Eino-Ville Talvalaacc00952014-08-06 14:31:08 -0700306 mCallbacks.onDeviceError(errorCode, resultExtras);
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -0700307 break;
308 }
309 case CAMERA_IDLE:
Eino-Ville Talvalaacc00952014-08-06 14:31:08 -0700310 mCallbacks.onDeviceIdle();
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -0700311 break;
312 case CAPTURE_STARTED: {
313 long timestamp = msg.arg2 & 0xFFFFFFFFL;
314 timestamp = (timestamp << 32) | (msg.arg1 & 0xFFFFFFFFL);
315 CaptureResultExtras resultExtras = (CaptureResultExtras) msg.obj;
316 mCallbacks.onCaptureStarted(resultExtras, timestamp);
317 break;
318 }
319 case RESULT_RECEIVED: {
320 Object[] resultArray = (Object[]) msg.obj;
321 CameraMetadataNative result = (CameraMetadataNative) resultArray[0];
322 CaptureResultExtras resultExtras = (CaptureResultExtras) resultArray[1];
323 mCallbacks.onResultReceived(result, resultExtras);
324 break;
325 }
Eino-Ville Talvalabe6d9852015-04-29 11:37:00 -0700326 case PREPARED: {
327 int streamId = msg.arg1;
328 mCallbacks.onPrepared(streamId);
329 break;
330 }
Chien-Yu Chen2da496f2016-04-14 13:33:00 -0700331 case REPEATING_REQUEST_ERROR: {
Yin-Chia Yeh8cd12e92017-09-05 18:14:21 -0700332 Object[] objArray = (Object[]) msg.obj;
333 long lastFrameNumber = (Long) objArray[0];
334 int repeatingRequestId = (Integer) objArray[1];
335 mCallbacks.onRepeatingRequestError(lastFrameNumber, repeatingRequestId);
Chien-Yu Chen2da496f2016-04-14 13:33:00 -0700336 break;
337 }
Shuzhen Wang88f1af22016-09-30 10:29:28 -0700338 case REQUEST_QUEUE_EMPTY: {
339 mCallbacks.onRequestQueueEmpty();
340 break;
341 }
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -0700342 default:
343 throw new IllegalArgumentException(
344 "Unknown callback message " + msg.what);
345 }
346 } catch (RemoteException e) {
347 throw new IllegalStateException(
348 "Received remote exception during camera callback " + msg.what, e);
349 }
350 }
351 }
352 }
353
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700354 public static CameraDeviceUserShim connectBinderShim(ICameraDeviceCallbacks callbacks,
355 int cameraId) {
356 if (DEBUG) {
357 Log.d(TAG, "Opening shim Camera device");
358 }
Igor Murashkina296fec2014-06-23 14:44:09 -0700359
360 /*
361 * Put the camera open on a separate thread with its own looper; otherwise
362 * if the main thread is used then the callbacks might never get delivered
363 * (e.g. in CTS which run its own default looper only after tests)
364 */
365
366 CameraLooper init = new CameraLooper(cameraId);
367
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -0700368 CameraCallbackThread threadCallbacks = new CameraCallbackThread(callbacks);
369
Igor Murashkina296fec2014-06-23 14:44:09 -0700370 // TODO: Make this async instead of blocking
371 int initErrors = init.waitForOpen(OPEN_CAMERA_TIMEOUT_MS);
372 Camera legacyCamera = init.getCamera();
Igor Murashkina1d66272014-06-20 11:22:11 -0700373
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700374 // Check errors old HAL initialization
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800375 LegacyExceptionUtils.throwOnServiceError(initErrors);
Igor Murashkina1d66272014-06-20 11:22:11 -0700376
Igor Murashkin66533622014-08-19 14:51:47 -0700377 // Disable shutter sounds (this will work unconditionally) for api2 clients
378 legacyCamera.disableShutterSound();
379
Igor Murashkina296fec2014-06-23 14:44:09 -0700380 CameraInfo info = new CameraInfo();
381 Camera.getCameraInfo(cameraId, info);
382
Eino-Ville Talvalaeecc9042014-09-23 16:37:31 -0700383 Camera.Parameters legacyParameters = null;
384 try {
385 legacyParameters = legacyCamera.getParameters();
386 } catch (RuntimeException e) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800387 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION,
388 "Unable to get initial parameters: " + e.getMessage());
Eino-Ville Talvalaeecc9042014-09-23 16:37:31 -0700389 }
390
Igor Murashkina296fec2014-06-23 14:44:09 -0700391 CameraCharacteristics characteristics =
Eino-Ville Talvalaeecc9042014-09-23 16:37:31 -0700392 LegacyMetadataMapper.createCharacteristics(legacyParameters, info);
Igor Murashkindf6242e2014-07-01 18:06:13 -0700393 LegacyCameraDevice device = new LegacyCameraDevice(
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -0700394 cameraId, legacyCamera, characteristics, threadCallbacks);
395 return new CameraDeviceUserShim(cameraId, device, characteristics, init, threadCallbacks);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700396 }
397
398 @Override
399 public void disconnect() {
400 if (DEBUG) {
401 Log.d(TAG, "disconnect called.");
402 }
Igor Murashkina296fec2014-06-23 14:44:09 -0700403
Ruben Brunke663cb772014-09-16 13:18:31 -0700404 if (mLegacyDevice.isClosed()) {
405 Log.w(TAG, "Cannot disconnect, device has already been closed.");
406 }
407
Igor Murashkina296fec2014-06-23 14:44:09 -0700408 try {
409 mLegacyDevice.close();
410 } finally {
411 mCameraInit.close();
Eino-Ville Talvala2f75e7d2014-07-15 10:31:54 -0700412 mCameraCallbacks.close();
Igor Murashkina296fec2014-06-23 14:44:09 -0700413 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700414 }
415
416 @Override
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800417 public SubmitInfo submitRequest(CaptureRequest request, boolean streaming) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700418 if (DEBUG) {
419 Log.d(TAG, "submitRequest called.");
420 }
Ruben Brunke663cb772014-09-16 13:18:31 -0700421 if (mLegacyDevice.isClosed()) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800422 String err = "Cannot submit request, device has been closed.";
423 Log.e(TAG, err);
424 throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
Ruben Brunke663cb772014-09-16 13:18:31 -0700425 }
426
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700427 synchronized(mConfigureLock) {
428 if (mConfiguring) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800429 String err = "Cannot submit request, configuration change in progress.";
430 Log.e(TAG, err);
431 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700432 }
433 }
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800434 return mLegacyDevice.submitRequest(request, streaming);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700435 }
436
437 @Override
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800438 public SubmitInfo submitRequestList(CaptureRequest[] request, boolean streaming) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700439 if (DEBUG) {
440 Log.d(TAG, "submitRequestList called.");
441 }
Ruben Brunke663cb772014-09-16 13:18:31 -0700442 if (mLegacyDevice.isClosed()) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800443 String err = "Cannot submit request list, device has been closed.";
444 Log.e(TAG, err);
445 throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
Ruben Brunke663cb772014-09-16 13:18:31 -0700446 }
447
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700448 synchronized(mConfigureLock) {
449 if (mConfiguring) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800450 String err = "Cannot submit request, configuration change in progress.";
451 Log.e(TAG, err);
452 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700453 }
454 }
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800455 return mLegacyDevice.submitRequestList(request, streaming);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700456 }
457
458 @Override
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800459 public long cancelRequest(int requestId) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700460 if (DEBUG) {
461 Log.d(TAG, "cancelRequest called.");
462 }
Ruben Brunke663cb772014-09-16 13:18:31 -0700463 if (mLegacyDevice.isClosed()) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800464 String err = "Cannot cancel request, device has been closed.";
465 Log.e(TAG, err);
466 throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
Ruben Brunke663cb772014-09-16 13:18:31 -0700467 }
468
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700469 synchronized(mConfigureLock) {
470 if (mConfiguring) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800471 String err = "Cannot cancel request, configuration change in progress.";
472 Log.e(TAG, err);
473 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700474 }
475 }
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800476 return mLegacyDevice.cancelRequest(requestId);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700477 }
478
479 @Override
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800480 public void beginConfigure() {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700481 if (DEBUG) {
482 Log.d(TAG, "beginConfigure called.");
483 }
Ruben Brunke663cb772014-09-16 13:18:31 -0700484 if (mLegacyDevice.isClosed()) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800485 String err = "Cannot begin configure, device has been closed.";
486 Log.e(TAG, err);
487 throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
Ruben Brunke663cb772014-09-16 13:18:31 -0700488 }
489
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700490 synchronized(mConfigureLock) {
491 if (mConfiguring) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800492 String err = "Cannot begin configure, configuration change already in progress.";
493 Log.e(TAG, err);
494 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700495 }
496 mConfiguring = true;
497 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700498 }
499
500 @Override
Emilian Peev75a55702017-11-07 16:09:59 +0000501 public void endConfigure(int operatingMode, CameraMetadataNative sessionParams) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700502 if (DEBUG) {
503 Log.d(TAG, "endConfigure called.");
504 }
Ruben Brunke663cb772014-09-16 13:18:31 -0700505 if (mLegacyDevice.isClosed()) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800506 String err = "Cannot end configure, device has been closed.";
507 Log.e(TAG, err);
Yin-Chia Yehdaf20732017-08-10 15:41:50 -0700508 synchronized(mConfigureLock) {
509 mConfiguring = false;
510 }
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800511 throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
Ruben Brunke663cb772014-09-16 13:18:31 -0700512 }
513
Eino-Ville Talvala0e04e912017-02-28 17:49:41 -0800514 if (operatingMode != ICameraDeviceUser.NORMAL_MODE) {
515 String err = "LEGACY devices do not support this operating mode";
516 Log.e(TAG, err);
Yin-Chia Yehdaf20732017-08-10 15:41:50 -0700517 synchronized(mConfigureLock) {
518 mConfiguring = false;
519 }
Eino-Ville Talvala0e04e912017-02-28 17:49:41 -0800520 throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
521 }
522
Eino-Ville Talvala385f9e22016-03-31 16:47:14 -0700523 SparseArray<Surface> surfaces = null;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700524 synchronized(mConfigureLock) {
525 if (!mConfiguring) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800526 String err = "Cannot end configure, no configuration change in progress.";
527 Log.e(TAG, err);
528 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700529 }
Eino-Ville Talvala385f9e22016-03-31 16:47:14 -0700530 if (mSurfaces != null) {
531 surfaces = mSurfaces.clone();
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700532 }
533 mConfiguring = false;
534 }
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800535 mLegacyDevice.configureOutputs(surfaces);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700536 }
537
538 @Override
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800539 public void deleteStream(int streamId) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700540 if (DEBUG) {
541 Log.d(TAG, "deleteStream called.");
542 }
Ruben Brunke663cb772014-09-16 13:18:31 -0700543 if (mLegacyDevice.isClosed()) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800544 String err = "Cannot delete stream, device has been closed.";
545 Log.e(TAG, err);
546 throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
Ruben Brunke663cb772014-09-16 13:18:31 -0700547 }
548
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700549 synchronized(mConfigureLock) {
550 if (!mConfiguring) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800551 String err = "Cannot delete stream, no configuration change in progress.";
552 Log.e(TAG, err);
553 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700554 }
555 int index = mSurfaces.indexOfKey(streamId);
556 if (index < 0) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800557 String err = "Cannot delete stream, stream id " + streamId + " doesn't exist.";
558 Log.e(TAG, err);
559 throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700560 }
561 mSurfaces.removeAt(index);
562 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700563 }
564
565 @Override
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -0700566 public int createStream(OutputConfiguration outputConfiguration) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700567 if (DEBUG) {
568 Log.d(TAG, "createStream called.");
569 }
Ruben Brunke663cb772014-09-16 13:18:31 -0700570 if (mLegacyDevice.isClosed()) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800571 String err = "Cannot create stream, device has been closed.";
572 Log.e(TAG, err);
573 throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
Ruben Brunke663cb772014-09-16 13:18:31 -0700574 }
575
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700576 synchronized(mConfigureLock) {
577 if (!mConfiguring) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800578 String err = "Cannot create stream, beginConfigure hasn't been called yet.";
579 Log.e(TAG, err);
580 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700581 }
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -0700582 if (outputConfiguration.getRotation() != OutputConfiguration.ROTATION_0) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800583 String err = "Cannot create stream, stream rotation is not supported.";
584 Log.e(TAG, err);
585 throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -0700586 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700587 int id = ++mSurfaceIdCounter;
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -0700588 mSurfaces.put(id, outputConfiguration.getSurface());
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700589 return id;
590 }
591 }
592
593 @Override
Shuzhen Wang4bd7abe2017-01-11 09:58:58 -0800594 public void finalizeOutputConfigurations(int steamId, OutputConfiguration config) {
595 String err = "Finalizing output configuration is not supported on legacy devices";
Zhijun Hec8b181e2016-05-30 14:54:39 -0700596 Log.e(TAG, err);
597 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
598 }
599
600 @Override
Chien-Yu Chen5398a672015-03-19 14:48:43 -0700601 public int createInputStream(int width, int height, int format) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800602 String err = "Creating input stream is not supported on legacy devices";
603 Log.e(TAG, err);
604 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
Chien-Yu Chen5398a672015-03-19 14:48:43 -0700605 }
606
607 @Override
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800608 public Surface getInputSurface() {
609 String err = "Getting input surface is not supported on legacy devices";
610 Log.e(TAG, err);
611 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
Chien-Yu Chen5398a672015-03-19 14:48:43 -0700612 }
613
614 @Override
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800615 public CameraMetadataNative createDefaultRequest(int templateId) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700616 if (DEBUG) {
617 Log.d(TAG, "createDefaultRequest called.");
618 }
Ruben Brunke663cb772014-09-16 13:18:31 -0700619 if (mLegacyDevice.isClosed()) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800620 String err = "Cannot create default request, device has been closed.";
621 Log.e(TAG, err);
622 throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
Ruben Brunke663cb772014-09-16 13:18:31 -0700623 }
Igor Murashkina296fec2014-06-23 14:44:09 -0700624
625 CameraMetadataNative template;
626 try {
627 template =
628 LegacyMetadataMapper.createRequestTemplate(mCameraCharacteristics, templateId);
629 } catch (IllegalArgumentException e) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800630 String err = "createDefaultRequest - invalid templateId specified";
631 Log.e(TAG, err);
632 throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
Igor Murashkina296fec2014-06-23 14:44:09 -0700633 }
634
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800635 return template;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700636 }
637
638 @Override
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800639 public CameraMetadataNative getCameraInfo() {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700640 if (DEBUG) {
641 Log.d(TAG, "getCameraInfo called.");
642 }
643 // TODO: implement getCameraInfo.
644 Log.e(TAG, "getCameraInfo unimplemented.");
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800645 return null;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700646 }
647
648 @Override
Emilian Peev03233152017-10-27 16:01:20 +0100649 public void updateOutputConfiguration(int streamId, OutputConfiguration config) {
650 // TODO: b/63912484 implement updateOutputConfiguration.
651 }
652
653 @Override
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800654 public void waitUntilIdle() throws RemoteException {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700655 if (DEBUG) {
656 Log.d(TAG, "waitUntilIdle called.");
657 }
Ruben Brunke663cb772014-09-16 13:18:31 -0700658 if (mLegacyDevice.isClosed()) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800659 String err = "Cannot wait until idle, device has been closed.";
660 Log.e(TAG, err);
661 throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
Ruben Brunke663cb772014-09-16 13:18:31 -0700662 }
663
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700664 synchronized(mConfigureLock) {
665 if (mConfiguring) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800666 String err = "Cannot wait until idle, configuration change in progress.";
667 Log.e(TAG, err);
668 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700669 }
670 }
671 mLegacyDevice.waitUntilIdle();
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700672 }
673
674 @Override
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800675 public long flush() {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700676 if (DEBUG) {
677 Log.d(TAG, "flush called.");
678 }
Ruben Brunke663cb772014-09-16 13:18:31 -0700679 if (mLegacyDevice.isClosed()) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800680 String err = "Cannot flush, device has been closed.";
681 Log.e(TAG, err);
682 throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
Ruben Brunke663cb772014-09-16 13:18:31 -0700683 }
684
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700685 synchronized(mConfigureLock) {
686 if (mConfiguring) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800687 String err = "Cannot flush, configuration change in progress.";
688 Log.e(TAG, err);
689 throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700690 }
691 }
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800692 return mLegacyDevice.flush();
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700693 }
694
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800695 public void prepare(int streamId) {
Eino-Ville Talvalaad916f72015-04-11 12:09:11 -0700696 if (DEBUG) {
697 Log.d(TAG, "prepare called.");
698 }
699 if (mLegacyDevice.isClosed()) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800700 String err = "Cannot prepare stream, device has been closed.";
701 Log.e(TAG, err);
702 throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
Eino-Ville Talvalaad916f72015-04-11 12:09:11 -0700703 }
704
Eino-Ville Talvalabe6d9852015-04-29 11:37:00 -0700705 // LEGACY doesn't support actual prepare, just signal success right away
706 mCameraCallbacks.onPrepared(streamId);
Eino-Ville Talvalaad916f72015-04-11 12:09:11 -0700707 }
708
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800709 public void prepare2(int maxCount, int streamId) {
Ruben Brunk7ed1aaa2015-08-13 17:57:14 -0700710 // We don't support this in LEGACY mode.
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800711 prepare(streamId);
Ruben Brunk7ed1aaa2015-08-13 17:57:14 -0700712 }
713
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800714 public void tearDown(int streamId) {
Eino-Ville Talvala14c09fa2015-07-15 16:04:04 -0700715 if (DEBUG) {
716 Log.d(TAG, "tearDown called.");
717 }
718 if (mLegacyDevice.isClosed()) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800719 String err = "Cannot tear down stream, device has been closed.";
720 Log.e(TAG, err);
721 throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
Eino-Ville Talvala14c09fa2015-07-15 16:04:04 -0700722 }
723
724 // LEGACY doesn't support actual teardown, so just a no-op
Eino-Ville Talvala14c09fa2015-07-15 16:04:04 -0700725 }
726
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700727 @Override
728 public IBinder asBinder() {
729 // This is solely intended to be used for in-process binding.
730 return null;
731 }
732}