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() throws Exception { 34 ShadowCamera.clearCameraInfo(); 35 } 36 37 @Test testOpen()38 public void testOpen() throws Exception { 39 assertThat(camera).isNotNull(); 40 assertThat(ShadowCamera.getLastOpenedCameraId()).isEqualTo(0); 41 } 42 43 @Test testOpenWithId()44 public void testOpenWithId() throws Exception { 45 camera = Camera.open(12); 46 assertThat(camera).isNotNull(); 47 assertThat(ShadowCamera.getLastOpenedCameraId()).isEqualTo(12); 48 } 49 50 @Test testUnlock()51 public void testUnlock() throws Exception { 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() throws Exception { 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() throws Exception { 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() throws Exception { 91 assertThat(shadowCamera.isPreviewing()).isFalse(); 92 camera.startPreview(); 93 assertThat(shadowCamera.isPreviewing()).isTrue(); 94 } 95 96 @Test testStopPreview()97 public void testStopPreview() throws Exception { 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() throws Exception { 106 assertThat(shadowCamera.isReleased()).isFalse(); 107 camera.release(); 108 assertThat(shadowCamera.isReleased()).isTrue(); 109 } 110 111 @Test testSetPreviewCallbacks()112 public void testSetPreviewCallbacks() throws Exception { 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() throws Exception { 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() throws Exception { 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() throws Exception { 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() throws Exception { 249 assertThat(Camera.getNumberOfCameras()).isEqualTo(0); 250 } 251 252 @Test testCameraInfoBackOnly()253 public void testCameraInfoBackOnly() throws Exception { 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() throws Exception { 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 testTakePicture()280 public void testTakePicture() throws Exception { 281 camera.takePicture(null, null, null); 282 283 TestShutterCallback shutterCallback = new TestShutterCallback(); 284 TestPictureCallback rawCallback = new TestPictureCallback(); 285 TestPictureCallback jpegCallback = new TestPictureCallback(); 286 camera.takePicture(shutterCallback, rawCallback, jpegCallback); 287 288 assertThat(shutterCallback.wasCalled).isTrue(); 289 assertThat(rawCallback.wasCalled).isTrue(); 290 assertThat(jpegCallback.wasCalled).isTrue(); 291 } 292 addBackCamera()293 private void addBackCamera() { 294 Camera.CameraInfo backCamera = new Camera.CameraInfo(); 295 backCamera.facing = Camera.CameraInfo.CAMERA_FACING_BACK; 296 backCamera.orientation = 0; 297 ShadowCamera.addCameraInfo(0, backCamera); 298 } 299 addFrontCamera()300 private void addFrontCamera() { 301 Camera.CameraInfo frontCamera = new Camera.CameraInfo(); 302 frontCamera.facing = Camera.CameraInfo.CAMERA_FACING_FRONT; 303 frontCamera.orientation = 90; 304 ShadowCamera.addCameraInfo(1, frontCamera); 305 } 306 307 private static class TestPreviewCallback implements Camera.PreviewCallback { 308 public Camera camera = null; 309 public byte[] data = null; 310 311 @Override onPreviewFrame(byte[] data, Camera camera)312 public void onPreviewFrame(byte[] data, Camera camera) { 313 this.data = data; 314 this.camera = camera; 315 } 316 } 317 318 private static class TestAutoFocusCallback implements Camera.AutoFocusCallback { 319 public boolean success; 320 public Camera camera; 321 322 @Override onAutoFocus(boolean success, Camera camera)323 public void onAutoFocus(boolean success, Camera camera) { 324 this.success = success; 325 this.camera = camera; 326 } 327 } 328 329 private static class TestShutterCallback implements Camera.ShutterCallback { 330 public boolean wasCalled; 331 332 @Override onShutter()333 public void onShutter() { 334 wasCalled = true; 335 } 336 } 337 338 private static class TestPictureCallback implements Camera.PictureCallback { 339 public boolean wasCalled; 340 341 @Override onPictureTaken(byte[] data, Camera camera)342 public void onPictureTaken(byte[] data, Camera camera) { 343 wasCalled = true; 344 } 345 } 346 347 private static class TestSurfaceHolder implements SurfaceHolder { 348 349 @Override addCallback(Callback callback)350 public void addCallback(Callback callback) { 351 } 352 353 @Override getSurface()354 public Surface getSurface() { 355 return null; 356 } 357 358 @Override getSurfaceFrame()359 public Rect getSurfaceFrame() { 360 return null; 361 } 362 363 @Override isCreating()364 public boolean isCreating() { 365 return false; 366 } 367 368 @Override lockCanvas()369 public Canvas lockCanvas() { 370 return null; 371 } 372 373 @Override lockCanvas(Rect dirty)374 public Canvas lockCanvas(Rect dirty) { 375 return null; 376 } 377 378 @Override removeCallback(Callback callback)379 public void removeCallback(Callback callback) { 380 } 381 382 @Override setFixedSize(int width, int height)383 public void setFixedSize(int width, int height) { 384 } 385 386 @Override setFormat(int format)387 public void setFormat(int format) { 388 } 389 390 @Override setKeepScreenOn(boolean screenOn)391 public void setKeepScreenOn(boolean screenOn) { 392 } 393 394 @Override setSizeFromLayout()395 public void setSizeFromLayout() { 396 } 397 398 @Override setType(int type)399 public void setType(int type) { 400 } 401 402 @Override unlockCanvasAndPost(Canvas canvas)403 public void unlockCanvasAndPost(Canvas canvas) { 404 } 405 } 406 } 407