blob: 29dc45b690ac48f2dbde25882bebea3785dfe62d [file] [log] [blame]
package org.robolectric.shadows;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import org.robolectric.Robolectric;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Shadows the Android {@code Camera} class.
*/
@Implements(Camera.class)
public class ShadowCamera {
private static int lastOpenedCameraId;
private int id;
private boolean locked;
private boolean previewing;
private boolean released;
private Camera.Parameters parameters;
private Camera.PreviewCallback previewCallback;
private SurfaceHolder surfaceHolder;
private int displayOrientation;
private Camera.AutoFocusCallback autoFocusCallback;
private static Map<Integer, Camera.CameraInfo> cameras = new HashMap<Integer,Camera.CameraInfo>();
@RealObject
private Camera realCamera;
public void __constructor__() {
locked = true;
previewing = false;
released = false;
}
@Implementation
public static Camera open() {
lastOpenedCameraId = 0;
Camera camera = Robolectric.newInstanceOf(Camera.class);
Robolectric.shadowOf(camera).id = 0;
return camera;
}
@Implementation
public static Camera open(int cameraId) {
lastOpenedCameraId = cameraId;
Camera camera = Robolectric.newInstanceOf(Camera.class);
Robolectric.shadowOf(camera).id = cameraId;
return camera;
}
public static int getLastOpenedCameraId() {
return lastOpenedCameraId;
}
@Implementation
public void unlock() {
locked = false;
}
@Implementation
public void reconnect() {
locked = true;
}
@Implementation
public Camera.Parameters getParameters() {
if (null == parameters) {
parameters = Robolectric.newInstanceOf(Camera.Parameters.class);
}
return parameters;
}
@Implementation
public void setParameters(Camera.Parameters params) {
parameters = params;
}
@Implementation
public void setPreviewDisplay(SurfaceHolder holder) {
surfaceHolder = holder;
}
@Implementation
public void startPreview() {
previewing = true;
}
@Implementation
public void stopPreview() {
previewing = false;
}
@Implementation
public void release() {
released = true;
}
@Implementation
public void setPreviewCallback(Camera.PreviewCallback cb) {
previewCallback = cb;
}
@Implementation
public void setOneShotPreviewCallback(Camera.PreviewCallback cb) {
previewCallback = cb;
}
@Implementation
public void setPreviewCallbackWithBuffer(Camera.PreviewCallback cb) {
previewCallback = cb;
}
@Implementation
public void setDisplayOrientation(int degrees) {
displayOrientation = degrees;
if (cameras.containsKey(id)) {
cameras.get(id).orientation = degrees;
}
}
public int getDisplayOrientation() {
return displayOrientation;
}
@Implementation
public void autoFocus(Camera.AutoFocusCallback callback) {
autoFocusCallback = callback;
}
public boolean hasRequestedAutoFocus() {
return autoFocusCallback != null;
}
public void invokeAutoFocusCallback(boolean success, Camera camera) {
if (autoFocusCallback == null) {
throw new IllegalStateException(
"cannot invoke AutoFocusCallback before autoFocus has been called.");
}
autoFocusCallback.onAutoFocus(success, camera);
}
@Implementation
public static void getCameraInfo(int cameraId, Camera.CameraInfo cameraInfo ) {
Camera.CameraInfo foundCam = cameras.get( cameraId );
cameraInfo.facing = foundCam.facing;
cameraInfo.orientation = foundCam.orientation;
}
@Implementation
public static int getNumberOfCameras() {
return cameras.size();
}
/**
* Allows test cases to invoke the preview callback, to simulate a frame of camera data.
*
* @param data byte buffer of simulated camera data
*/
public void invokePreviewCallback(byte[] data) {
if (previewCallback != null) {
previewCallback.onPreviewFrame(data, realCamera);
}
}
public boolean isLocked() {
return locked;
}
public boolean isPreviewing() {
return previewing;
}
public boolean isReleased() {
return released;
}
public SurfaceHolder getPreviewDisplay() {
return surfaceHolder;
}
/**
* Add a mock {@code Camera.CameraInfo} object to simulate
* the existence of one or more cameras. By default, no
* cameras are defined.
*
* @param id
* @param camInfo
*/
public static void addCameraInfo(int id, Camera.CameraInfo camInfo) {
cameras.put(id, camInfo);
}
public static void clearCameraInfo() {
cameras.clear();
}
/**
* Shadows the Android {@code Camera.Parameters} class.
*/
@Implements(Camera.Parameters.class)
public static class ShadowParameters {
private int pictureWidth = 1280;
private int pictureHeight = 960;
private int previewWidth = 640;
private int previewHeight = 480;
private int previewFormat = ImageFormat.NV21;
private int previewFpsMin = 10;
private int previewFpsMax = 30;
private int previewFps = 30;
private int exposureCompensation = 0;
private String focusMode;
private List<String> supportedFocusModes = new ArrayList<String>();
@Implementation
public Camera.Size getPictureSize() {
Camera.Size pictureSize = Robolectric.newInstanceOf(Camera.class).new Size(0, 0);
pictureSize.width = pictureWidth;
pictureSize.height = pictureHeight;
return pictureSize;
}
@Implementation
public int getPreviewFormat() {
return previewFormat;
}
@Implementation
public void getPreviewFpsRange(int[] range) {
range[0] = previewFpsMin;
range[1] = previewFpsMax;
}
@Implementation
public int getPreviewFrameRate() {
return previewFps;
}
@Implementation
public Camera.Size getPreviewSize() {
Camera.Size previewSize = Robolectric.newInstanceOf(Camera.class).new Size(0, 0);
previewSize.width = previewWidth;
previewSize.height = previewHeight;
return previewSize;
}
@Implementation
public List<Camera.Size> getSupportedPictureSizes() {
List<Camera.Size> supportedSizes = new ArrayList<Camera.Size>();
addSize(supportedSizes, 320, 240);
addSize(supportedSizes, 640, 480);
addSize(supportedSizes, 800, 600);
return supportedSizes;
}
@Implementation
public List<Integer> getSupportedPictureFormats() {
List<Integer> formats = new ArrayList<Integer>();
formats.add(ImageFormat.NV21);
formats.add(ImageFormat.JPEG);
return formats;
}
@Implementation
public List<Integer> getSupportedPreviewFormats() {
List<Integer> formats = new ArrayList<Integer>();
formats.add(ImageFormat.NV21);
formats.add(ImageFormat.JPEG);
return formats;
}
@Implementation
public List<int[]> getSupportedPreviewFpsRange() {
List<int[]> supportedRanges = new ArrayList<int[]>();
addRange(supportedRanges, 15000, 15000);
addRange(supportedRanges, 10000, 30000);
return supportedRanges;
}
@Implementation
public List<Integer> getSupportedPreviewFrameRates() {
List<Integer> supportedRates = new ArrayList<Integer>();
supportedRates.add(10);
supportedRates.add(15);
supportedRates.add(30);
return supportedRates;
}
@Implementation
public List<Camera.Size> getSupportedPreviewSizes() {
List<Camera.Size> supportedSizes = new ArrayList<Camera.Size>();
addSize(supportedSizes, 320, 240);
addSize(supportedSizes, 640, 480);
return supportedSizes;
}
public void setSupportedFocusModes(String... focusModes) {
supportedFocusModes = Arrays.asList(focusModes);
}
@Implementation
public List<String> getSupportedFocusModes() {
return supportedFocusModes;
}
@Implementation
public String getFocusMode() {
return focusMode;
}
@Implementation
public void setFocusMode(String focusMode) {
this.focusMode = focusMode;
}
@Implementation
public void setPictureSize(int width, int height) {
pictureWidth = width;
pictureHeight = height;
}
@Implementation
public void setPreviewFormat(int pixel_format) {
previewFormat = pixel_format;
}
@Implementation
public void setPreviewFpsRange(int min, int max) {
previewFpsMin = min;
previewFpsMax = max;
}
@Implementation
public void setPreviewFrameRate(int fps) {
previewFps = fps;
}
@Implementation
public void setPreviewSize(int width, int height) {
previewWidth = width;
previewHeight = height;
}
@Implementation
public int getMinExposureCompensation() {
return -6;
}
@Implementation
public int getMaxExposureCompensation() {
return 6;
}
@Implementation
public float getExposureCompensationStep() {
return 0.5f;
}
@Implementation
public int getExposureCompensation() {
return exposureCompensation;
}
@Implementation
public void setExposureCompensation(int compensation) {
exposureCompensation = compensation;
}
public int getPreviewWidth() {
return previewWidth;
}
public int getPreviewHeight() {
return previewHeight;
}
public int getPictureWidth() {
return pictureWidth;
}
public int getPictureHeight() {
return pictureHeight;
}
private void addSize(List<Camera.Size> sizes, int width, int height) {
Camera.Size newSize = Robolectric.newInstanceOf(Camera.class).new Size(0, 0);
newSize.width = width;
newSize.height = height;
sizes.add(newSize);
}
private void addRange(List<int[]> ranges, int min, int max) {
int[] range = new int[2];
range[0] = min;
range[1] = max;
ranges.add(range);
}
}
/**
* Shadow for the Android {@code Camera.Size} value object.
*/
@Implements(Camera.Size.class)
public static class ShadowSize {
@RealObject private Camera.Size realCameraSize;
public void __constructor__(Camera camera, int width, int height) {
realCameraSize.width = width;
realCameraSize.height = height;
}
}
}