blob: 30561ba0f7601ed9302070c3cc515a16bbf9dfe3 [file] [log] [blame]
Igor Murashkin70725502013-06-25 20:27:06 +00001/*
2 * Copyright (C) 2013 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 com.android.mediaframeworktest.integration;
18
Philip P. Moltmann68366072017-11-27 12:29:20 -080019import static android.hardware.camera2.CameraDevice.TEMPLATE_PREVIEW;
20
21import static org.mockito.Mockito.any;
22import static org.mockito.Mockito.anyLong;
23import static org.mockito.Mockito.argThat;
24import static org.mockito.Mockito.spy;
25import static org.mockito.Mockito.timeout;
26import static org.mockito.Mockito.verify;
27
Zhijun He7b7a1542013-09-25 16:33:35 -070028import android.graphics.ImageFormat;
Igor Murashkin70725502013-06-25 20:27:06 +000029import android.graphics.SurfaceTexture;
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -080030import android.hardware.ICameraService;
Chien-Yu Chen7a316f6b2015-04-13 14:31:45 -070031import android.hardware.camera2.CameraCaptureSession;
Igor Murashkin68f40062013-09-10 12:15:54 -070032import android.hardware.camera2.CameraCharacteristics;
Eino-Ville Talvala2f1a2e42013-07-25 17:12:05 -070033import android.hardware.camera2.CaptureRequest;
34import android.hardware.camera2.ICameraDeviceCallbacks;
35import android.hardware.camera2.ICameraDeviceUser;
Eino-Ville Talvala70c22072013-08-27 12:09:04 -070036import android.hardware.camera2.impl.CameraMetadataNative;
Igor Murashkin72f9f0a2014-05-14 15:46:10 -070037import android.hardware.camera2.impl.CaptureResultExtras;
Shuzhen Wang0960fb42018-01-10 20:35:11 -080038import android.hardware.camera2.impl.PhysicalCaptureResultInfo;
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -070039import android.hardware.camera2.params.OutputConfiguration;
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -080040import android.hardware.camera2.utils.SubmitInfo;
Zhijun He7b7a1542013-09-25 16:33:35 -070041import android.media.Image;
42import android.media.ImageReader;
43import android.os.Handler;
44import android.os.HandlerThread;
Igor Murashkin70725502013-06-25 20:27:06 +000045import android.os.RemoteException;
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -080046import android.os.ServiceSpecificException;
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -070047import android.os.SystemClock;
Igor Murashkin70725502013-06-25 20:27:06 +000048import android.test.AndroidTestCase;
49import android.test.suitebuilder.annotation.SmallTest;
50import android.util.Log;
51import android.view.Surface;
52
Igor Murashkin70725502013-06-25 20:27:06 +000053import com.android.mediaframeworktest.MediaFrameworkIntegrationTestRunner;
Zhijun He693e21d2013-07-31 14:16:14 -070054
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -070055import org.mockito.ArgumentCaptor;
Philip P. Moltmann68366072017-11-27 12:29:20 -080056import org.mockito.ArgumentMatcher;
Igor Murashkin70725502013-06-25 20:27:06 +000057
58public class CameraDeviceBinderTest extends AndroidTestCase {
59 private static String TAG = "CameraDeviceBinderTest";
Zhijun He693e21d2013-07-31 14:16:14 -070060 // Number of streaming callbacks need to check.
61 private static int NUM_CALLBACKS_CHECKED = 10;
Ruben Brunk66ef6452013-08-08 13:05:30 -070062 // Wait for capture result timeout value: 1500ms
63 private final static int WAIT_FOR_COMPLETE_TIMEOUT_MS = 1500;
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -070064 // Wait for flush timeout value: 1000ms
65 private final static int WAIT_FOR_FLUSH_TIMEOUT_MS = 1000;
66 // Wait for idle timeout value: 2000ms
67 private final static int WAIT_FOR_IDLE_TIMEOUT_MS = 2000;
68 // Wait while camera device starts working on requests
69 private final static int WAIT_FOR_WORK_MS = 300;
Zhijun He7b7a1542013-09-25 16:33:35 -070070 // Default size is VGA, which is mandatory camera supported image size by CDD.
71 private static final int DEFAULT_IMAGE_WIDTH = 640;
72 private static final int DEFAULT_IMAGE_HEIGHT = 480;
73 private static final int MAX_NUM_IMAGES = 5;
Igor Murashkin70725502013-06-25 20:27:06 +000074
Eino-Ville Talvala283ae234f2016-12-08 13:38:52 -080075 private String mCameraId;
Igor Murashkin70725502013-06-25 20:27:06 +000076 private ICameraDeviceUser mCameraUser;
77 private CameraBinderTestUtils mUtils;
Zhijun He693e21d2013-07-31 14:16:14 -070078 private ICameraDeviceCallbacks.Stub mMockCb;
79 private Surface mSurface;
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -070080 private OutputConfiguration mOutputConfiguration;
Zhijun He7b7a1542013-09-25 16:33:35 -070081 private HandlerThread mHandlerThread;
82 private Handler mHandler;
83 ImageReader mImageReader;
Igor Murashkin70725502013-06-25 20:27:06 +000084
85 public CameraDeviceBinderTest() {
86 }
87
Zhijun He7b7a1542013-09-25 16:33:35 -070088 private class ImageDropperListener implements ImageReader.OnImageAvailableListener {
89
90 @Override
91 public void onImageAvailable(ImageReader reader) {
92 Image image = reader.acquireNextImage();
93 if (image != null) image.close();
94 }
95 }
96
Zhijun He693e21d2013-07-31 14:16:14 -070097 public class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
Igor Murashkin70725502013-06-25 20:27:06 +000098
Zhijun He438d77e2014-04-10 17:09:22 -070099 /*
100 * (non-Javadoc)
101 * @see
Eino-Ville Talvalaacc00952014-08-06 14:31:08 -0700102 * android.hardware.camera2.ICameraDeviceCallbacks#onDeviceError(int,
Zhijun He438d77e2014-04-10 17:09:22 -0700103 * android.hardware.camera2.CaptureResultExtras)
104 */
Eino-Ville Talvalaacc00952014-08-06 14:31:08 -0700105 public void onDeviceError(int errorCode, CaptureResultExtras resultExtras)
Zhijun He438d77e2014-04-10 17:09:22 -0700106 throws RemoteException {
107 // TODO Auto-generated method stub
108
Igor Murashkin70725502013-06-25 20:27:06 +0000109 }
110
Zhijun He438d77e2014-04-10 17:09:22 -0700111 /*
112 * (non-Javadoc)
Eino-Ville Talvalaacc00952014-08-06 14:31:08 -0700113 * @see android.hardware.camera2.ICameraDeviceCallbacks#onDeviceIdle()
Zhijun He438d77e2014-04-10 17:09:22 -0700114 */
Eino-Ville Talvalaacc00952014-08-06 14:31:08 -0700115 public void onDeviceIdle() throws RemoteException {
Zhijun He438d77e2014-04-10 17:09:22 -0700116 // TODO Auto-generated method stub
117
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700118 }
119
Zhijun He438d77e2014-04-10 17:09:22 -0700120 /*
121 * (non-Javadoc)
122 * @see
123 * android.hardware.camera2.ICameraDeviceCallbacks#onCaptureStarted(
124 * android.hardware.camera2.CaptureResultExtras, long)
125 */
126 public void onCaptureStarted(CaptureResultExtras resultExtras, long timestamp)
127 throws RemoteException {
128 // TODO Auto-generated method stub
129
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700130 }
131
Zhijun He438d77e2014-04-10 17:09:22 -0700132 /*
133 * (non-Javadoc)
134 * @see
135 * android.hardware.camera2.ICameraDeviceCallbacks#onResultReceived(
136 * android.hardware.camera2.impl.CameraMetadataNative,
137 * android.hardware.camera2.CaptureResultExtras)
138 */
Shuzhen Wang0960fb42018-01-10 20:35:11 -0800139 public void onResultReceived(CameraMetadataNative result, CaptureResultExtras resultExtras,
140 PhysicalCaptureResultInfo physicalResults[]) throws RemoteException {
Zhijun He438d77e2014-04-10 17:09:22 -0700141 // TODO Auto-generated method stub
142
Igor Murashkin70725502013-06-25 20:27:06 +0000143 }
Eino-Ville Talvalaad916f72015-04-11 12:09:11 -0700144
145 /*
146 * (non-Javadoc)
147 * @see android.hardware.camera2.ICameraDeviceCallbacks#onPrepared()
148 */
149 @Override
150 public void onPrepared(int streamId) throws RemoteException {
151 // TODO Auto-generated method stub
152
153 }
Chien-Yu Chen2da496f2016-04-14 13:33:00 -0700154
155 /*
156 * (non-Javadoc)
Shuzhen Wang88f1af22016-09-30 10:29:28 -0700157 * @see android.hardware.camera2.ICameraDeviceCallbacks#onRequestQueueEmpty()
158 */
159 @Override
160 public void onRequestQueueEmpty() throws RemoteException {
161 // TODO Auto-generated method stub
162
163 }
164
165 /*
166 * (non-Javadoc)
Chien-Yu Chen2da496f2016-04-14 13:33:00 -0700167 * @see android.hardware.camera2.ICameraDeviceCallbacks#onRepeatingRequestError()
168 */
169 @Override
Yin-Chia Yeh8cd12e92017-09-05 18:14:21 -0700170 public void onRepeatingRequestError(long lastFrameNumber, int repeatingRequestId) {
Chien-Yu Chen2da496f2016-04-14 13:33:00 -0700171 // TODO Auto-generated method stub
172 }
Igor Murashkin70725502013-06-25 20:27:06 +0000173 }
174
Philip P. Moltmann68366072017-11-27 12:29:20 -0800175 class IsMetadataNotEmpty implements ArgumentMatcher<CameraMetadataNative> {
Zhijun He20011882013-09-25 10:05:59 -0700176 @Override
Philip P. Moltmann68366072017-11-27 12:29:20 -0800177 public boolean matches(CameraMetadataNative obj) {
178 return !obj.isEmpty();
Zhijun He693e21d2013-07-31 14:16:14 -0700179 }
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700180 }
Zhijun He693e21d2013-07-31 14:16:14 -0700181
182 private void createDefaultSurface() {
Zhijun He7b7a1542013-09-25 16:33:35 -0700183 mImageReader =
184 ImageReader.newInstance(DEFAULT_IMAGE_WIDTH,
185 DEFAULT_IMAGE_HEIGHT,
186 ImageFormat.YUV_420_888,
187 MAX_NUM_IMAGES);
188 mImageReader.setOnImageAvailableListener(new ImageDropperListener(), mHandler);
189 mSurface = mImageReader.getSurface();
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -0700190 mOutputConfiguration = new OutputConfiguration(mSurface);
Zhijun He693e21d2013-07-31 14:16:14 -0700191 }
192
Eino-Ville Talvala70c22072013-08-27 12:09:04 -0700193 private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800194 CameraMetadataNative metadata = null;
Zhijun He693e21d2013-07-31 14:16:14 -0700195 assertTrue(metadata.isEmpty());
196
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800197 metadata = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW);
Zhijun He693e21d2013-07-31 14:16:14 -0700198 assertFalse(metadata.isEmpty());
199
Chien-Yu Chen7a316f6b2015-04-13 14:31:45 -0700200 CaptureRequest.Builder request = new CaptureRequest.Builder(metadata, /*reprocess*/false,
Emilian Peev2100ae72018-01-12 16:56:25 +0000201 CameraCaptureSession.SESSION_ID_NONE, mCameraId, /*physicalCameraIdSet*/null);
Zhijun He693e21d2013-07-31 14:16:14 -0700202 assertFalse(request.isEmpty());
Eino-Ville Talvala70c22072013-08-27 12:09:04 -0700203 assertFalse(metadata.isEmpty());
Zhijun He693e21d2013-07-31 14:16:14 -0700204 if (needStream) {
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -0700205 int streamId = mCameraUser.createStream(mOutputConfiguration);
Zhijun He693e21d2013-07-31 14:16:14 -0700206 assertEquals(0, streamId);
207 request.addTarget(mSurface);
208 }
209 return request;
210 }
211
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800212 private SubmitInfo submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
213 SubmitInfo requestInfo = mCameraUser.submitRequest(request, streaming);
Igor Murashkin5c207ec2014-04-01 15:50:48 -0700214 assertTrue(
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800215 "Request IDs should be non-negative (expected: >= 0, actual: " +
216 requestInfo.getRequestId() + ")",
217 requestInfo.getRequestId() >= 0);
218 return requestInfo;
Zhijun He693e21d2013-07-31 14:16:14 -0700219 }
220
Igor Murashkin70725502013-06-25 20:27:06 +0000221 @Override
222 protected void setUp() throws Exception {
223 super.setUp();
224
Zhijun He693e21d2013-07-31 14:16:14 -0700225 /**
226 * Workaround for mockito and JB-MR2 incompatibility
227 *
228 * Avoid java.lang.IllegalArgumentException: dexcache == null
229 * https://code.google.com/p/dexmaker/issues/detail?id=2
230 */
231 System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
Igor Murashkin70725502013-06-25 20:27:06 +0000232 mUtils = new CameraBinderTestUtils(getContext());
233
234 // This cannot be set in the constructor, since the onCreate isn't
235 // called yet
236 mCameraId = MediaFrameworkIntegrationTestRunner.mCameraId;
237
Zhijun He693e21d2013-07-31 14:16:14 -0700238 ICameraDeviceCallbacks.Stub dummyCallbacks = new DummyCameraDeviceCallbacks();
Igor Murashkin70725502013-06-25 20:27:06 +0000239
240 String clientPackageName = getContext().getPackageName();
241
Zhijun He693e21d2013-07-31 14:16:14 -0700242 mMockCb = spy(dummyCallbacks);
243
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800244 mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
245 clientPackageName, ICameraService.USE_CALLING_UID);
Igor Murashkin70725502013-06-25 20:27:06 +0000246 assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
Zhijun He7b7a1542013-09-25 16:33:35 -0700247 mHandlerThread = new HandlerThread(TAG);
248 mHandlerThread.start();
249 mHandler = new Handler(mHandlerThread.getLooper());
Zhijun He693e21d2013-07-31 14:16:14 -0700250 createDefaultSurface();
Igor Murashkin70725502013-06-25 20:27:06 +0000251
252 Log.v(TAG, String.format("Camera %s connected", mCameraId));
253 }
254
255 @Override
256 protected void tearDown() throws Exception {
257 mCameraUser.disconnect();
258 mCameraUser = null;
Zhijun He693e21d2013-07-31 14:16:14 -0700259 mSurface.release();
Zhijun He7b7a1542013-09-25 16:33:35 -0700260 mImageReader.close();
261 mHandlerThread.quitSafely();
Igor Murashkin70725502013-06-25 20:27:06 +0000262 }
263
264 @SmallTest
265 public void testCreateDefaultRequest() throws Exception {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800266 CameraMetadataNative metadata = null;
Igor Murashkin70725502013-06-25 20:27:06 +0000267 assertTrue(metadata.isEmpty());
268
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800269 metadata = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW);
Igor Murashkin70725502013-06-25 20:27:06 +0000270 assertFalse(metadata.isEmpty());
271
Igor Murashkin70725502013-06-25 20:27:06 +0000272 }
273
274 @SmallTest
275 public void testCreateStream() throws Exception {
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -0700276 int streamId = mCameraUser.createStream(mOutputConfiguration);
Igor Murashkin70725502013-06-25 20:27:06 +0000277 assertEquals(0, streamId);
278
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800279 try {
280 mCameraUser.createStream(mOutputConfiguration);
281 fail("Creating same stream twice");
282 } catch (ServiceSpecificException e) {
283 assertEquals("Creating same stream twice",
284 e.errorCode, ICameraService.ERROR_ALREADY_EXISTS);
285 }
Igor Murashkin70725502013-06-25 20:27:06 +0000286
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800287 mCameraUser.deleteStream(streamId);
Igor Murashkin70725502013-06-25 20:27:06 +0000288 }
289
290 @SmallTest
291 public void testDeleteInvalidStream() throws Exception {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800292 int[] badStreams = { -1, 0, 1, 0xC0FFEE };
293 for (int badStream : badStreams) {
294 try {
295 mCameraUser.deleteStream(badStream);
296 fail("Allowed bad stream delete");
297 } catch (ServiceSpecificException e) {
298 assertEquals(e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT);
299 }
300 }
Igor Murashkin70725502013-06-25 20:27:06 +0000301 }
302
303 @SmallTest
304 public void testCreateStreamTwo() throws Exception {
305
306 // Create first stream
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -0700307 int streamId = mCameraUser.createStream(mOutputConfiguration);
Igor Murashkin70725502013-06-25 20:27:06 +0000308 assertEquals(0, streamId);
309
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800310 try {
311 mCameraUser.createStream(mOutputConfiguration);
312 fail("Created same stream twice");
313 } catch (ServiceSpecificException e) {
314 assertEquals("Created same stream twice",
315 ICameraService.ERROR_ALREADY_EXISTS, e.errorCode);
316 }
Igor Murashkin70725502013-06-25 20:27:06 +0000317
Zhijun He693e21d2013-07-31 14:16:14 -0700318 // Create second stream with a different surface.
319 SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
320 surfaceTexture.setDefaultBufferSize(640, 480);
321 Surface surface2 = new Surface(surfaceTexture);
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -0700322 OutputConfiguration output2 = new OutputConfiguration(surface2);
Igor Murashkin70725502013-06-25 20:27:06 +0000323
Yin-Chia Yehbfbbee72015-03-12 13:39:26 -0700324 int streamId2 = mCameraUser.createStream(output2);
Igor Murashkin70725502013-06-25 20:27:06 +0000325 assertEquals(1, streamId2);
326
327 // Clean up streams
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800328 mCameraUser.deleteStream(streamId);
329 mCameraUser.deleteStream(streamId2);
Igor Murashkin70725502013-06-25 20:27:06 +0000330 }
331
332 @SmallTest
333 public void testSubmitBadRequest() throws Exception {
334
Eino-Ville Talvala70c22072013-08-27 12:09:04 -0700335 CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */false);
336 CaptureRequest request1 = builder.build();
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800337 try {
338 SubmitInfo requestInfo = mCameraUser.submitRequest(request1, /* streaming */false);
339 fail("Exception expected");
340 } catch(ServiceSpecificException e) {
341 assertEquals("Expected submitRequest to throw ServiceSpecificException with BAD_VALUE " +
342 "since we had 0 surface targets set.", ICameraService.ERROR_ILLEGAL_ARGUMENT,
343 e.errorCode);
344 }
Igor Murashkin70725502013-06-25 20:27:06 +0000345
Eino-Ville Talvala70c22072013-08-27 12:09:04 -0700346 builder.addTarget(mSurface);
347 CaptureRequest request2 = builder.build();
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800348 try {
349 SubmitInfo requestInfo = mCameraUser.submitRequest(request2, /* streaming */false);
350 fail("Exception expected");
351 } catch(ServiceSpecificException e) {
352 assertEquals("Expected submitRequest to throw ILLEGAL_ARGUMENT " +
353 "ServiceSpecificException since the target wasn't registered with createStream.",
354 ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
355 }
Igor Murashkin70725502013-06-25 20:27:06 +0000356 }
357
358 @SmallTest
359 public void testSubmitGoodRequest() throws Exception {
360
Eino-Ville Talvala70c22072013-08-27 12:09:04 -0700361 CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true);
362 CaptureRequest request = builder.build();
Igor Murashkin70725502013-06-25 20:27:06 +0000363
364 // Submit valid request twice.
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800365 SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
366 SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
367 assertNotSame("Request IDs should be unique for multiple requests",
368 requestInfo1.getRequestId(), requestInfo2.getRequestId());
Igor Murashkin70725502013-06-25 20:27:06 +0000369
Igor Murashkin70725502013-06-25 20:27:06 +0000370 }
371
372 @SmallTest
373 public void testSubmitStreamingRequest() throws Exception {
374
Eino-Ville Talvala70c22072013-08-27 12:09:04 -0700375 CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true);
376
377 CaptureRequest request = builder.build();
Igor Murashkin70725502013-06-25 20:27:06 +0000378
379 // Submit valid request once (non-streaming), and another time
380 // (streaming)
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800381 SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
Igor Murashkin70725502013-06-25 20:27:06 +0000382
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800383 SubmitInfo requestInfoStreaming = submitCameraRequest(request, /* streaming */true);
384 assertNotSame("Request IDs should be unique for multiple requests",
385 requestInfo1.getRequestId(),
386 requestInfoStreaming.getRequestId());
Igor Murashkin70725502013-06-25 20:27:06 +0000387
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800388 try {
389 long lastFrameNumber = mCameraUser.cancelRequest(-1);
390 fail("Expected exception");
391 } catch (ServiceSpecificException e) {
392 assertEquals("Invalid request IDs should not be cancellable",
393 ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
394 }
Igor Murashkin70725502013-06-25 20:27:06 +0000395
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800396 try {
397 long lastFrameNumber = mCameraUser.cancelRequest(requestInfo1.getRequestId());
398 fail("Expected exception");
399 } catch (ServiceSpecificException e) {
400 assertEquals("Non-streaming request IDs should not be cancellable",
401 ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
402 }
Igor Murashkin70725502013-06-25 20:27:06 +0000403
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800404 long lastFrameNumber = mCameraUser.cancelRequest(requestInfoStreaming.getRequestId());
Igor Murashkin70725502013-06-25 20:27:06 +0000405 }
Igor Murashkind7bf1772013-07-12 18:01:31 -0700406
407 @SmallTest
408 public void testCameraInfo() throws RemoteException {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800409 CameraMetadataNative info = mCameraUser.getCameraInfo();
Igor Murashkind7bf1772013-07-12 18:01:31 -0700410
411 assertFalse(info.isEmpty());
Igor Murashkin68f40062013-09-10 12:15:54 -0700412 assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
Igor Murashkind7bf1772013-07-12 18:01:31 -0700413 }
414
Zhijun He7f4d3142013-07-23 07:54:38 -0700415 @SmallTest
Zhijun He20011882013-09-25 10:05:59 -0700416 public void testCameraCharacteristics() throws RemoteException {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800417 CameraMetadataNative info = mUtils.getCameraService().getCameraCharacteristics(mCameraId);
Zhijun He20011882013-09-25 10:05:59 -0700418
419 assertFalse(info.isEmpty());
420 assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
421 }
422
423 @SmallTest
Zhijun He7f4d3142013-07-23 07:54:38 -0700424 public void testWaitUntilIdle() throws Exception {
Eino-Ville Talvala70c22072013-08-27 12:09:04 -0700425 CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true);
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800426 SubmitInfo requestInfoStreaming = submitCameraRequest(builder.build(), /* streaming */true);
Zhijun He7f4d3142013-07-23 07:54:38 -0700427
428 // Test Bad case first: waitUntilIdle when there is active repeating request
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800429 try {
430 mCameraUser.waitUntilIdle();
431 } catch (ServiceSpecificException e) {
432 assertEquals("waitUntilIdle is invalid operation when there is active repeating request",
433 ICameraService.ERROR_INVALID_OPERATION, e.errorCode);
434 }
Zhijun He7f4d3142013-07-23 07:54:38 -0700435
436 // Test good case, waitUntilIdle when there is no active repeating request
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800437 long lastFrameNumber = mCameraUser.cancelRequest(requestInfoStreaming.getRequestId());
438 mCameraUser.waitUntilIdle();
Zhijun He7f4d3142013-07-23 07:54:38 -0700439 }
440
Zhijun He693e21d2013-07-31 14:16:14 -0700441 @SmallTest
442 public void testCaptureResultCallbacks() throws Exception {
443 IsMetadataNotEmpty matcher = new IsMetadataNotEmpty();
Eino-Ville Talvala70c22072013-08-27 12:09:04 -0700444 CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
Zhijun He693e21d2013-07-31 14:16:14 -0700445
446 // Test both single request and streaming request.
Zhijun He693e21d2013-07-31 14:16:14 -0700447 verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onResultReceived(
Zhijun He438d77e2014-04-10 17:09:22 -0700448 argThat(matcher),
Shuzhen Wang0960fb42018-01-10 20:35:11 -0800449 any(CaptureResultExtras.class),
450 any(PhysicalCaptureResultInfo[].class));
Zhijun He693e21d2013-07-31 14:16:14 -0700451
Zhijun He693e21d2013-07-31 14:16:14 -0700452 verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
453 .onResultReceived(
Zhijun He438d77e2014-04-10 17:09:22 -0700454 argThat(matcher),
Shuzhen Wang0960fb42018-01-10 20:35:11 -0800455 any(CaptureResultExtras.class),
456 any(PhysicalCaptureResultInfo[].class));
Zhijun He693e21d2013-07-31 14:16:14 -0700457 }
Eino-Ville Talvala8ebd52b2013-08-13 12:09:44 -0700458
459 @SmallTest
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700460 public void testCaptureStartedCallbacks() throws Exception {
461 CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
462
463 ArgumentCaptor<Long> timestamps = ArgumentCaptor.forClass(Long.class);
464
465 // Test both single request and streaming request.
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800466 SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700467 verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onCaptureStarted(
Zhijun He438d77e2014-04-10 17:09:22 -0700468 any(CaptureResultExtras.class),
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700469 anyLong());
470
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800471 SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700472 verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
473 .onCaptureStarted(
Zhijun He438d77e2014-04-10 17:09:22 -0700474 any(CaptureResultExtras.class),
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700475 timestamps.capture());
476
477 long timestamp = 0; // All timestamps should be larger than 0.
478 for (Long nextTimestamp : timestamps.getAllValues()) {
479 Log.v(TAG, "next t: " + nextTimestamp + " current t: " + timestamp);
480 assertTrue("Captures are out of order", timestamp < nextTimestamp);
481 timestamp = nextTimestamp;
482 }
483 }
484
485 @SmallTest
486 public void testIdleCallback() throws Exception {
487 int status;
488 CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
489
490 // Try streaming
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800491 SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700492
493 // Wait a bit to fill up the queue
494 SystemClock.sleep(WAIT_FOR_WORK_MS);
495
496 // Cancel and make sure we eventually quiesce
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800497 long lastFrameNumber = mCameraUser.cancelRequest(streamingInfo.getRequestId());
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700498
Eino-Ville Talvalaacc00952014-08-06 14:31:08 -0700499 verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(1)).onDeviceIdle();
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700500
501 // Submit a few capture requests
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800502 SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
503 SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
504 SubmitInfo requestInfo3 = submitCameraRequest(request, /* streaming */false);
505 SubmitInfo requestInfo4 = submitCameraRequest(request, /* streaming */false);
506 SubmitInfo requestInfo5 = submitCameraRequest(request, /* streaming */false);
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700507
508 // And wait for more idle
Eino-Ville Talvalaacc00952014-08-06 14:31:08 -0700509 verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(2)).onDeviceIdle();
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700510
511 }
512
513 @SmallTest
Eino-Ville Talvala8ebd52b2013-08-13 12:09:44 -0700514 public void testFlush() throws Exception {
515 int status;
516
517 // Initial flush should work
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800518 long lastFrameNumber = mCameraUser.flush();
Eino-Ville Talvala8ebd52b2013-08-13 12:09:44 -0700519
520 // Then set up a stream
Eino-Ville Talvala70c22072013-08-27 12:09:04 -0700521 CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
Eino-Ville Talvala8ebd52b2013-08-13 12:09:44 -0700522
523 // Flush should still be a no-op, really
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800524 lastFrameNumber = mCameraUser.flush();
Eino-Ville Talvala8ebd52b2013-08-13 12:09:44 -0700525
526 // Submit a few capture requests
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800527 SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
528 SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
529 SubmitInfo requestInfo3 = submitCameraRequest(request, /* streaming */false);
530 SubmitInfo requestInfo4 = submitCameraRequest(request, /* streaming */false);
531 SubmitInfo requestInfo5 = submitCameraRequest(request, /* streaming */false);
Eino-Ville Talvala8ebd52b2013-08-13 12:09:44 -0700532
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700533 // Then flush and wait for idle
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800534 lastFrameNumber = mCameraUser.flush();
Eino-Ville Talvala8ebd52b2013-08-13 12:09:44 -0700535
Eino-Ville Talvalaacc00952014-08-06 14:31:08 -0700536 verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(1)).onDeviceIdle();
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700537
538 // Now a streaming request
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800539 SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700540
541 // Wait a bit to fill up the queue
542 SystemClock.sleep(WAIT_FOR_WORK_MS);
543
544 // Then flush and wait for the idle callback
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800545 lastFrameNumber = mCameraUser.flush();
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700546
Eino-Ville Talvalaacc00952014-08-06 14:31:08 -0700547 verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(2)).onDeviceIdle();
Eino-Ville Talvalae841d4e2013-09-05 09:04:08 -0700548
Eino-Ville Talvala8ebd52b2013-08-13 12:09:44 -0700549 // TODO: When errors are hooked up, count that errors + successful
550 // requests equal to 5.
551 }
Igor Murashkin70725502013-06-25 20:27:06 +0000552}