/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.StringTokenizer; import java.io.IOException; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; import android.graphics.PixelFormat; import android.os.Handler; import android.os.Looper; import android.os.Message; /** * The Camera class is used to connect/disconnect with the camera service, * set capture settings, start/stop preview, snap a picture, and retrieve * frames for encoding for video. *
There is no default constructor for this class. Use {@link #open()} to * get a Camera object.
* *In order to use the device camera, you must declare the * {@link android.Manifest.permission#CAMERA} permission in your Android * Manifest. Also be sure to include the * <uses-feature> * manifest element in order to declare camera features used by your application. * For example, if you use the camera and auto-focus feature, your Manifest * should include the following:
*<uses-permission android:name="android.permission.CAMERA" /> * <uses-feature android:name="android.hardware.camera" /> * <uses-feature android:name="android.hardware.camera.autofocus" />* *
Caution: Different Android-powered devices * may have different hardware specifications, such as megapixel ratings and * auto-focus capabilities. In order for your application to be compatible with * more devices, you should not make assumptions about the device camera * specifications.
*/ public class Camera { private static final String TAG = "Camera"; // These match the enums in frameworks/base/include/ui/Camera.h private static final int CAMERA_MSG_ERROR = 0x001; private static final int CAMERA_MSG_SHUTTER = 0x002; private static final int CAMERA_MSG_FOCUS = 0x004; private static final int CAMERA_MSG_ZOOM = 0x008; private static final int CAMERA_MSG_PREVIEW_FRAME = 0x010; private static final int CAMERA_MSG_VIDEO_FRAME = 0x020; private static final int CAMERA_MSG_POSTVIEW_FRAME = 0x040; private static final int CAMERA_MSG_RAW_IMAGE = 0x080; private static final int CAMERA_MSG_COMPRESSED_IMAGE = 0x100; private static final int CAMERA_MSG_ALL_MSGS = 0x1FF; private int mNativeContext; // accessed by native methods private EventHandler mEventHandler; private ShutterCallback mShutterCallback; private PictureCallback mRawImageCallback; private PictureCallback mJpegCallback; private PreviewCallback mPreviewCallback; private PictureCallback mPostviewCallback; private AutoFocusCallback mAutoFocusCallback; private ZoomCallback mZoomCallback; private ErrorCallback mErrorCallback; private boolean mOneShot; /** * Returns a new Camera object. */ public static Camera open() { return new Camera(); } Camera() { mShutterCallback = null; mRawImageCallback = null; mJpegCallback = null; mPreviewCallback = null; mPostviewCallback = null; mZoomCallback = null; Looper looper; if ((looper = Looper.myLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else if ((looper = Looper.getMainLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else { mEventHandler = null; } native_setup(new WeakReferenceIt is recommended that you call this as soon as you're done with the * Camera object.
*/ public final void release() { native_release(); } /** * Reconnect to the camera after passing it to MediaRecorder. To save * setup/teardown time, a client of Camera can pass an initialized Camera * object to a MediaRecorder to use for video recording. Once the * MediaRecorder is done with the Camera, this method can be used to * re-establish a connection with the camera hardware. NOTE: The Camera * object must first be unlocked by the process that owns it before it * can be connected to another process. * * @throws IOException if the method fails. * * @hide */ public native final void reconnect() throws IOException; /** * Lock the camera to prevent other processes from accessing it. To save * setup/teardown time, a client of Camera can pass an initialized Camera * object to another process. This method is used to re-lock the Camera * object prevent other processes from accessing it. By default, the * Camera object is locked. Locking it again from the same process will * have no effect. Attempting to lock it from another process if it has * not been unlocked will fail. * * @throws RuntimeException if the method fails. */ public native final void lock(); /** * Unlock the camera to allow another process to access it. To save * setup/teardown time, a client of Camera can pass an initialized Camera * object to another process. This method is used to unlock the Camera * object before handing off the Camera object to the other process. * * @throws RuntimeException if the method fails. */ public native final void unlock(); /** * Sets the SurfaceHolder to be used for a picture preview. If the surface * changed since the last call, the screen will blank. Nothing happens * if the same surface is re-set. * * @param holder the SurfaceHolder upon which to place the picture preview * @throws IOException if the method fails. */ public final void setPreviewDisplay(SurfaceHolder holder) throws IOException { if (holder != null) { setPreviewDisplay(holder.getSurface()); } else { setPreviewDisplay((Surface)null); } } private native final void setPreviewDisplay(Surface surface); /** * Used to get a copy of each preview frame. */ public interface PreviewCallback { /** * The callback that delivers the preview frames. * * @param data The contents of the preview frame in the format defined * by {@link android.graphics.PixelFormat}, which can be queried * with {@link android.hardware.Camera.Parameters#getPreviewFormat()}. * If {@link android.hardware.Camera.Parameters#setPreviewFormat(int)} * is never called, the default will be the YCbCr_420_SP * (NV21) format. * @param camera The Camera service object. */ void onPreviewFrame(byte[] data, Camera camera); }; /** * Start drawing preview frames to the surface. */ public native final void startPreview(); /** * Stop drawing preview frames to the surface. */ public native final void stopPreview(); /** * Return current preview state. * * FIXME: Unhide before release * @hide */ public native final boolean previewEnabled(); /** * Can be called at any time to instruct the camera to use a callback for * each preview frame in addition to displaying it. * * @param cb A callback object that receives a copy of each preview frame. * Pass null to stop receiving callbacks at any time. */ public final void setPreviewCallback(PreviewCallback cb) { mPreviewCallback = cb; mOneShot = false; setHasPreviewCallback(cb != null, false); } /** * Installs a callback to retrieve a single preview frame, after which the * callback is cleared. * * @param cb A callback object that receives a copy of the preview frame. */ public final void setOneShotPreviewCallback(PreviewCallback cb) { if (cb != null) { mPreviewCallback = cb; mOneShot = true; setHasPreviewCallback(true, true); } } private native final void setHasPreviewCallback(boolean installed, boolean oneshot); private class EventHandler extends Handler { private Camera mCamera; public EventHandler(Camera c, Looper looper) { super(looper); mCamera = c; } @Override public void handleMessage(Message msg) { switch(msg.what) { case CAMERA_MSG_SHUTTER: if (mShutterCallback != null) { mShutterCallback.onShutter(); } return; case CAMERA_MSG_RAW_IMAGE: if (mRawImageCallback != null) { mRawImageCallback.onPictureTaken((byte[])msg.obj, mCamera); } return; case CAMERA_MSG_COMPRESSED_IMAGE: if (mJpegCallback != null) { mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera); } return; case CAMERA_MSG_PREVIEW_FRAME: if (mPreviewCallback != null) { mPreviewCallback.onPreviewFrame((byte[])msg.obj, mCamera); if (mOneShot) { mPreviewCallback = null; } } return; case CAMERA_MSG_POSTVIEW_FRAME: if (mPostviewCallback != null) { mPostviewCallback.onPictureTaken((byte[])msg.obj, mCamera); } return; case CAMERA_MSG_FOCUS: if (mAutoFocusCallback != null) { mAutoFocusCallback.onAutoFocus(msg.arg1 == 0 ? false : true, mCamera); } return; case CAMERA_MSG_ZOOM: if (mZoomCallback != null) { mZoomCallback.onZoomUpdate(msg.arg1, mCamera); } return; case CAMERA_MSG_ERROR : Log.e(TAG, "Error " + msg.arg1); if (mErrorCallback != null) { mErrorCallback.onError(msg.arg1, mCamera); } return; default: Log.e(TAG, "Unknown message type " + msg.what); return; } } } private static void postEventFromNative(Object camera_ref, int what, int arg1, int arg2, Object obj) { Camera c = (Camera)((WeakReference)camera_ref).get(); if (c == null) return; if (c.mEventHandler != null) { Message m = c.mEventHandler.obtainMessage(what, arg1, arg2, obj); c.mEventHandler.sendMessage(m); } } /** * Handles the callback for the camera auto focus. *Devices that do not support auto-focus will receive a "fake" * callback to this interface. If your application needs auto-focus and * should not be installed on devices without auto-focus, you must * declare that your app uses the * {@code android.hardware.camera.autofocus} feature, in the * <uses-feature> * manifest element.
*/ public interface AutoFocusCallback { /** * Callback for the camera auto focus. If the camera does not support * auto-focus and autoFocus is called, onAutoFocus will be called * immediately with success. * * @param success true if focus was successful, false if otherwise * @param camera the Camera service object */ void onAutoFocus(boolean success, Camera camera); }; /** * Starts auto-focus function and registers a callback function to run when * camera is focused. Only valid after startPreview() has been called. * Applications should call {@link * android.hardware.Camera.Parameters#getFocusMode()} to determine if this * method should be called. If the camera does not support auto-focus, it is * a no-op and {@link AutoFocusCallback#onAutoFocus(boolean, Camera)} * callback will be called immediately. *If your application should not be installed * on devices without auto-focus, you must declare that your application * uses auto-focus with the * <uses-feature> * manifest element.
* * @param cb the callback to run */ public final void autoFocus(AutoFocusCallback cb) { mAutoFocusCallback = cb; native_autoFocus(); } private native final void native_autoFocus(); /** * Cancels auto-focus function. If the auto-focus is still in progress, * this function will cancel it. Whether the auto-focus is in progress * or not, this function will return the focus position to the default. * If the camera does not support auto-focus, this is a no-op. */ public final void cancelAutoFocus() { mAutoFocusCallback = null; native_cancelAutoFocus(); } private native final void native_cancelAutoFocus(); /** * An interface which contains a callback for the shutter closing after taking a picture. */ public interface ShutterCallback { /** * Can be used to play a shutter sound as soon as the image has been captured, but before * the data is available. */ void onShutter(); } /** * Handles the callback for when a picture is taken. */ public interface PictureCallback { /** * Callback for when a picture is taken. * * @param data a byte array of the picture data * @param camera the Camera service object */ void onPictureTaken(byte[] data, Camera camera); }; /** * Triggers an asynchronous image capture. The camera service will initiate * a series of callbacks to the application as the image capture progresses. * The shutter callback occurs after the image is captured. This can be used * to trigger a sound to let the user know that image has been captured. The * raw callback occurs when the raw image data is available (NOTE: the data * may be null if the hardware does not have enough memory to make a copy). * The jpeg callback occurs when the compressed image is available. If the * application does not need a particular callback, a null can be passed * instead of a callback method. * * @param shutter callback after the image is captured, may be null * @param raw callback with raw image data, may be null * @param jpeg callback with jpeg image data, may be null */ public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg) { takePicture(shutter, raw, null, jpeg); } private native final void native_takePicture(); /** * Triggers an asynchronous image capture. The camera service will initiate * a series of callbacks to the application as the image capture progresses. * The shutter callback occurs after the image is captured. This can be used * to trigger a sound to let the user know that image has been captured. The * raw callback occurs when the raw image data is available (NOTE: the data * may be null if the hardware does not have enough memory to make a copy). * The postview callback occurs when a scaled, fully processed postview * image is available (NOTE: not all hardware supports this). The jpeg * callback occurs when the compressed image is available. If the * application does not need a particular callback, a null can be passed * instead of a callback method. * * @param shutter callback after the image is captured, may be null * @param raw callback with raw image data, may be null * @param postview callback with postview image data, may be null * @param jpeg callback with jpeg image data, may be null */ public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback postview, PictureCallback jpeg) { mShutterCallback = shutter; mRawImageCallback = raw; mPostviewCallback = postview; mJpegCallback = jpeg; native_takePicture(); } /** * Handles the zoom callback. */ public interface ZoomCallback { /** * Callback for zoom updates * @param zoomLevel new zoom level in 1/1000 increments, * e.g. a zoom of 3.2x is stored as 3200. Accuracy of the * value is dependent on the hardware implementation. Not * all devices will generate this callback. * @param camera the Camera service object */ void onZoomUpdate(int zoomLevel, Camera camera); }; /** * Registers a callback to be invoked when the zoom * level is updated by the camera driver. * @param cb the callback to run */ public final void setZoomCallback(ZoomCallback cb) { mZoomCallback = cb; } // These match the enum in include/ui/Camera.h /** Unspecified camerar error. @see #ErrorCallback */ public static final int CAMERA_ERROR_UNKNOWN = 1; /** Media server died. In this case, the application must release the * Camera object and instantiate a new one. @see #ErrorCallback */ public static final int CAMERA_ERROR_SERVER_DIED = 100; /** * Handles the camera error callback. */ public interface ErrorCallback { /** * Callback for camera errors. * @param error error code: *To make camera parameters take effect, applications have to call * Camera.setParameters. For example, after setWhiteBalance is called, white * balance is not changed until Camera.setParameters() is called. * *
Different devices may have different camera capabilities, such as
* picture size or flash modes. The application should query the camera
* capabilities before setting parameters. For example, the application
* should call getSupportedColorEffects before calling setEffect. If the
* camera does not support color effects, getSupportedColorEffects will
* return null.
*/
public class Parameters {
// Parameter keys to communicate with the camera driver.
private static final String KEY_PREVIEW_SIZE = "preview-size";
private static final String KEY_PREVIEW_FORMAT = "preview-format";
private static final String KEY_PREVIEW_FRAME_RATE = "preview-frame-rate";
private static final String KEY_PICTURE_SIZE = "picture-size";
private static final String KEY_PICTURE_FORMAT = "picture-format";
private static final String KEY_JPEG_THUMBNAIL_WIDTH = "jpeg-thumbnail-width";
private static final String KEY_JPEG_THUMBNAIL_HEIGHT = "jpeg-thumbnail-height";
private static final String KEY_JPEG_THUMBNAIL_QUALITY = "jpeg-thumbnail-quality";
private static final String KEY_JPEG_QUALITY = "jpeg-quality";
private static final String KEY_ROTATION = "rotation";
private static final String KEY_GPS_LATITUDE = "gps-latitude";
private static final String KEY_GPS_LONGITUDE = "gps-longitude";
private static final String KEY_GPS_ALTITUDE = "gps-altitude";
private static final String KEY_GPS_TIMESTAMP = "gps-timestamp";
private static final String KEY_WHITE_BALANCE = "whitebalance";
private static final String KEY_EFFECT = "effect";
private static final String KEY_ANTIBANDING = "antibanding";
private static final String KEY_SCENE_MODE = "scene-mode";
private static final String KEY_FLASH_MODE = "flash-mode";
private static final String KEY_FOCUS_MODE = "focus-mode";
// Parameter key suffix for supported values.
private static final String SUPPORTED_VALUES_SUFFIX = "-values";
// Values for white balance settings.
public static final String WHITE_BALANCE_AUTO = "auto";
public static final String WHITE_BALANCE_INCANDESCENT = "incandescent";
public static final String WHITE_BALANCE_FLUORESCENT = "fluorescent";
public static final String WHITE_BALANCE_WARM_FLUORESCENT = "warm-fluorescent";
public static final String WHITE_BALANCE_DAYLIGHT = "daylight";
public static final String WHITE_BALANCE_CLOUDY_DAYLIGHT = "cloudy-daylight";
public static final String WHITE_BALANCE_TWILIGHT = "twilight";
public static final String WHITE_BALANCE_SHADE = "shade";
// Values for color effect settings.
public static final String EFFECT_NONE = "none";
public static final String EFFECT_MONO = "mono";
public static final String EFFECT_NEGATIVE = "negative";
public static final String EFFECT_SOLARIZE = "solarize";
public static final String EFFECT_SEPIA = "sepia";
public static final String EFFECT_POSTERIZE = "posterize";
public static final String EFFECT_WHITEBOARD = "whiteboard";
public static final String EFFECT_BLACKBOARD = "blackboard";
public static final String EFFECT_AQUA = "aqua";
// Values for antibanding settings.
public static final String ANTIBANDING_AUTO = "auto";
public static final String ANTIBANDING_50HZ = "50hz";
public static final String ANTIBANDING_60HZ = "60hz";
public static final String ANTIBANDING_OFF = "off";
// Values for flash mode settings.
/**
* Flash will not be fired.
*/
public static final String FLASH_MODE_OFF = "off";
/**
* Flash will be fired automatically when required. The timing is
* decided by camera driver.
*/
public static final String FLASH_MODE_AUTO = "auto";
/**
* Flash will always be fired. The timing is decided by camera driver.
*/
public static final String FLASH_MODE_ON = "on";
/**
* Flash will be fired in red-eye reduction mode.
*/
public static final String FLASH_MODE_RED_EYE = "red-eye";
/**
* Constant emission of light. This can be used for video recording.
*/
public static final String FLASH_MODE_VIDEO_LIGHT = "video-light";
// Values for scene mode settings.
public static final String SCENE_MODE_AUTO = "auto";
public static final String SCENE_MODE_ACTION = "action";
public static final String SCENE_MODE_PORTRAIT = "portrait";
public static final String SCENE_MODE_LANDSCAPE = "landscape";
public static final String SCENE_MODE_NIGHT = "night";
public static final String SCENE_MODE_NIGHT_PORTRAIT = "night-portrait";
public static final String SCENE_MODE_THEATRE = "theatre";
public static final String SCENE_MODE_BEACH = "beach";
public static final String SCENE_MODE_SNOW = "snow";
public static final String SCENE_MODE_SUNSET = "sunset";
public static final String SCENE_MODE_STEADYPHOTO = "steadyphoto";
public static final String SCENE_MODE_FIREWORKS = "fireworks";
public static final String SCENE_MODE_SPORTS = "sports";
public static final String SCENE_MODE_PARTY = "party";
public static final String SCENE_MODE_CANDLELIGHT = "candlelight";
// Values for focus mode settings.
/**
* Auto-focus mode.
*/
public static final String FOCUS_MODE_AUTO = "auto";
/**
* Focus is set at infinity. Applications should not call
* {@link #autoFocus(AutoFocusCallback)} in this mode.
*/
public static final String FOCUS_MODE_INFINITY = "infinity";
public static final String FOCUS_MODE_MACRO = "macro";
/**
* Focus is fixed. The camera is always in this mode if the focus is not
* adjustable. If the camera has auto-focus, this mode can fix the
* focus, which is usually at hyperfocal distance. Applications should
* not call {@link #autoFocus(AutoFocusCallback)} in this mode.
*/
public static final String FOCUS_MODE_FIXED = "fixed";
// Formats for setPreviewFormat and setPictureFormat.
private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp";
private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp";
private static final String PIXEL_FORMAT_YUV422I = "yuv422i-yuyv";
private static final String PIXEL_FORMAT_RGB565 = "rgb565";
private static final String PIXEL_FORMAT_JPEG = "jpeg";
private HashMap The {@link #unflatten(String)} method does the reverse. The {@link #flatten()} method does the reverse. If this is never called, the default format will be
* {@link android.graphics.PixelFormat#YCbCr_420_SP}, which
* uses the NV21 encoding format.