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