Home | History | Annotate | Download | only in shadows
      1 package org.robolectric.shadows;
      2 
      3 import static org.robolectric.shadow.api.Shadow.newInstanceOf;
      4 
      5 import android.graphics.ImageFormat;
      6 import android.hardware.Camera;
      7 import android.view.SurfaceHolder;
      8 import java.util.ArrayList;
      9 import java.util.Arrays;
     10 import java.util.Collections;
     11 import java.util.HashMap;
     12 import java.util.List;
     13 import java.util.Map;
     14 import org.robolectric.Shadows;
     15 import org.robolectric.annotation.Implementation;
     16 import org.robolectric.annotation.Implements;
     17 import org.robolectric.annotation.RealObject;
     18 
     19 @Implements(Camera.class)
     20 public class ShadowCamera {
     21 
     22   private static int lastOpenedCameraId;
     23 
     24   private int id;
     25   private boolean locked;
     26   private boolean previewing;
     27   private boolean released;
     28   private Camera.Parameters parameters;
     29   private Camera.PreviewCallback previewCallback;
     30   private List<byte[]> callbackBuffers = new ArrayList<>();
     31   private SurfaceHolder surfaceHolder;
     32   private int displayOrientation;
     33   private Camera.AutoFocusCallback autoFocusCallback;
     34   private boolean autoFocusing;
     35 
     36   private static Map<Integer, Camera.CameraInfo> cameras = new HashMap<>();
     37 
     38   @RealObject
     39   private Camera realCamera;
     40 
     41   @Implementation
     42   public void __constructor__() {
     43     locked = true;
     44     previewing = false;
     45     released = false;
     46   }
     47 
     48   @Implementation
     49   public static Camera open() {
     50     lastOpenedCameraId = 0;
     51     Camera camera = newInstanceOf(Camera.class);
     52     Shadows.shadowOf(camera).id = 0;
     53     return camera;
     54   }
     55 
     56   @Implementation
     57   public static Camera open(int cameraId) {
     58     lastOpenedCameraId = cameraId;
     59     Camera camera = newInstanceOf(Camera.class);
     60     Shadows.shadowOf(camera).id = cameraId;
     61     return camera;
     62   }
     63 
     64   public static int getLastOpenedCameraId() {
     65     return lastOpenedCameraId;
     66   }
     67 
     68   @Implementation
     69   public void unlock() {
     70     locked = false;
     71   }
     72 
     73   @Implementation
     74   public void reconnect() {
     75     locked = true;
     76   }
     77 
     78   @Implementation
     79   public Camera.Parameters getParameters() {
     80     if (null == parameters) {
     81       parameters = newInstanceOf(Camera.Parameters.class);
     82     }
     83     return parameters;
     84   }
     85 
     86   @Implementation
     87   public void setParameters(Camera.Parameters params) {
     88     parameters = params;
     89   }
     90 
     91   @Implementation
     92   public void setPreviewDisplay(SurfaceHolder holder) {
     93     surfaceHolder = holder;
     94   }
     95 
     96   @Implementation
     97   public void startPreview() {
     98     previewing = true;
     99   }
    100 
    101   @Implementation
    102   public void stopPreview() {
    103     previewing = false;
    104   }
    105 
    106   @Implementation
    107   public void release() {
    108     released = true;
    109   }
    110 
    111   @Implementation
    112   public void setPreviewCallback(Camera.PreviewCallback cb) {
    113     previewCallback = cb;
    114   }
    115 
    116   @Implementation
    117   public void setOneShotPreviewCallback(Camera.PreviewCallback cb) {
    118     previewCallback = cb;
    119   }
    120 
    121   @Implementation
    122   public void setPreviewCallbackWithBuffer(Camera.PreviewCallback cb) {
    123     previewCallback = cb;
    124   }
    125 
    126   /**
    127    * Allows test cases to invoke the preview callback, to simulate a frame of camera data.
    128    *
    129    * @param data byte buffer of simulated camera data
    130    */
    131   public void invokePreviewCallback(byte[] data) {
    132     if (previewCallback != null) {
    133       previewCallback.onPreviewFrame(data, realCamera);
    134     }
    135   }
    136 
    137   @Implementation
    138   public void addCallbackBuffer(byte[] callbackBuffer) {
    139     callbackBuffers.add(callbackBuffer);
    140   }
    141 
    142   public List<byte[]> getAddedCallbackBuffers() {
    143     return Collections.unmodifiableList(callbackBuffers);
    144   }
    145 
    146   @Implementation
    147   public void setDisplayOrientation(int degrees) {
    148     displayOrientation = degrees;
    149     if (cameras.containsKey(id)) {
    150       cameras.get(id).orientation = degrees;
    151     }
    152   }
    153 
    154   public int getDisplayOrientation() {
    155     return displayOrientation;
    156   }
    157 
    158   @Implementation
    159   public void autoFocus(Camera.AutoFocusCallback callback) {
    160     autoFocusCallback = callback;
    161     autoFocusing = true;
    162   }
    163 
    164   @Implementation
    165   public void cancelAutoFocus() {
    166     autoFocusCallback = null;
    167     autoFocusing = false;
    168   }
    169 
    170   public boolean hasRequestedAutoFocus() {
    171     return autoFocusing;
    172   }
    173 
    174   public void invokeAutoFocusCallback(boolean success, Camera camera) {
    175     if (autoFocusCallback == null) {
    176       throw new IllegalStateException(
    177           "cannot invoke AutoFocusCallback before autoFocus() has been called "
    178               + "or after cancelAutoFocus() has been called "
    179               + "or after the callback has been invoked.");
    180     }
    181     autoFocusCallback.onAutoFocus(success, camera);
    182     autoFocusCallback = null;
    183     autoFocusing = false;
    184   }
    185 
    186   @Implementation
    187   public static void getCameraInfo(int cameraId, Camera.CameraInfo cameraInfo ) {
    188     Camera.CameraInfo foundCam = cameras.get( cameraId );
    189     cameraInfo.facing = foundCam.facing;
    190     cameraInfo.orientation = foundCam.orientation;
    191   }
    192 
    193   @Implementation
    194   public static int getNumberOfCameras() {
    195     return cameras.size();
    196   }
    197 
    198   public boolean isLocked() {
    199     return locked;
    200   }
    201 
    202   public boolean isPreviewing() {
    203     return previewing;
    204   }
    205 
    206   public boolean isReleased() {
    207     return released;
    208   }
    209 
    210   public SurfaceHolder getPreviewDisplay() {
    211     return surfaceHolder;
    212   }
    213 
    214   /**
    215    * Add a mock {@code Camera.CameraInfo} object to simulate
    216    * the existence of one or more cameras.  By default, no
    217    * cameras are defined.
    218    *
    219    * @param id The camera id
    220    * @param camInfo The CameraInfo
    221    */
    222   public static void addCameraInfo(int id, Camera.CameraInfo camInfo) {
    223     cameras.put(id, camInfo);
    224   }
    225 
    226   public static void clearCameraInfo() {
    227     cameras.clear();
    228   }
    229 
    230   /**
    231    * Shadows the Android {@code Camera.Parameters} class.
    232    */
    233   @Implements(Camera.Parameters.class)
    234   public static class ShadowParameters {
    235 
    236     private int pictureWidth = 1280;
    237     private int pictureHeight = 960;
    238     private int previewWidth = 640;
    239     private int previewHeight = 480;
    240     private int previewFormat = ImageFormat.NV21;
    241     private int previewFpsMin = 10;
    242     private int previewFpsMax = 30;
    243     private int previewFps = 30;
    244     private int exposureCompensation = 0;
    245     private String focusMode;
    246     private List<String> supportedFocusModes = new ArrayList<>();
    247 
    248     @Implementation
    249     public Camera.Size getPictureSize() {
    250       Camera.Size pictureSize = newInstanceOf(Camera.class).new Size(0, 0);
    251       pictureSize.width = pictureWidth;
    252       pictureSize.height = pictureHeight;
    253       return pictureSize;
    254     }
    255 
    256     @Implementation
    257     public int getPreviewFormat() {
    258       return previewFormat;
    259     }
    260 
    261     @Implementation
    262     public void getPreviewFpsRange(int[] range) {
    263       range[0] = previewFpsMin;
    264       range[1] = previewFpsMax;
    265     }
    266 
    267     @Implementation
    268     public int getPreviewFrameRate() {
    269       return previewFps;
    270     }
    271 
    272     @Implementation
    273     public Camera.Size getPreviewSize() {
    274       Camera.Size previewSize = newInstanceOf(Camera.class).new Size(0, 0);
    275       previewSize.width = previewWidth;
    276       previewSize.height = previewHeight;
    277       return previewSize;
    278     }
    279 
    280     @Implementation
    281     public List<Camera.Size> getSupportedPictureSizes() {
    282       List<Camera.Size> supportedSizes = new ArrayList<>();
    283       addSize(supportedSizes, 320, 240);
    284       addSize(supportedSizes, 640, 480);
    285       addSize(supportedSizes, 800, 600);
    286       return supportedSizes;
    287     }
    288 
    289     @Implementation
    290     public List<Integer> getSupportedPictureFormats() {
    291       List<Integer> formats = new ArrayList<>();
    292       formats.add(ImageFormat.NV21);
    293       formats.add(ImageFormat.JPEG);
    294       return formats;
    295     }
    296 
    297     @Implementation
    298     public List<Integer> getSupportedPreviewFormats() {
    299       List<Integer> formats = new ArrayList<>();
    300       formats.add(ImageFormat.NV21);
    301       formats.add(ImageFormat.JPEG);
    302       return formats;
    303     }
    304 
    305     @Implementation
    306     public List<int[]> getSupportedPreviewFpsRange() {
    307       List<int[]> supportedRanges = new ArrayList<>();
    308       addRange(supportedRanges, 15000, 15000);
    309       addRange(supportedRanges, 10000, 30000);
    310       return supportedRanges;
    311     }
    312 
    313     @Implementation
    314     public List<Integer> getSupportedPreviewFrameRates() {
    315       List<Integer> supportedRates = new ArrayList<>();
    316       supportedRates.add(10);
    317       supportedRates.add(15);
    318       supportedRates.add(30);
    319       return supportedRates;
    320     }
    321 
    322     @Implementation
    323     public List<Camera.Size> getSupportedPreviewSizes() {
    324       List<Camera.Size> supportedSizes = new ArrayList<>();
    325       addSize(supportedSizes, 320, 240);
    326       addSize(supportedSizes, 640, 480);
    327       return supportedSizes;
    328     }
    329 
    330     public void setSupportedFocusModes(String... focusModes) {
    331       supportedFocusModes = Arrays.asList(focusModes);
    332     }
    333 
    334     @Implementation
    335     public List<String> getSupportedFocusModes() {
    336       return supportedFocusModes;
    337     }
    338 
    339     @Implementation
    340     public String getFocusMode() {
    341       return focusMode;
    342     }
    343 
    344     @Implementation
    345     public void setFocusMode(String focusMode) {
    346       this.focusMode = focusMode;
    347     }
    348 
    349     @Implementation
    350     public void setPictureSize(int width, int height) {
    351       pictureWidth = width;
    352       pictureHeight = height;
    353     }
    354 
    355     @Implementation
    356     public void setPreviewFormat(int pixel_format) {
    357       previewFormat = pixel_format;
    358     }
    359 
    360     @Implementation
    361     public void setPreviewFpsRange(int min, int max) {
    362       previewFpsMin = min;
    363       previewFpsMax = max;
    364     }
    365 
    366     @Implementation
    367     public void setPreviewFrameRate(int fps) {
    368       previewFps = fps;
    369     }
    370 
    371     @Implementation
    372     public void setPreviewSize(int width, int height) {
    373       previewWidth = width;
    374       previewHeight = height;
    375     }
    376 
    377     @Implementation
    378     public int getMinExposureCompensation() {
    379       return -6;
    380     }
    381 
    382     @Implementation
    383     public int getMaxExposureCompensation() {
    384       return 6;
    385     }
    386 
    387     @Implementation
    388     public float getExposureCompensationStep() {
    389       return 0.5f;
    390     }
    391 
    392     @Implementation
    393     public int getExposureCompensation() {
    394       return exposureCompensation;
    395     }
    396 
    397     @Implementation
    398     public void setExposureCompensation(int compensation) {
    399       exposureCompensation = compensation;
    400     }
    401 
    402     public int getPreviewWidth() {
    403       return previewWidth;
    404     }
    405 
    406     public int getPreviewHeight() {
    407       return previewHeight;
    408     }
    409 
    410     public int getPictureWidth() {
    411       return pictureWidth;
    412     }
    413 
    414     public int getPictureHeight() {
    415       return pictureHeight;
    416     }
    417 
    418     private void addSize(List<Camera.Size> sizes, int width, int height) {
    419       Camera.Size newSize = newInstanceOf(Camera.class).new Size(0, 0);
    420       newSize.width = width;
    421       newSize.height = height;
    422       sizes.add(newSize);
    423     }
    424 
    425     private void addRange(List<int[]> ranges, int min, int max) {
    426       int[] range = new int[2];
    427       range[0] = min;
    428       range[1] = max;
    429       ranges.add(range);
    430     }
    431 
    432   }
    433 
    434   @Implements(Camera.Size.class)
    435   public static class ShadowSize {
    436     @RealObject private Camera.Size realCameraSize;
    437 
    438     @Implementation
    439     public void __constructor__(Camera camera, int width, int height) {
    440       realCameraSize.width = width;
    441       realCameraSize.height = height;
    442     }
    443   }
    444 }
    445