CameraDeviceBinderTest.java revision 70c2207c34cf0e6b3b383b1b1500ff5385aa51a6
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 17package com.android.mediaframeworktest.integration; 18 19import android.graphics.SurfaceTexture; 20import android.hardware.camera2.CameraMetadata; 21import android.hardware.camera2.CameraProperties; 22import android.hardware.camera2.CaptureRequest; 23import android.hardware.camera2.ICameraDeviceCallbacks; 24import android.hardware.camera2.ICameraDeviceUser; 25import android.hardware.camera2.impl.CameraMetadataNative; 26import android.hardware.camera2.utils.BinderHolder; 27import android.os.RemoteException; 28import android.test.AndroidTestCase; 29import android.test.suitebuilder.annotation.SmallTest; 30import android.util.Log; 31import android.view.Surface; 32 33import static android.hardware.camera2.CameraDevice.TEMPLATE_PREVIEW; 34 35import com.android.mediaframeworktest.MediaFrameworkIntegrationTestRunner; 36 37import org.mockito.ArgumentMatcher; 38import static org.mockito.Mockito.*; 39 40public class CameraDeviceBinderTest extends AndroidTestCase { 41 private static String TAG = "CameraDeviceBinderTest"; 42 // Number of streaming callbacks need to check. 43 private static int NUM_CALLBACKS_CHECKED = 10; 44 // Wait for capture result timeout value: 1500ms 45 private final static int WAIT_FOR_COMPLETE_TIMEOUT_MS = 1500; 46 47 private int mCameraId; 48 private ICameraDeviceUser mCameraUser; 49 private CameraBinderTestUtils mUtils; 50 private ICameraDeviceCallbacks.Stub mMockCb; 51 private Surface mSurface; 52 // Need hold a Surfacetexture reference during a test execution, otherwise, 53 // it could be GCed during a test, which causes camera run into bad state. 54 private SurfaceTexture mSurfaceTexture; 55 56 public CameraDeviceBinderTest() { 57 } 58 59 public class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub { 60 61 @Override 62 public void notifyCallback(int msgType, int ext1, int ext2) throws RemoteException { 63 } 64 65 @Override 66 public void onResultReceived(int frameId, CameraMetadataNative result) throws RemoteException { 67 } 68 } 69 70 class IsMetadataNotEmpty extends ArgumentMatcher<CameraMetadataNative> { 71 public boolean matches(Object obj) { 72 return !((CameraMetadataNative) obj).isEmpty(); 73 } 74 } 75 76 private void createDefaultSurface() { 77 mSurfaceTexture = new SurfaceTexture(/* ignored */0); 78 mSurfaceTexture.setDefaultBufferSize(640, 480); 79 mSurface = new Surface(mSurfaceTexture); 80 } 81 82 private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception { 83 CameraMetadataNative metadata = new CameraMetadataNative(); 84 assertTrue(metadata.isEmpty()); 85 86 int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata); 87 assertEquals(CameraBinderTestUtils.NO_ERROR, status); 88 assertFalse(metadata.isEmpty()); 89 90 CaptureRequest.Builder request = new CaptureRequest.Builder(metadata); 91 assertFalse(request.isEmpty()); 92 assertFalse(metadata.isEmpty()); 93 if (needStream) { 94 int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20, 95 /* ignored */30, mSurface); 96 assertEquals(0, streamId); 97 request.addTarget(mSurface); 98 } 99 return request; 100 } 101 102 private int submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception { 103 int requestId = mCameraUser.submitRequest(request, streaming); 104 assertTrue("Request IDs should be non-negative", requestId >= 0); 105 return requestId; 106 } 107 108 @Override 109 protected void setUp() throws Exception { 110 super.setUp(); 111 112 /** 113 * Workaround for mockito and JB-MR2 incompatibility 114 * 115 * Avoid java.lang.IllegalArgumentException: dexcache == null 116 * https://code.google.com/p/dexmaker/issues/detail?id=2 117 */ 118 System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString()); 119 mUtils = new CameraBinderTestUtils(getContext()); 120 121 // This cannot be set in the constructor, since the onCreate isn't 122 // called yet 123 mCameraId = MediaFrameworkIntegrationTestRunner.mCameraId; 124 125 ICameraDeviceCallbacks.Stub dummyCallbacks = new DummyCameraDeviceCallbacks(); 126 127 String clientPackageName = getContext().getPackageName(); 128 129 mMockCb = spy(dummyCallbacks); 130 131 BinderHolder holder = new BinderHolder(); 132 mUtils.getCameraService().connectDevice(mMockCb, mCameraId, 133 clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder); 134 mCameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder()); 135 assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser); 136 createDefaultSurface(); 137 138 Log.v(TAG, String.format("Camera %s connected", mCameraId)); 139 } 140 141 @Override 142 protected void tearDown() throws Exception { 143 mCameraUser.disconnect(); 144 mCameraUser = null; 145 mSurface.release(); 146 mSurfaceTexture.release(); 147 } 148 149 @SmallTest 150 public void testCreateDefaultRequest() throws Exception { 151 CameraMetadataNative metadata = new CameraMetadataNative(); 152 assertTrue(metadata.isEmpty()); 153 154 int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata); 155 assertEquals(CameraBinderTestUtils.NO_ERROR, status); 156 assertFalse(metadata.isEmpty()); 157 158 } 159 160 @SmallTest 161 public void testCreateStream() throws Exception { 162 int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20, /* ignored */30, 163 mSurface); 164 assertEquals(0, streamId); 165 166 assertEquals(CameraBinderTestUtils.ALREADY_EXISTS, 167 mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0, mSurface)); 168 169 assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId)); 170 } 171 172 @SmallTest 173 public void testDeleteInvalidStream() throws Exception { 174 assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(-1)); 175 assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0)); 176 assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(1)); 177 assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0xC0FFEE)); 178 } 179 180 @SmallTest 181 public void testCreateStreamTwo() throws Exception { 182 183 // Create first stream 184 int streamId = mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0, 185 mSurface); 186 assertEquals(0, streamId); 187 188 assertEquals(CameraBinderTestUtils.ALREADY_EXISTS, 189 mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0, mSurface)); 190 191 // Create second stream with a different surface. 192 SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0); 193 surfaceTexture.setDefaultBufferSize(640, 480); 194 Surface surface2 = new Surface(surfaceTexture); 195 196 int streamId2 = mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0, 197 surface2); 198 assertEquals(1, streamId2); 199 200 // Clean up streams 201 assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId)); 202 assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId2)); 203 } 204 205 @SmallTest 206 public void testSubmitBadRequest() throws Exception { 207 208 CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */false); 209 CaptureRequest request1 = builder.build(); 210 int status = mCameraUser.submitRequest(request1, /* streaming */false); 211 assertEquals("Expected submitRequest to return BAD_VALUE " + 212 "since we had 0 surface targets set.", CameraBinderTestUtils.BAD_VALUE, status); 213 214 builder.addTarget(mSurface); 215 CaptureRequest request2 = builder.build(); 216 status = mCameraUser.submitRequest(request2, /* streaming */false); 217 assertEquals("Expected submitRequest to return BAD_VALUE since " + 218 "the target surface wasn't registered with createStream.", 219 CameraBinderTestUtils.BAD_VALUE, status); 220 } 221 222 @SmallTest 223 public void testSubmitGoodRequest() throws Exception { 224 225 CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true); 226 CaptureRequest request = builder.build(); 227 228 // Submit valid request twice. 229 int requestId1 = submitCameraRequest(request, /* streaming */false); 230 int requestId2 = submitCameraRequest(request, /* streaming */false); 231 assertNotSame("Request IDs should be unique for multiple requests", requestId1, requestId2); 232 233 } 234 235 @SmallTest 236 public void testSubmitStreamingRequest() throws Exception { 237 238 CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true); 239 240 CaptureRequest request = builder.build(); 241 242 // Submit valid request once (non-streaming), and another time 243 // (streaming) 244 int requestId1 = submitCameraRequest(request, /* streaming */false); 245 246 int requestIdStreaming = submitCameraRequest(request, /* streaming */true); 247 assertNotSame("Request IDs should be unique for multiple requests", requestId1, 248 requestIdStreaming); 249 250 int status = mCameraUser.cancelRequest(-1); 251 assertEquals("Invalid request IDs should not be cancellable", 252 CameraBinderTestUtils.BAD_VALUE, status); 253 254 status = mCameraUser.cancelRequest(requestId1); 255 assertEquals("Non-streaming request IDs should not be cancellable", 256 CameraBinderTestUtils.BAD_VALUE, status); 257 258 status = mCameraUser.cancelRequest(requestIdStreaming); 259 assertEquals("Streaming request IDs should be cancellable", CameraBinderTestUtils.NO_ERROR, 260 status); 261 262 } 263 264 @SmallTest 265 public void testCameraInfo() throws RemoteException { 266 CameraMetadataNative info = new CameraMetadataNative(); 267 268 int status = mCameraUser.getCameraInfo(/*out*/info); 269 assertEquals(CameraBinderTestUtils.NO_ERROR, status); 270 271 assertFalse(info.isEmpty()); 272 assertNotNull(info.get(CameraProperties.SCALER_AVAILABLE_FORMATS)); 273 } 274 275 @SmallTest 276 public void testWaitUntilIdle() throws Exception { 277 CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true); 278 int requestIdStreaming = submitCameraRequest(builder.build(), /* streaming */true); 279 280 // Test Bad case first: waitUntilIdle when there is active repeating request 281 int status = mCameraUser.waitUntilIdle(); 282 assertEquals("waitUntilIdle is invalid operation when there is active repeating request", 283 CameraBinderTestUtils.INVALID_OPERATION, status); 284 285 // Test good case, waitUntilIdle when there is no active repeating request 286 status = mCameraUser.cancelRequest(requestIdStreaming); 287 assertEquals(CameraBinderTestUtils.NO_ERROR, status); 288 status = mCameraUser.waitUntilIdle(); 289 assertEquals(CameraBinderTestUtils.NO_ERROR, status); 290 } 291 292 @SmallTest 293 public void testCaptureResultCallbacks() throws Exception { 294 IsMetadataNotEmpty matcher = new IsMetadataNotEmpty(); 295 CaptureRequest request = createDefaultBuilder(/* needStream */true).build(); 296 297 // Test both single request and streaming request. 298 int requestId1 = submitCameraRequest(request, /* streaming */false); 299 verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onResultReceived( 300 eq(requestId1), 301 argThat(matcher)); 302 303 int streamingId = submitCameraRequest(request, /* streaming */true); 304 verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED)) 305 .onResultReceived( 306 eq(streamingId), 307 argThat(matcher)); 308 } 309 310 @SmallTest 311 public void testFlush() throws Exception { 312 int status; 313 314 // Initial flush should work 315 status = mCameraUser.flush(); 316 assertEquals(CameraBinderTestUtils.NO_ERROR, status); 317 318 // Then set up a stream 319 CaptureRequest request = createDefaultBuilder(/* needStream */true).build(); 320 321 // Flush should still be a no-op, really 322 status = mCameraUser.flush(); 323 assertEquals(CameraBinderTestUtils.NO_ERROR, status); 324 325 // Submit a few capture requests 326 int requestId1 = submitCameraRequest(request, /* streaming */false); 327 int requestId2 = submitCameraRequest(request, /* streaming */false); 328 int requestId3 = submitCameraRequest(request, /* streaming */false); 329 int requestId4 = submitCameraRequest(request, /* streaming */false); 330 int requestId5 = submitCameraRequest(request, /* streaming */false); 331 332 // Then flush 333 status = mCameraUser.flush(); 334 assertEquals(CameraBinderTestUtils.NO_ERROR, status); 335 336 // TODO: When errors are hooked up, count that errors + successful 337 // requests equal to 5. 338 } 339} 340