1 package org.robolectric.shadows; 2 3 import static com.google.common.truth.Truth.assertThat; 4 import static java.nio.charset.StandardCharsets.UTF_8; 5 import static org.junit.Assert.fail; 6 7 import android.graphics.Canvas; 8 import android.graphics.ImageFormat; 9 import android.graphics.Rect; 10 import android.hardware.Camera; 11 import android.view.Surface; 12 import android.view.SurfaceHolder; 13 import androidx.test.ext.junit.runners.AndroidJUnit4; 14 import org.junit.After; 15 import org.junit.Before; 16 import org.junit.Test; 17 import org.junit.runner.RunWith; 18 import org.robolectric.Shadows; 19 20 @RunWith(AndroidJUnit4.class) 21 public class ShadowCameraTest { 22 23 private Camera camera; 24 private ShadowCamera shadowCamera; 25 26 @Before setUp()27 public void setUp() throws Exception { 28 camera = Camera.open(); 29 shadowCamera = Shadows.shadowOf(camera); 30 } 31 32 @After tearDown()33 public void tearDown() { 34 ShadowCamera.clearCameraInfo(); 35 } 36 37 @Test testOpen()38 public void testOpen() { 39 assertThat(camera).isNotNull(); 40 assertThat(ShadowCamera.getLastOpenedCameraId()).isEqualTo(0); 41 } 42 43 @Test testOpenWithId()44 public void testOpenWithId() { 45 camera = Camera.open(12); 46 assertThat(camera).isNotNull(); 47 assertThat(ShadowCamera.getLastOpenedCameraId()).isEqualTo(12); 48 } 49 50 @Test testUnlock()51 public void testUnlock() { 52 assertThat(shadowCamera.isLocked()).isTrue(); 53 camera.unlock(); 54 assertThat(shadowCamera.isLocked()).isFalse(); 55 } 56 57 @Test testReconnect()58 public void testReconnect() throws Exception { 59 camera.unlock(); 60 assertThat(shadowCamera.isLocked()).isFalse(); 61 camera.reconnect(); 62 assertThat(shadowCamera.isLocked()).isTrue(); 63 } 64 65 @Test testGetParameters()66 public void testGetParameters() { 67 Camera.Parameters parameters = camera.getParameters(); 68 assertThat(parameters).isNotNull(); 69 assertThat(parameters.getSupportedPreviewFormats()).isNotNull(); 70 assertThat(parameters.getSupportedPreviewFormats().size()).isNotEqualTo(0); 71 } 72 73 @Test testSetParameters()74 public void testSetParameters() { 75 Camera.Parameters parameters = camera.getParameters(); 76 assertThat(parameters.getPreviewFormat()).isEqualTo(ImageFormat.NV21); 77 parameters.setPreviewFormat(ImageFormat.JPEG); 78 camera.setParameters(parameters); 79 assertThat(camera.getParameters().getPreviewFormat()).isEqualTo(ImageFormat.JPEG); 80 } 81 82 @Test testSetPreviewDisplay()83 public void testSetPreviewDisplay() throws Exception { 84 SurfaceHolder previewSurfaceHolder = new TestSurfaceHolder(); 85 camera.setPreviewDisplay(previewSurfaceHolder); 86 assertThat(shadowCamera.getPreviewDisplay()).isSameInstanceAs(previewSurfaceHolder); 87 } 88 89 @Test testStartPreview()90 public void testStartPreview() { 91 assertThat(shadowCamera.isPreviewing()).isFalse(); 92 camera.startPreview(); 93 assertThat(shadowCamera.isPreviewing()).isTrue(); 94 } 95 96 @Test testStopPreview()97 public void testStopPreview() { 98 camera.startPreview(); 99 assertThat(shadowCamera.isPreviewing()).isTrue(); 100 camera.stopPreview(); 101 assertThat(shadowCamera.isPreviewing()).isFalse(); 102 } 103 104 @Test testRelease()105 public void testRelease() { 106 assertThat(shadowCamera.isReleased()).isFalse(); 107 camera.release(); 108 assertThat(shadowCamera.isReleased()).isTrue(); 109 } 110 111 @Test testSetPreviewCallbacks()112 public void testSetPreviewCallbacks() { 113 TestPreviewCallback callback = new TestPreviewCallback(); 114 assertThat(callback.camera).isNull(); 115 assertThat(callback.data).isNull(); 116 117 camera.setPreviewCallback(callback); 118 shadowCamera.invokePreviewCallback("foobar".getBytes(UTF_8)); 119 120 assertThat(callback.camera).isSameInstanceAs(camera); 121 assertThat(callback.data).isEqualTo("foobar".getBytes(UTF_8)); 122 } 123 124 @Test testSetOneShotPreviewCallbacks()125 public void testSetOneShotPreviewCallbacks() { 126 TestPreviewCallback callback = new TestPreviewCallback(); 127 assertThat(callback.camera).isNull(); 128 assertThat(callback.data).isNull(); 129 130 camera.setOneShotPreviewCallback(callback); 131 shadowCamera.invokePreviewCallback("foobar".getBytes(UTF_8)); 132 133 assertThat(callback.camera).isSameInstanceAs(camera); 134 assertThat(callback.data).isEqualTo("foobar".getBytes(UTF_8)); 135 } 136 137 @Test testPreviewCallbacksWithBuffers()138 public void testPreviewCallbacksWithBuffers() { 139 TestPreviewCallback callback = new TestPreviewCallback(); 140 assertThat(callback.camera).isNull(); 141 assertThat(callback.data).isNull(); 142 143 camera.setPreviewCallbackWithBuffer(callback); 144 shadowCamera.invokePreviewCallback("foobar".getBytes(UTF_8)); 145 146 assertThat(callback.camera).isSameInstanceAs(camera); 147 assertThat(callback.data).isEqualTo("foobar".getBytes(UTF_8)); 148 } 149 150 @Test testClearPreviewCallback()151 public void testClearPreviewCallback() { 152 TestPreviewCallback callback = new TestPreviewCallback(); 153 assertThat(callback.camera).isNull(); 154 assertThat(callback.data).isNull(); 155 156 camera.setPreviewCallback(callback); 157 camera.setPreviewCallback(null); 158 159 shadowCamera.invokePreviewCallback("foobar".getBytes(UTF_8)); 160 assertThat(callback.camera).isNull(); 161 assertThat(callback.data).isNull(); 162 163 camera.setOneShotPreviewCallback(callback); 164 camera.setOneShotPreviewCallback(null); 165 166 shadowCamera.invokePreviewCallback("foobar".getBytes(UTF_8)); 167 assertThat(callback.camera).isNull(); 168 assertThat(callback.data).isNull(); 169 170 camera.setPreviewCallbackWithBuffer(callback); 171 camera.setPreviewCallbackWithBuffer(null); 172 173 shadowCamera.invokePreviewCallback("foobar".getBytes(UTF_8)); 174 assertThat(callback.camera).isNull(); 175 assertThat(callback.data).isNull(); 176 } 177 178 @Test testAddCallbackBuffer()179 public void testAddCallbackBuffer() { 180 byte[] buf1 = new byte[0]; 181 byte[] buf2 = new byte[1]; 182 camera.addCallbackBuffer(buf1); 183 assertThat(shadowCamera.getAddedCallbackBuffers()).containsExactly(buf1); 184 camera.addCallbackBuffer(buf2); 185 assertThat(shadowCamera.getAddedCallbackBuffers()).containsExactly(buf1, buf2); 186 } 187 188 @Test testDisplayOrientation()189 public void testDisplayOrientation() { 190 camera.setDisplayOrientation(180); 191 assertThat(shadowCamera.getDisplayOrientation()).isEqualTo(180); 192 } 193 194 @Test testSetDisplayOrientationUpdatesCameraInfos()195 public void testSetDisplayOrientationUpdatesCameraInfos() { 196 addBackCamera(); 197 addFrontCamera(); 198 199 camera = Camera.open(1); 200 camera.setDisplayOrientation(180); 201 202 Camera.CameraInfo cameraQuery = new Camera.CameraInfo(); 203 Camera.getCameraInfo(ShadowCamera.getLastOpenedCameraId(), cameraQuery); 204 assertThat(cameraQuery.orientation).isEqualTo(180); 205 } 206 207 @Test testAutoFocus()208 public void testAutoFocus() { 209 assertThat(shadowCamera.hasRequestedAutoFocus()).isFalse(); 210 TestAutoFocusCallback callback = new TestAutoFocusCallback(); 211 212 camera.autoFocus(callback); 213 214 assertThat(shadowCamera.hasRequestedAutoFocus()).isTrue(); 215 shadowCamera.invokeAutoFocusCallback(true, camera); 216 assertThat(callback.success).isEqualTo(true); 217 assertThat(callback.camera).isEqualTo(camera); 218 219 assertThat(shadowCamera.hasRequestedAutoFocus()).isFalse(); 220 try { 221 shadowCamera.invokeAutoFocusCallback(true, camera); 222 fail("expected an IllegalStateException"); 223 } catch (IllegalStateException e) { 224 // expected 225 } 226 } 227 228 @Test testInvokeAutoFocusCallbackMissing()229 public void testInvokeAutoFocusCallbackMissing() { 230 try { 231 shadowCamera.invokeAutoFocusCallback(true, camera); 232 fail("expected an IllegalStateException"); 233 } catch (IllegalStateException e) { 234 // expected 235 } 236 } 237 238 @Test testCancelAutoFocus()239 public void testCancelAutoFocus() { 240 assertThat(shadowCamera.hasRequestedAutoFocus()).isFalse(); 241 camera.autoFocus(null); 242 assertThat(shadowCamera.hasRequestedAutoFocus()).isTrue(); 243 camera.cancelAutoFocus(); 244 assertThat(shadowCamera.hasRequestedAutoFocus()).isFalse(); 245 } 246 247 @Test testCameraInfoNoCameras()248 public void testCameraInfoNoCameras() { 249 assertThat(Camera.getNumberOfCameras()).isEqualTo(0); 250 } 251 252 @Test testCameraInfoBackOnly()253 public void testCameraInfoBackOnly() { 254 Camera.CameraInfo cameraQuery = new Camera.CameraInfo(); 255 256 addBackCamera(); 257 Camera.getCameraInfo(0, cameraQuery); 258 259 assertThat(Camera.getNumberOfCameras()).isEqualTo(1); 260 assertThat(cameraQuery.facing).isEqualTo(Camera.CameraInfo.CAMERA_FACING_BACK); 261 assertThat(cameraQuery.orientation).isEqualTo(0); 262 } 263 264 @Test testCameraInfoBackAndFront()265 public void testCameraInfoBackAndFront() { 266 Camera.CameraInfo cameraQuery = new Camera.CameraInfo(); 267 addBackCamera(); 268 addFrontCamera(); 269 270 assertThat(Camera.getNumberOfCameras()).isEqualTo(2); 271 Camera.getCameraInfo(0, cameraQuery); 272 assertThat(cameraQuery.facing).isEqualTo(Camera.CameraInfo.CAMERA_FACING_BACK); 273 assertThat(cameraQuery.orientation).isEqualTo(0); 274 Camera.getCameraInfo(1, cameraQuery); 275 assertThat(cameraQuery.facing).isEqualTo(Camera.CameraInfo.CAMERA_FACING_FRONT); 276 assertThat(cameraQuery.orientation).isEqualTo(90); 277 } 278 279 @Test testCameraInfoShutterSound()280 public void testCameraInfoShutterSound() { 281 Camera.CameraInfo cameraQueryCannotDisable = new Camera.CameraInfo(); 282 Camera.CameraInfo cameraInfoCannotDisable = new Camera.CameraInfo(); 283 cameraInfoCannotDisable.canDisableShutterSound = false; 284 ShadowCamera.addCameraInfo(0, cameraInfoCannotDisable); 285 286 Camera.CameraInfo cameraQueryCanDisable = new Camera.CameraInfo(); 287 Camera.CameraInfo cameraInfoCanDisable = new Camera.CameraInfo(); 288 cameraInfoCanDisable.canDisableShutterSound = true; 289 ShadowCamera.addCameraInfo(1, cameraInfoCanDisable); 290 291 assertThat(Camera.getNumberOfCameras()).isEqualTo(2); 292 Camera.getCameraInfo(0, cameraQueryCannotDisable); 293 assertThat(cameraQueryCannotDisable.canDisableShutterSound).isFalse(); 294 Camera.getCameraInfo(1, cameraQueryCanDisable); 295 assertThat(cameraQueryCanDisable.canDisableShutterSound).isTrue(); 296 } 297 298 @Test testTakePicture()299 public void testTakePicture() { 300 camera.takePicture(null, null, null); 301 302 TestShutterCallback shutterCallback = new TestShutterCallback(); 303 TestPictureCallback rawCallback = new TestPictureCallback(); 304 TestPictureCallback jpegCallback = new TestPictureCallback(); 305 camera.takePicture(shutterCallback, rawCallback, jpegCallback); 306 307 assertThat(shutterCallback.wasCalled).isTrue(); 308 assertThat(rawCallback.wasCalled).isTrue(); 309 assertThat(jpegCallback.wasCalled).isTrue(); 310 } 311 312 @Test testShutterEnabled()313 public void testShutterEnabled() { 314 Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); 315 cameraInfo.facing = Camera.CameraInfo.CAMERA_FACING_BACK; 316 cameraInfo.canDisableShutterSound = false; 317 ShadowCamera.addCameraInfo(0, cameraInfo); 318 319 assertThat(Camera.getNumberOfCameras()).isEqualTo(1); 320 assertThat(shadowCamera.enableShutterSound(true)).isTrue(); 321 assertThat(shadowCamera.enableShutterSound(false)).isFalse(); 322 323 cameraInfo.canDisableShutterSound = true; 324 assertThat(shadowCamera.enableShutterSound(true)).isTrue(); 325 assertThat(shadowCamera.enableShutterSound(false)).isTrue(); 326 assertThat(shadowCamera.enableShutterSound(true)).isTrue(); 327 } 328 329 @Test cameraParameters_areCached()330 public void cameraParameters_areCached() { 331 assertThat(camera.getParameters()).isSameInstanceAs(Camera.open().getParameters()); 332 } 333 334 @Test setSupportedFocusModes_empty_clearsCurrentFocusMode()335 public void setSupportedFocusModes_empty_clearsCurrentFocusMode() { 336 Camera.Parameters parameters = camera.getParameters(); 337 assertThat(parameters.getFocusMode()).isNotNull(); 338 Shadows.shadowOf(parameters).setSupportedFocusModes(); 339 assertThat(parameters.getFocusMode()).isNull(); 340 } 341 342 @Test setSupportedFlashModes_empty_clearsCurrentFocusMode()343 public void setSupportedFlashModes_empty_clearsCurrentFocusMode() { 344 Camera.Parameters parameters = camera.getParameters(); 345 assertThat(parameters.getFlashMode()).isNotNull(); 346 Shadows.shadowOf(parameters).setSupportedFlashModes(); 347 assertThat(parameters.getFlashMode()).isNull(); 348 } 349 addBackCamera()350 private void addBackCamera() { 351 Camera.CameraInfo backCamera = new Camera.CameraInfo(); 352 backCamera.facing = Camera.CameraInfo.CAMERA_FACING_BACK; 353 backCamera.orientation = 0; 354 ShadowCamera.addCameraInfo(0, backCamera); 355 } 356 addFrontCamera()357 private void addFrontCamera() { 358 Camera.CameraInfo frontCamera = new Camera.CameraInfo(); 359 frontCamera.facing = Camera.CameraInfo.CAMERA_FACING_FRONT; 360 frontCamera.orientation = 90; 361 ShadowCamera.addCameraInfo(1, frontCamera); 362 } 363 364 private static class TestPreviewCallback implements Camera.PreviewCallback { 365 public Camera camera = null; 366 public byte[] data = null; 367 368 @Override onPreviewFrame(byte[] data, Camera camera)369 public void onPreviewFrame(byte[] data, Camera camera) { 370 this.data = data; 371 this.camera = camera; 372 } 373 } 374 375 private static class TestAutoFocusCallback implements Camera.AutoFocusCallback { 376 public boolean success; 377 public Camera camera; 378 379 @Override onAutoFocus(boolean success, Camera camera)380 public void onAutoFocus(boolean success, Camera camera) { 381 this.success = success; 382 this.camera = camera; 383 } 384 } 385 386 private static class TestShutterCallback implements Camera.ShutterCallback { 387 public boolean wasCalled; 388 389 @Override onShutter()390 public void onShutter() { 391 wasCalled = true; 392 } 393 } 394 395 private static class TestPictureCallback implements Camera.PictureCallback { 396 public boolean wasCalled; 397 398 @Override onPictureTaken(byte[] data, Camera camera)399 public void onPictureTaken(byte[] data, Camera camera) { 400 wasCalled = true; 401 } 402 } 403 404 private static class TestSurfaceHolder implements SurfaceHolder { 405 406 @Override addCallback(Callback callback)407 public void addCallback(Callback callback) {} 408 409 @Override getSurface()410 public Surface getSurface() { 411 return null; 412 } 413 414 @Override getSurfaceFrame()415 public Rect getSurfaceFrame() { 416 return null; 417 } 418 419 @Override isCreating()420 public boolean isCreating() { 421 return false; 422 } 423 424 @Override lockCanvas()425 public Canvas lockCanvas() { 426 return null; 427 } 428 429 @Override lockCanvas(Rect dirty)430 public Canvas lockCanvas(Rect dirty) { 431 return null; 432 } 433 434 @Override removeCallback(Callback callback)435 public void removeCallback(Callback callback) {} 436 437 @Override setFixedSize(int width, int height)438 public void setFixedSize(int width, int height) {} 439 440 @Override setFormat(int format)441 public void setFormat(int format) {} 442 443 @Override setKeepScreenOn(boolean screenOn)444 public void setKeepScreenOn(boolean screenOn) {} 445 446 @Override setSizeFromLayout()447 public void setSizeFromLayout() {} 448 449 @Override setType(int type)450 public void setType(int type) {} 451 452 @Override unlockCanvasAndPost(Canvas canvas)453 public void unlockCanvasAndPost(Canvas canvas) {} 454 } 455 } 456