Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package com.android.mediaframeworktest.integration; |
| 18 | |
Zhijun He | 7b7a154 | 2013-09-25 16:33:35 -0700 | [diff] [blame] | 19 | import android.graphics.ImageFormat; |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 20 | import android.graphics.SurfaceTexture; |
Eino-Ville Talvala | 2f1a2e4 | 2013-07-25 17:12:05 -0700 | [diff] [blame] | 21 | import android.hardware.camera2.CameraMetadata; |
Igor Murashkin | 68f4006 | 2013-09-10 12:15:54 -0700 | [diff] [blame] | 22 | import android.hardware.camera2.CameraCharacteristics; |
Eino-Ville Talvala | 2f1a2e4 | 2013-07-25 17:12:05 -0700 | [diff] [blame] | 23 | import android.hardware.camera2.CaptureRequest; |
| 24 | import android.hardware.camera2.ICameraDeviceCallbacks; |
| 25 | import android.hardware.camera2.ICameraDeviceUser; |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 26 | import android.hardware.camera2.impl.CameraMetadataNative; |
Igor Murashkin | 72f9f0a | 2014-05-14 15:46:10 -0700 | [diff] [blame] | 27 | import android.hardware.camera2.impl.CaptureResultExtras; |
Yin-Chia Yeh | 981e056 | 2015-03-12 13:39:26 -0700 | [diff] [blame^] | 28 | import android.hardware.camera2.params.OutputConfiguration; |
Ruben Brunk | 66ef645 | 2013-08-08 13:05:30 -0700 | [diff] [blame] | 29 | import android.hardware.camera2.utils.BinderHolder; |
Zhijun He | 7b7a154 | 2013-09-25 16:33:35 -0700 | [diff] [blame] | 30 | import android.media.Image; |
| 31 | import android.media.ImageReader; |
| 32 | import android.os.Handler; |
| 33 | import android.os.HandlerThread; |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 34 | import android.os.RemoteException; |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 35 | import android.os.SystemClock; |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 36 | import android.test.AndroidTestCase; |
| 37 | import android.test.suitebuilder.annotation.SmallTest; |
| 38 | import android.util.Log; |
| 39 | import android.view.Surface; |
| 40 | |
Eino-Ville Talvala | 2f1a2e4 | 2013-07-25 17:12:05 -0700 | [diff] [blame] | 41 | import static android.hardware.camera2.CameraDevice.TEMPLATE_PREVIEW; |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 42 | |
| 43 | import com.android.mediaframeworktest.MediaFrameworkIntegrationTestRunner; |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 44 | |
| 45 | import org.mockito.ArgumentMatcher; |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 46 | import org.mockito.ArgumentCaptor; |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 47 | import static org.mockito.Mockito.*; |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 48 | |
| 49 | public class CameraDeviceBinderTest extends AndroidTestCase { |
| 50 | private static String TAG = "CameraDeviceBinderTest"; |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 51 | // Number of streaming callbacks need to check. |
| 52 | private static int NUM_CALLBACKS_CHECKED = 10; |
Ruben Brunk | 66ef645 | 2013-08-08 13:05:30 -0700 | [diff] [blame] | 53 | // Wait for capture result timeout value: 1500ms |
| 54 | private final static int WAIT_FOR_COMPLETE_TIMEOUT_MS = 1500; |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 55 | // Wait for flush timeout value: 1000ms |
| 56 | private final static int WAIT_FOR_FLUSH_TIMEOUT_MS = 1000; |
| 57 | // Wait for idle timeout value: 2000ms |
| 58 | private final static int WAIT_FOR_IDLE_TIMEOUT_MS = 2000; |
| 59 | // Wait while camera device starts working on requests |
| 60 | private final static int WAIT_FOR_WORK_MS = 300; |
Zhijun He | 7b7a154 | 2013-09-25 16:33:35 -0700 | [diff] [blame] | 61 | // Default size is VGA, which is mandatory camera supported image size by CDD. |
| 62 | private static final int DEFAULT_IMAGE_WIDTH = 640; |
| 63 | private static final int DEFAULT_IMAGE_HEIGHT = 480; |
| 64 | private static final int MAX_NUM_IMAGES = 5; |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 65 | |
| 66 | private int mCameraId; |
| 67 | private ICameraDeviceUser mCameraUser; |
| 68 | private CameraBinderTestUtils mUtils; |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 69 | private ICameraDeviceCallbacks.Stub mMockCb; |
| 70 | private Surface mSurface; |
Yin-Chia Yeh | 981e056 | 2015-03-12 13:39:26 -0700 | [diff] [blame^] | 71 | private OutputConfiguration mOutputConfiguration; |
Zhijun He | 7b7a154 | 2013-09-25 16:33:35 -0700 | [diff] [blame] | 72 | private HandlerThread mHandlerThread; |
| 73 | private Handler mHandler; |
| 74 | ImageReader mImageReader; |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 75 | |
| 76 | public CameraDeviceBinderTest() { |
| 77 | } |
| 78 | |
Zhijun He | 7b7a154 | 2013-09-25 16:33:35 -0700 | [diff] [blame] | 79 | private class ImageDropperListener implements ImageReader.OnImageAvailableListener { |
| 80 | |
| 81 | @Override |
| 82 | public void onImageAvailable(ImageReader reader) { |
| 83 | Image image = reader.acquireNextImage(); |
| 84 | if (image != null) image.close(); |
| 85 | } |
| 86 | } |
| 87 | |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 88 | public class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub { |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 89 | |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 90 | /* |
| 91 | * (non-Javadoc) |
| 92 | * @see |
Eino-Ville Talvala | acc0095 | 2014-08-06 14:31:08 -0700 | [diff] [blame] | 93 | * android.hardware.camera2.ICameraDeviceCallbacks#onDeviceError(int, |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 94 | * android.hardware.camera2.CaptureResultExtras) |
| 95 | */ |
Eino-Ville Talvala | acc0095 | 2014-08-06 14:31:08 -0700 | [diff] [blame] | 96 | public void onDeviceError(int errorCode, CaptureResultExtras resultExtras) |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 97 | throws RemoteException { |
| 98 | // TODO Auto-generated method stub |
| 99 | |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 100 | } |
| 101 | |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 102 | /* |
| 103 | * (non-Javadoc) |
Eino-Ville Talvala | acc0095 | 2014-08-06 14:31:08 -0700 | [diff] [blame] | 104 | * @see android.hardware.camera2.ICameraDeviceCallbacks#onDeviceIdle() |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 105 | */ |
Eino-Ville Talvala | acc0095 | 2014-08-06 14:31:08 -0700 | [diff] [blame] | 106 | public void onDeviceIdle() throws RemoteException { |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 107 | // TODO Auto-generated method stub |
| 108 | |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 109 | } |
| 110 | |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 111 | /* |
| 112 | * (non-Javadoc) |
| 113 | * @see |
| 114 | * android.hardware.camera2.ICameraDeviceCallbacks#onCaptureStarted( |
| 115 | * android.hardware.camera2.CaptureResultExtras, long) |
| 116 | */ |
| 117 | public void onCaptureStarted(CaptureResultExtras resultExtras, long timestamp) |
| 118 | throws RemoteException { |
| 119 | // TODO Auto-generated method stub |
| 120 | |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 121 | } |
| 122 | |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 123 | /* |
| 124 | * (non-Javadoc) |
| 125 | * @see |
| 126 | * android.hardware.camera2.ICameraDeviceCallbacks#onResultReceived( |
| 127 | * android.hardware.camera2.impl.CameraMetadataNative, |
| 128 | * android.hardware.camera2.CaptureResultExtras) |
| 129 | */ |
| 130 | public void onResultReceived(CameraMetadataNative result, CaptureResultExtras resultExtras) |
| 131 | throws RemoteException { |
| 132 | // TODO Auto-generated method stub |
| 133 | |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 134 | } |
| 135 | } |
| 136 | |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 137 | class IsMetadataNotEmpty extends ArgumentMatcher<CameraMetadataNative> { |
Zhijun He | 2001188 | 2013-09-25 10:05:59 -0700 | [diff] [blame] | 138 | @Override |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 139 | public boolean matches(Object obj) { |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 140 | return !((CameraMetadataNative) obj).isEmpty(); |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 141 | } |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 142 | } |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 143 | |
| 144 | private void createDefaultSurface() { |
Zhijun He | 7b7a154 | 2013-09-25 16:33:35 -0700 | [diff] [blame] | 145 | mImageReader = |
| 146 | ImageReader.newInstance(DEFAULT_IMAGE_WIDTH, |
| 147 | DEFAULT_IMAGE_HEIGHT, |
| 148 | ImageFormat.YUV_420_888, |
| 149 | MAX_NUM_IMAGES); |
| 150 | mImageReader.setOnImageAvailableListener(new ImageDropperListener(), mHandler); |
| 151 | mSurface = mImageReader.getSurface(); |
Yin-Chia Yeh | 981e056 | 2015-03-12 13:39:26 -0700 | [diff] [blame^] | 152 | mOutputConfiguration = new OutputConfiguration(mSurface); |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 153 | } |
| 154 | |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 155 | private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception { |
| 156 | CameraMetadataNative metadata = new CameraMetadataNative(); |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 157 | assertTrue(metadata.isEmpty()); |
| 158 | |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 159 | int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata); |
| 160 | assertEquals(CameraBinderTestUtils.NO_ERROR, status); |
| 161 | assertFalse(metadata.isEmpty()); |
| 162 | |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 163 | CaptureRequest.Builder request = new CaptureRequest.Builder(metadata); |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 164 | assertFalse(request.isEmpty()); |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 165 | assertFalse(metadata.isEmpty()); |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 166 | if (needStream) { |
Yin-Chia Yeh | 981e056 | 2015-03-12 13:39:26 -0700 | [diff] [blame^] | 167 | int streamId = mCameraUser.createStream(mOutputConfiguration); |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 168 | assertEquals(0, streamId); |
| 169 | request.addTarget(mSurface); |
| 170 | } |
| 171 | return request; |
| 172 | } |
| 173 | |
| 174 | private int submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception { |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 175 | int requestId = mCameraUser.submitRequest(request, streaming, null); |
Igor Murashkin | 5c207ec | 2014-04-01 15:50:48 -0700 | [diff] [blame] | 176 | assertTrue( |
| 177 | "Request IDs should be non-negative (expected: >= 0, actual: " + requestId + ")", |
| 178 | requestId >= 0); |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 179 | return requestId; |
| 180 | } |
| 181 | |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 182 | @Override |
| 183 | protected void setUp() throws Exception { |
| 184 | super.setUp(); |
| 185 | |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 186 | /** |
| 187 | * Workaround for mockito and JB-MR2 incompatibility |
| 188 | * |
| 189 | * Avoid java.lang.IllegalArgumentException: dexcache == null |
| 190 | * https://code.google.com/p/dexmaker/issues/detail?id=2 |
| 191 | */ |
| 192 | System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString()); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 193 | mUtils = new CameraBinderTestUtils(getContext()); |
| 194 | |
| 195 | // This cannot be set in the constructor, since the onCreate isn't |
| 196 | // called yet |
| 197 | mCameraId = MediaFrameworkIntegrationTestRunner.mCameraId; |
| 198 | |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 199 | ICameraDeviceCallbacks.Stub dummyCallbacks = new DummyCameraDeviceCallbacks(); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 200 | |
| 201 | String clientPackageName = getContext().getPackageName(); |
| 202 | |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 203 | mMockCb = spy(dummyCallbacks); |
| 204 | |
Ruben Brunk | 66ef645 | 2013-08-08 13:05:30 -0700 | [diff] [blame] | 205 | BinderHolder holder = new BinderHolder(); |
| 206 | mUtils.getCameraService().connectDevice(mMockCb, mCameraId, |
| 207 | clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder); |
| 208 | mCameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder()); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 209 | assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser); |
Zhijun He | 7b7a154 | 2013-09-25 16:33:35 -0700 | [diff] [blame] | 210 | mHandlerThread = new HandlerThread(TAG); |
| 211 | mHandlerThread.start(); |
| 212 | mHandler = new Handler(mHandlerThread.getLooper()); |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 213 | createDefaultSurface(); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 214 | |
| 215 | Log.v(TAG, String.format("Camera %s connected", mCameraId)); |
| 216 | } |
| 217 | |
| 218 | @Override |
| 219 | protected void tearDown() throws Exception { |
| 220 | mCameraUser.disconnect(); |
| 221 | mCameraUser = null; |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 222 | mSurface.release(); |
Zhijun He | 7b7a154 | 2013-09-25 16:33:35 -0700 | [diff] [blame] | 223 | mImageReader.close(); |
| 224 | mHandlerThread.quitSafely(); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 225 | } |
| 226 | |
| 227 | @SmallTest |
| 228 | public void testCreateDefaultRequest() throws Exception { |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 229 | CameraMetadataNative metadata = new CameraMetadataNative(); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 230 | assertTrue(metadata.isEmpty()); |
| 231 | |
| 232 | int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata); |
| 233 | assertEquals(CameraBinderTestUtils.NO_ERROR, status); |
| 234 | assertFalse(metadata.isEmpty()); |
| 235 | |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 236 | } |
| 237 | |
| 238 | @SmallTest |
| 239 | public void testCreateStream() throws Exception { |
Yin-Chia Yeh | 981e056 | 2015-03-12 13:39:26 -0700 | [diff] [blame^] | 240 | int streamId = mCameraUser.createStream(mOutputConfiguration); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 241 | assertEquals(0, streamId); |
| 242 | |
| 243 | assertEquals(CameraBinderTestUtils.ALREADY_EXISTS, |
Yin-Chia Yeh | 981e056 | 2015-03-12 13:39:26 -0700 | [diff] [blame^] | 244 | mCameraUser.createStream(mOutputConfiguration)); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 245 | |
| 246 | assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId)); |
| 247 | } |
| 248 | |
| 249 | @SmallTest |
| 250 | public void testDeleteInvalidStream() throws Exception { |
| 251 | assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(-1)); |
| 252 | assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0)); |
| 253 | assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(1)); |
| 254 | assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0xC0FFEE)); |
| 255 | } |
| 256 | |
| 257 | @SmallTest |
| 258 | public void testCreateStreamTwo() throws Exception { |
| 259 | |
| 260 | // Create first stream |
Yin-Chia Yeh | 981e056 | 2015-03-12 13:39:26 -0700 | [diff] [blame^] | 261 | int streamId = mCameraUser.createStream(mOutputConfiguration); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 262 | assertEquals(0, streamId); |
| 263 | |
| 264 | assertEquals(CameraBinderTestUtils.ALREADY_EXISTS, |
Yin-Chia Yeh | 981e056 | 2015-03-12 13:39:26 -0700 | [diff] [blame^] | 265 | mCameraUser.createStream(mOutputConfiguration)); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 266 | |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 267 | // Create second stream with a different surface. |
| 268 | SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0); |
| 269 | surfaceTexture.setDefaultBufferSize(640, 480); |
| 270 | Surface surface2 = new Surface(surfaceTexture); |
Yin-Chia Yeh | 981e056 | 2015-03-12 13:39:26 -0700 | [diff] [blame^] | 271 | OutputConfiguration output2 = new OutputConfiguration(surface2); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 272 | |
Yin-Chia Yeh | 981e056 | 2015-03-12 13:39:26 -0700 | [diff] [blame^] | 273 | int streamId2 = mCameraUser.createStream(output2); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 274 | assertEquals(1, streamId2); |
| 275 | |
| 276 | // Clean up streams |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 277 | assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId)); |
| 278 | assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId2)); |
| 279 | } |
| 280 | |
| 281 | @SmallTest |
| 282 | public void testSubmitBadRequest() throws Exception { |
| 283 | |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 284 | CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */false); |
| 285 | CaptureRequest request1 = builder.build(); |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 286 | int status = mCameraUser.submitRequest(request1, /* streaming */false, null); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 287 | assertEquals("Expected submitRequest to return BAD_VALUE " + |
| 288 | "since we had 0 surface targets set.", CameraBinderTestUtils.BAD_VALUE, status); |
| 289 | |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 290 | builder.addTarget(mSurface); |
| 291 | CaptureRequest request2 = builder.build(); |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 292 | status = mCameraUser.submitRequest(request2, /* streaming */false, null); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 293 | assertEquals("Expected submitRequest to return BAD_VALUE since " + |
| 294 | "the target surface wasn't registered with createStream.", |
| 295 | CameraBinderTestUtils.BAD_VALUE, status); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 296 | } |
| 297 | |
| 298 | @SmallTest |
| 299 | public void testSubmitGoodRequest() throws Exception { |
| 300 | |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 301 | CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true); |
| 302 | CaptureRequest request = builder.build(); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 303 | |
| 304 | // Submit valid request twice. |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 305 | int requestId1 = submitCameraRequest(request, /* streaming */false); |
| 306 | int requestId2 = submitCameraRequest(request, /* streaming */false); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 307 | assertNotSame("Request IDs should be unique for multiple requests", requestId1, requestId2); |
| 308 | |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 309 | } |
| 310 | |
| 311 | @SmallTest |
| 312 | public void testSubmitStreamingRequest() throws Exception { |
| 313 | |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 314 | CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true); |
| 315 | |
| 316 | CaptureRequest request = builder.build(); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 317 | |
| 318 | // Submit valid request once (non-streaming), and another time |
| 319 | // (streaming) |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 320 | int requestId1 = submitCameraRequest(request, /* streaming */false); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 321 | |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 322 | int requestIdStreaming = submitCameraRequest(request, /* streaming */true); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 323 | assertNotSame("Request IDs should be unique for multiple requests", requestId1, |
| 324 | requestIdStreaming); |
| 325 | |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 326 | int status = mCameraUser.cancelRequest(-1, null); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 327 | assertEquals("Invalid request IDs should not be cancellable", |
| 328 | CameraBinderTestUtils.BAD_VALUE, status); |
| 329 | |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 330 | status = mCameraUser.cancelRequest(requestId1, null); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 331 | assertEquals("Non-streaming request IDs should not be cancellable", |
| 332 | CameraBinderTestUtils.BAD_VALUE, status); |
| 333 | |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 334 | status = mCameraUser.cancelRequest(requestIdStreaming, null); |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 335 | assertEquals("Streaming request IDs should be cancellable", CameraBinderTestUtils.NO_ERROR, |
| 336 | status); |
| 337 | |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 338 | } |
Igor Murashkin | d7bf177 | 2013-07-12 18:01:31 -0700 | [diff] [blame] | 339 | |
| 340 | @SmallTest |
| 341 | public void testCameraInfo() throws RemoteException { |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 342 | CameraMetadataNative info = new CameraMetadataNative(); |
Igor Murashkin | d7bf177 | 2013-07-12 18:01:31 -0700 | [diff] [blame] | 343 | |
| 344 | int status = mCameraUser.getCameraInfo(/*out*/info); |
| 345 | assertEquals(CameraBinderTestUtils.NO_ERROR, status); |
| 346 | |
| 347 | assertFalse(info.isEmpty()); |
Igor Murashkin | 68f4006 | 2013-09-10 12:15:54 -0700 | [diff] [blame] | 348 | assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS)); |
Igor Murashkin | d7bf177 | 2013-07-12 18:01:31 -0700 | [diff] [blame] | 349 | } |
| 350 | |
Zhijun He | 7f4d314 | 2013-07-23 07:54:38 -0700 | [diff] [blame] | 351 | @SmallTest |
Zhijun He | 2001188 | 2013-09-25 10:05:59 -0700 | [diff] [blame] | 352 | public void testCameraCharacteristics() throws RemoteException { |
| 353 | CameraMetadataNative info = new CameraMetadataNative(); |
| 354 | |
| 355 | int status = mUtils.getCameraService().getCameraCharacteristics(mCameraId, /*out*/info); |
| 356 | assertEquals(CameraBinderTestUtils.NO_ERROR, status); |
| 357 | |
| 358 | assertFalse(info.isEmpty()); |
| 359 | assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS)); |
| 360 | } |
| 361 | |
| 362 | @SmallTest |
Zhijun He | 7f4d314 | 2013-07-23 07:54:38 -0700 | [diff] [blame] | 363 | public void testWaitUntilIdle() throws Exception { |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 364 | CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true); |
| 365 | int requestIdStreaming = submitCameraRequest(builder.build(), /* streaming */true); |
Zhijun He | 7f4d314 | 2013-07-23 07:54:38 -0700 | [diff] [blame] | 366 | |
| 367 | // Test Bad case first: waitUntilIdle when there is active repeating request |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 368 | int status = mCameraUser.waitUntilIdle(); |
Zhijun He | 7f4d314 | 2013-07-23 07:54:38 -0700 | [diff] [blame] | 369 | assertEquals("waitUntilIdle is invalid operation when there is active repeating request", |
| 370 | CameraBinderTestUtils.INVALID_OPERATION, status); |
| 371 | |
| 372 | // Test good case, waitUntilIdle when there is no active repeating request |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 373 | status = mCameraUser.cancelRequest(requestIdStreaming, null); |
Zhijun He | 7f4d314 | 2013-07-23 07:54:38 -0700 | [diff] [blame] | 374 | assertEquals(CameraBinderTestUtils.NO_ERROR, status); |
| 375 | status = mCameraUser.waitUntilIdle(); |
| 376 | assertEquals(CameraBinderTestUtils.NO_ERROR, status); |
| 377 | } |
| 378 | |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 379 | @SmallTest |
| 380 | public void testCaptureResultCallbacks() throws Exception { |
| 381 | IsMetadataNotEmpty matcher = new IsMetadataNotEmpty(); |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 382 | CaptureRequest request = createDefaultBuilder(/* needStream */true).build(); |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 383 | |
| 384 | // Test both single request and streaming request. |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 385 | verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onResultReceived( |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 386 | argThat(matcher), |
| 387 | any(CaptureResultExtras.class)); |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 388 | |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 389 | verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED)) |
| 390 | .onResultReceived( |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 391 | argThat(matcher), |
| 392 | any(CaptureResultExtras.class)); |
Zhijun He | 693e21d | 2013-07-31 14:16:14 -0700 | [diff] [blame] | 393 | } |
Eino-Ville Talvala | 8ebd52b | 2013-08-13 12:09:44 -0700 | [diff] [blame] | 394 | |
| 395 | @SmallTest |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 396 | public void testCaptureStartedCallbacks() throws Exception { |
| 397 | CaptureRequest request = createDefaultBuilder(/* needStream */true).build(); |
| 398 | |
| 399 | ArgumentCaptor<Long> timestamps = ArgumentCaptor.forClass(Long.class); |
| 400 | |
| 401 | // Test both single request and streaming request. |
| 402 | int requestId1 = submitCameraRequest(request, /* streaming */false); |
| 403 | verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onCaptureStarted( |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 404 | any(CaptureResultExtras.class), |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 405 | anyLong()); |
| 406 | |
| 407 | int streamingId = submitCameraRequest(request, /* streaming */true); |
| 408 | verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED)) |
| 409 | .onCaptureStarted( |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 410 | any(CaptureResultExtras.class), |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 411 | timestamps.capture()); |
| 412 | |
| 413 | long timestamp = 0; // All timestamps should be larger than 0. |
| 414 | for (Long nextTimestamp : timestamps.getAllValues()) { |
| 415 | Log.v(TAG, "next t: " + nextTimestamp + " current t: " + timestamp); |
| 416 | assertTrue("Captures are out of order", timestamp < nextTimestamp); |
| 417 | timestamp = nextTimestamp; |
| 418 | } |
| 419 | } |
| 420 | |
| 421 | @SmallTest |
| 422 | public void testIdleCallback() throws Exception { |
| 423 | int status; |
| 424 | CaptureRequest request = createDefaultBuilder(/* needStream */true).build(); |
| 425 | |
| 426 | // Try streaming |
| 427 | int streamingId = submitCameraRequest(request, /* streaming */true); |
| 428 | |
| 429 | // Wait a bit to fill up the queue |
| 430 | SystemClock.sleep(WAIT_FOR_WORK_MS); |
| 431 | |
| 432 | // Cancel and make sure we eventually quiesce |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 433 | status = mCameraUser.cancelRequest(streamingId, null); |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 434 | |
Eino-Ville Talvala | acc0095 | 2014-08-06 14:31:08 -0700 | [diff] [blame] | 435 | verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(1)).onDeviceIdle(); |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 436 | |
| 437 | // Submit a few capture requests |
| 438 | int requestId1 = submitCameraRequest(request, /* streaming */false); |
| 439 | int requestId2 = submitCameraRequest(request, /* streaming */false); |
| 440 | int requestId3 = submitCameraRequest(request, /* streaming */false); |
| 441 | int requestId4 = submitCameraRequest(request, /* streaming */false); |
| 442 | int requestId5 = submitCameraRequest(request, /* streaming */false); |
| 443 | |
| 444 | // And wait for more idle |
Eino-Ville Talvala | acc0095 | 2014-08-06 14:31:08 -0700 | [diff] [blame] | 445 | verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(2)).onDeviceIdle(); |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 446 | |
| 447 | } |
| 448 | |
| 449 | @SmallTest |
Eino-Ville Talvala | 8ebd52b | 2013-08-13 12:09:44 -0700 | [diff] [blame] | 450 | public void testFlush() throws Exception { |
| 451 | int status; |
| 452 | |
| 453 | // Initial flush should work |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 454 | status = mCameraUser.flush(null); |
Eino-Ville Talvala | 8ebd52b | 2013-08-13 12:09:44 -0700 | [diff] [blame] | 455 | assertEquals(CameraBinderTestUtils.NO_ERROR, status); |
| 456 | |
| 457 | // Then set up a stream |
Eino-Ville Talvala | 70c2207 | 2013-08-27 12:09:04 -0700 | [diff] [blame] | 458 | CaptureRequest request = createDefaultBuilder(/* needStream */true).build(); |
Eino-Ville Talvala | 8ebd52b | 2013-08-13 12:09:44 -0700 | [diff] [blame] | 459 | |
| 460 | // Flush should still be a no-op, really |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 461 | status = mCameraUser.flush(null); |
Eino-Ville Talvala | 8ebd52b | 2013-08-13 12:09:44 -0700 | [diff] [blame] | 462 | assertEquals(CameraBinderTestUtils.NO_ERROR, status); |
| 463 | |
| 464 | // Submit a few capture requests |
| 465 | int requestId1 = submitCameraRequest(request, /* streaming */false); |
| 466 | int requestId2 = submitCameraRequest(request, /* streaming */false); |
| 467 | int requestId3 = submitCameraRequest(request, /* streaming */false); |
| 468 | int requestId4 = submitCameraRequest(request, /* streaming */false); |
| 469 | int requestId5 = submitCameraRequest(request, /* streaming */false); |
| 470 | |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 471 | // Then flush and wait for idle |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 472 | status = mCameraUser.flush(null); |
Eino-Ville Talvala | 8ebd52b | 2013-08-13 12:09:44 -0700 | [diff] [blame] | 473 | assertEquals(CameraBinderTestUtils.NO_ERROR, status); |
| 474 | |
Eino-Ville Talvala | acc0095 | 2014-08-06 14:31:08 -0700 | [diff] [blame] | 475 | verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(1)).onDeviceIdle(); |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 476 | |
| 477 | // Now a streaming request |
| 478 | int streamingId = submitCameraRequest(request, /* streaming */true); |
| 479 | |
| 480 | // Wait a bit to fill up the queue |
| 481 | SystemClock.sleep(WAIT_FOR_WORK_MS); |
| 482 | |
| 483 | // Then flush and wait for the idle callback |
Zhijun He | 438d77e | 2014-04-10 17:09:22 -0700 | [diff] [blame] | 484 | status = mCameraUser.flush(null); |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 485 | assertEquals(CameraBinderTestUtils.NO_ERROR, status); |
| 486 | |
Eino-Ville Talvala | acc0095 | 2014-08-06 14:31:08 -0700 | [diff] [blame] | 487 | verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(2)).onDeviceIdle(); |
Eino-Ville Talvala | e841d4e | 2013-09-05 09:04:08 -0700 | [diff] [blame] | 488 | |
Eino-Ville Talvala | 8ebd52b | 2013-08-13 12:09:44 -0700 | [diff] [blame] | 489 | // TODO: When errors are hooked up, count that errors + successful |
| 490 | // requests equal to 5. |
| 491 | } |
Igor Murashkin | 7072550 | 2013-06-25 20:27:06 +0000 | [diff] [blame] | 492 | } |