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 19 import android.hardware.CameraInfo; 20 import android.hardware.ICamera; 21 import android.hardware.ICameraClient; 22 import android.hardware.ICameraService; 23 import android.hardware.ICameraServiceListener; 24 import android.hardware.camera2.ICameraDeviceCallbacks; 25 import android.hardware.camera2.ICameraDeviceUser; 26 import android.hardware.camera2.impl.CameraMetadataNative; 27 import android.hardware.camera2.impl.CaptureResultExtras; 28 import android.hardware.camera2.impl.PhysicalCaptureResultInfo; 29 import android.os.Binder; 30 import android.os.IBinder; 31 import android.os.RemoteException; 32 import android.os.ServiceSpecificException; 33 import android.test.AndroidTestCase; 34 import android.test.suitebuilder.annotation.SmallTest; 35 import android.util.Log; 36 37 /** 38 * <p> 39 * Junit / Instrumentation test case for the camera2 api 40 * </p> 41 * <p> 42 * To run only tests in this class: 43 * </p> 44 * 45 * <pre> 46 * adb shell am instrument \ 47 * -e class com.android.mediaframeworktest.integration.CameraBinderTest \ 48 * -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner 49 * </pre> 50 */ 51 public class CameraBinderTest extends AndroidTestCase { 52 private static final int MAX_PARAMETERS_LENGTH = 100; 53 54 static String TAG = "CameraBinderTest"; 55 56 // From ICameraService.h 57 private static final int API_VERSION_1 = 1; 58 private static final int API_VERSION_2 = 2; 59 60 private static final int CAMERA_TYPE_BACKWARD_COMPATIBLE = 0; 61 private static final int CAMERA_TYPE_ALL = 1; 62 63 protected CameraBinderTestUtils mUtils; 64 65 public CameraBinderTest() { 66 } 67 68 @Override 69 protected void setUp() throws Exception { 70 super.setUp(); 71 72 mUtils = new CameraBinderTestUtils(getContext()); 73 } 74 75 @SmallTest 76 public void testNumberOfCameras() throws Exception { 77 78 int numCameras = mUtils.getCameraService().getNumberOfCameras(CAMERA_TYPE_ALL); 79 assertTrue("At least this many cameras: " + mUtils.getGuessedNumCameras(), 80 numCameras >= mUtils.getGuessedNumCameras()); 81 Log.v(TAG, "Number of cameras " + numCameras); 82 } 83 84 @SmallTest 85 public void testCameraInfo() throws Exception { 86 for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { 87 88 CameraInfo info = mUtils.getCameraService().getCameraInfo(cameraId); 89 assertTrue("Facing was not set for camera " + cameraId, info.info.facing != -1); 90 assertTrue("Orientation was not set for camera " + cameraId, 91 info.info.orientation != -1); 92 93 Log.v(TAG, "Camera " + cameraId + " info: facing " + info.info.facing 94 + ", orientation " + info.info.orientation); 95 } 96 } 97 98 @SmallTest 99 public void testGetLegacyParameters() throws Exception { 100 for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { 101 102 String parameters = mUtils.getCameraService().getLegacyParameters(cameraId); 103 assertNotNull(parameters); 104 assertTrue("Parameters should have at least one character in it", 105 parameters.length() > 0); 106 107 int end = parameters.length(); 108 if (end > MAX_PARAMETERS_LENGTH) { 109 end = MAX_PARAMETERS_LENGTH; 110 } 111 112 Log.v(TAG, "Camera " + cameraId + " parameters: " + parameters.substring(0, end)); 113 } 114 } 115 116 /** The camera2 api is only supported on HAL3.2+ devices */ 117 @SmallTest 118 public void testSupportsCamera2Api() throws Exception { 119 for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { 120 boolean supports = mUtils.getCameraService().supportsCameraApi( 121 String.valueOf(cameraId), API_VERSION_2); 122 123 Log.v(TAG, "Camera " + cameraId + " supports api2: " + supports); 124 } 125 } 126 127 /** The camera1 api is supported on *all* devices regardless of HAL version */ 128 @SmallTest 129 public void testSupportsCamera1Api() throws Exception { 130 for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { 131 132 boolean supports = mUtils.getCameraService().supportsCameraApi( 133 String.valueOf(cameraId), API_VERSION_1); 134 assertTrue( 135 "Camera service returned false when queried if it supports camera1 api " + 136 " for camera ID " + cameraId, supports); 137 } 138 } 139 140 static abstract class DummyBase extends Binder implements android.os.IInterface { 141 @Override 142 public IBinder asBinder() { 143 return this; 144 } 145 } 146 147 static class DummyCameraClient extends DummyBase implements ICameraClient { 148 } 149 150 @SmallTest 151 public void testConnect() throws Exception { 152 for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { 153 154 ICameraClient dummyCallbacks = new DummyCameraClient(); 155 156 String clientPackageName = getContext().getPackageName(); 157 158 ICamera cameraUser = mUtils.getCameraService() 159 .connect(dummyCallbacks, cameraId, clientPackageName, 160 ICameraService.USE_CALLING_UID, 161 ICameraService.USE_CALLING_PID); 162 assertNotNull(String.format("Camera %s was null", cameraId), cameraUser); 163 164 Log.v(TAG, String.format("Camera %s connected", cameraId)); 165 166 cameraUser.disconnect(); 167 } 168 } 169 170 @SmallTest 171 public void testConnectLegacy() throws Exception { 172 final int CAMERA_HAL_API_VERSION_1_0 = 0x100; 173 for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { 174 ICamera cameraUser = null; 175 ICameraClient dummyCallbacks = new DummyCameraClient(); 176 177 String clientPackageName = getContext().getPackageName(); 178 179 try { 180 cameraUser = mUtils.getCameraService() 181 .connectLegacy(dummyCallbacks, cameraId, CAMERA_HAL_API_VERSION_1_0, 182 clientPackageName, 183 ICameraService.USE_CALLING_UID); 184 assertNotNull(String.format("Camera %s was null", cameraId), cameraUser); 185 186 Log.v(TAG, String.format("Camera %s connected as HAL1 legacy device", cameraId)); 187 } catch (RuntimeException e) { 188 // Not all camera device support openLegacy. 189 Log.i(TAG, "Unable to open camera as HAL1 legacy camera device " + e); 190 } finally { 191 if (cameraUser != null) { 192 cameraUser.disconnect(); 193 } 194 } 195 } 196 } 197 198 static class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub { 199 200 /* 201 * (non-Javadoc) 202 * @see 203 * android.hardware.camera2.ICameraDeviceCallbacks#onCameraError(int, 204 * android.hardware.camera2.CaptureResultExtras) 205 */ 206 @Override 207 public void onDeviceError(int errorCode, CaptureResultExtras resultExtras) 208 throws RemoteException { 209 // TODO Auto-generated method stub 210 211 } 212 213 /* 214 * (non-Javadoc) 215 * @see 216 * android.hardware.camera2.ICameraDeviceCallbacks#onCaptureStarted( 217 * android.hardware.camera2.CaptureResultExtras, long) 218 */ 219 @Override 220 public void onCaptureStarted(CaptureResultExtras resultExtras, long timestamp) 221 throws RemoteException { 222 // TODO Auto-generated method stub 223 224 } 225 226 /* 227 * (non-Javadoc) 228 * @see 229 * android.hardware.camera2.ICameraDeviceCallbacks#onResultReceived( 230 * android.hardware.camera2.impl.CameraMetadataNative, 231 * android.hardware.camera2.CaptureResultExtras) 232 */ 233 @Override 234 public void onResultReceived(CameraMetadataNative result, CaptureResultExtras resultExtras, 235 PhysicalCaptureResultInfo physicalResults[]) throws RemoteException { 236 // TODO Auto-generated method stub 237 238 } 239 240 /* 241 * (non-Javadoc) 242 * @see android.hardware.camera2.ICameraDeviceCallbacks#onCameraIdle() 243 */ 244 @Override 245 public void onDeviceIdle() throws RemoteException { 246 // TODO Auto-generated method stub 247 248 } 249 250 /* 251 * (non-Javadoc) 252 * @see android.hardware.camera2.ICameraDeviceCallbacks#onPrepared() 253 */ 254 @Override 255 public void onPrepared(int streamId) throws RemoteException { 256 // TODO Auto-generated method stub 257 258 } 259 260 /* 261 * (non-Javadoc) 262 * @see android.hardware.camera2.ICameraDeviceCallbacks#onRequestQueueEmpty() 263 */ 264 @Override 265 public void onRequestQueueEmpty() throws RemoteException { 266 // TODO Auto-generated method stub 267 268 } 269 270 /* 271 * (non-Javadoc) 272 * @see android.hardware.camera2.ICameraDeviceCallbacks#onRepeatingRequestError() 273 */ 274 @Override 275 public void onRepeatingRequestError(long lastFrameNumber, int repeatingRequestId) { 276 // TODO Auto-generated method stub 277 } 278 } 279 280 @SmallTest 281 public void testConnectDevice() throws Exception { 282 for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { 283 284 ICameraDeviceCallbacks dummyCallbacks = new DummyCameraDeviceCallbacks(); 285 286 String clientPackageName = getContext().getPackageName(); 287 288 ICameraDeviceUser cameraUser = 289 mUtils.getCameraService().connectDevice( 290 dummyCallbacks, String.valueOf(cameraId), 291 clientPackageName, 292 ICameraService.USE_CALLING_UID); 293 assertNotNull(String.format("Camera %s was null", cameraId), cameraUser); 294 295 Log.v(TAG, String.format("Camera %s connected", cameraId)); 296 297 cameraUser.disconnect(); 298 } 299 } 300 301 static class DummyCameraServiceListener extends ICameraServiceListener.Stub { 302 @Override 303 public void onStatusChanged(int status, String cameraId) 304 throws RemoteException { 305 Log.v(TAG, String.format("Camera %s has status changed to 0x%x", cameraId, status)); 306 } 307 public void onTorchStatusChanged(int status, String cameraId) 308 throws RemoteException { 309 Log.v(TAG, String.format("Camera %s has torch status changed to 0x%x", 310 cameraId, status)); 311 } 312 } 313 314 /** 315 * <pre> 316 * adb shell am instrument \ 317 * -e class 'com.android.mediaframeworktest.integration.CameraBinderTest#testAddRemoveListeners' \ 318 * -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner 319 * </pre> 320 */ 321 @SmallTest 322 public void testAddRemoveListeners() throws Exception { 323 for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) { 324 325 ICameraServiceListener listener = new DummyCameraServiceListener(); 326 327 try { 328 mUtils.getCameraService().removeListener(listener); 329 fail("Listener was removed before added"); 330 } catch (ServiceSpecificException e) { 331 assertEquals("Listener was removed before added", 332 e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT); 333 } 334 335 mUtils.getCameraService().addListener(listener); 336 337 try { 338 mUtils.getCameraService().addListener(listener); 339 fail("Listener was wrongly added again"); 340 } catch (ServiceSpecificException e) { 341 assertEquals("Listener was wrongly added again", 342 e.errorCode, ICameraService.ERROR_ALREADY_EXISTS); 343 } 344 345 mUtils.getCameraService().removeListener(listener); 346 347 try { 348 mUtils.getCameraService().removeListener(listener); 349 fail("Listener was wrongly removed twice"); 350 } catch (ServiceSpecificException e) { 351 assertEquals("Listener was wrongly removed twice", 352 e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT); 353 } 354 } 355 } 356 } 357