Camera.java revision 9b6a8ab8221f2df20c32711b0f1e4f301165fac2
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.hardware;
18
19import java.lang.ref.WeakReference;
20import java.util.ArrayList;
21import java.util.HashMap;
22import java.util.List;
23import java.util.StringTokenizer;
24import java.io.IOException;
25
26import android.util.Log;
27import android.view.Surface;
28import android.view.SurfaceHolder;
29import android.graphics.PixelFormat;
30import android.os.Handler;
31import android.os.Looper;
32import android.os.Message;
33
34/**
35 * The Camera class is used to connect/disconnect with the camera service,
36 * set capture settings, start/stop preview, snap a picture, and retrieve
37 * frames for encoding for video.
38 * <p>There is no default constructor for this class. Use {@link #open()} to
39 * get a Camera object.</p>
40 */
41public class Camera {
42    private static final String TAG = "Camera";
43
44    // These match the enums in frameworks/base/include/ui/Camera.h
45    private static final int CAMERA_MSG_ERROR            = 0x001;
46    private static final int CAMERA_MSG_SHUTTER          = 0x002;
47    private static final int CAMERA_MSG_FOCUS            = 0x004;
48    private static final int CAMERA_MSG_ZOOM             = 0x008;
49    private static final int CAMERA_MSG_PREVIEW_FRAME    = 0x010;
50    private static final int CAMERA_MSG_VIDEO_FRAME      = 0x020;
51    private static final int CAMERA_MSG_POSTVIEW_FRAME   = 0x040;
52    private static final int CAMERA_MSG_RAW_IMAGE        = 0x080;
53    private static final int CAMERA_MSG_COMPRESSED_IMAGE = 0x100;
54    private static final int CAMERA_MSG_ALL_MSGS         = 0x1FF;
55
56    private int mNativeContext; // accessed by native methods
57    private EventHandler mEventHandler;
58    private ShutterCallback mShutterCallback;
59    private PictureCallback mRawImageCallback;
60    private PictureCallback mJpegCallback;
61    private PreviewCallback mPreviewCallback;
62    private PictureCallback mPostviewCallback;
63    private AutoFocusCallback mAutoFocusCallback;
64    private ZoomCallback mZoomCallback;
65    private ErrorCallback mErrorCallback;
66    private boolean mOneShot;
67
68    /**
69     * Returns a new Camera object.
70     */
71    public static Camera open() {
72        return new Camera();
73    }
74
75    Camera() {
76        mShutterCallback = null;
77        mRawImageCallback = null;
78        mJpegCallback = null;
79        mPreviewCallback = null;
80        mPostviewCallback = null;
81        mZoomCallback = null;
82
83        Looper looper;
84        if ((looper = Looper.myLooper()) != null) {
85            mEventHandler = new EventHandler(this, looper);
86        } else if ((looper = Looper.getMainLooper()) != null) {
87            mEventHandler = new EventHandler(this, looper);
88        } else {
89            mEventHandler = null;
90        }
91
92        native_setup(new WeakReference<Camera>(this));
93    }
94
95    protected void finalize() {
96        native_release();
97    }
98
99    private native final void native_setup(Object camera_this);
100    private native final void native_release();
101
102
103    /**
104     * Disconnects and releases the Camera object resources.
105     * <p>It is recommended that you call this as soon as you're done with the
106     * Camera object.</p>
107     */
108    public final void release() {
109        native_release();
110    }
111
112    /**
113     * Reconnect to the camera after passing it to MediaRecorder. To save
114     * setup/teardown time, a client of Camera can pass an initialized Camera
115     * object to a MediaRecorder to use for video recording. Once the
116     * MediaRecorder is done with the Camera, this method can be used to
117     * re-establish a connection with the camera hardware. NOTE: The Camera
118     * object must first be unlocked by the process that owns it before it
119     * can be connected to another process.
120     *
121     * @throws IOException if the method fails.
122     *
123     * FIXME: Unhide after approval
124     * @hide
125     */
126    public native final void reconnect() throws IOException;
127
128    /**
129     * Lock the camera to prevent other processes from accessing it. To save
130     * setup/teardown time, a client of Camera can pass an initialized Camera
131     * object to another process. This method is used to re-lock the Camera
132     * object prevent other processes from accessing it. By default, the
133     * Camera object is locked. Locking it again from the same process will
134     * have no effect. Attempting to lock it from another process if it has
135     * not been unlocked will fail.
136     * Returns 0 if lock was successful.
137     *
138     * FIXME: Unhide after approval
139     * @hide
140     */
141    public native final int lock();
142
143    /**
144     * Unlock the camera to allow another process to access it. To save
145     * setup/teardown time, a client of Camera can pass an initialized Camera
146     * object to another process. This method is used to unlock the Camera
147     * object before handing off the Camera object to the other process.
148
149     * Returns 0 if unlock was successful.
150     *
151     * FIXME: Unhide after approval
152     * @hide
153     */
154    public native final int unlock();
155
156    /**
157     * Sets the SurfaceHolder to be used for a picture preview. If the surface
158     * changed since the last call, the screen will blank. Nothing happens
159     * if the same surface is re-set.
160     *
161     * @param holder the SurfaceHolder upon which to place the picture preview
162     * @throws IOException if the method fails.
163     */
164    public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
165        if (holder != null) {
166            setPreviewDisplay(holder.getSurface());
167        } else {
168            setPreviewDisplay((Surface)null);
169        }
170    }
171
172    private native final void setPreviewDisplay(Surface surface);
173
174    /**
175     * Used to get a copy of each preview frame.
176     */
177    public interface PreviewCallback
178    {
179        /**
180         * The callback that delivers the preview frames.
181         *
182         * @param data The contents of the preview frame in {@link
183         *             android.hardware.Camera.Parameters#getPreviewFormat()}
184         *             format. If {@link
185         *             android.hardware.Camera.Parameters#setPreviewFormat()}
186         *             is never called, the default will be the YCbCr_420_SP
187         *             (NV21) format.
188         * @param camera The Camera service object.
189         */
190        void onPreviewFrame(byte[] data, Camera camera);
191    };
192
193    /**
194     * Start drawing preview frames to the surface.
195     */
196    public native final void startPreview();
197
198    /**
199     * Stop drawing preview frames to the surface.
200     */
201    public native final void stopPreview();
202
203    /**
204     * Return current preview state.
205     *
206     * FIXME: Unhide before release
207     * @hide
208     */
209    public native final boolean previewEnabled();
210
211    /**
212     * Can be called at any time to instruct the camera to use a callback for
213     * each preview frame in addition to displaying it.
214     *
215     * @param cb A callback object that receives a copy of each preview frame.
216     *           Pass null to stop receiving callbacks at any time.
217     */
218    public final void setPreviewCallback(PreviewCallback cb) {
219        mPreviewCallback = cb;
220        mOneShot = false;
221        setHasPreviewCallback(cb != null, false);
222    }
223
224    /**
225     * Installs a callback to retrieve a single preview frame, after which the
226     * callback is cleared.
227     *
228     * @param cb A callback object that receives a copy of the preview frame.
229     */
230    public final void setOneShotPreviewCallback(PreviewCallback cb) {
231        if (cb != null) {
232            mPreviewCallback = cb;
233            mOneShot = true;
234            setHasPreviewCallback(true, true);
235        }
236    }
237
238    private native final void setHasPreviewCallback(boolean installed, boolean oneshot);
239
240    private class EventHandler extends Handler
241    {
242        private Camera mCamera;
243
244        public EventHandler(Camera c, Looper looper) {
245            super(looper);
246            mCamera = c;
247        }
248
249        @Override
250        public void handleMessage(Message msg) {
251            switch(msg.what) {
252            case CAMERA_MSG_SHUTTER:
253                if (mShutterCallback != null) {
254                    mShutterCallback.onShutter();
255                }
256                return;
257
258            case CAMERA_MSG_RAW_IMAGE:
259                if (mRawImageCallback != null) {
260                    mRawImageCallback.onPictureTaken((byte[])msg.obj, mCamera);
261                }
262                return;
263
264            case CAMERA_MSG_COMPRESSED_IMAGE:
265                if (mJpegCallback != null) {
266                    mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera);
267                }
268                return;
269
270            case CAMERA_MSG_PREVIEW_FRAME:
271                if (mPreviewCallback != null) {
272                    mPreviewCallback.onPreviewFrame((byte[])msg.obj, mCamera);
273                    if (mOneShot) {
274                        mPreviewCallback = null;
275                    }
276                }
277                return;
278
279            case CAMERA_MSG_POSTVIEW_FRAME:
280                if (mPostviewCallback != null) {
281                    mPostviewCallback.onPictureTaken((byte[])msg.obj, mCamera);
282                }
283                return;
284
285            case CAMERA_MSG_FOCUS:
286                if (mAutoFocusCallback != null) {
287                    mAutoFocusCallback.onAutoFocus(msg.arg1 == 0 ? false : true, mCamera);
288                }
289                return;
290
291            case CAMERA_MSG_ZOOM:
292                if (mZoomCallback != null) {
293                    mZoomCallback.onZoomUpdate(msg.arg1, mCamera);
294                }
295                return;
296
297            case CAMERA_MSG_ERROR :
298                Log.e(TAG, "Error " + msg.arg1);
299                if (mErrorCallback != null) {
300                    mErrorCallback.onError(msg.arg1, mCamera);
301                }
302                return;
303
304            default:
305                Log.e(TAG, "Unknown message type " + msg.what);
306                return;
307            }
308        }
309    }
310
311    private static void postEventFromNative(Object camera_ref,
312                                            int what, int arg1, int arg2, Object obj)
313    {
314        Camera c = (Camera)((WeakReference)camera_ref).get();
315        if (c == null)
316            return;
317
318        if (c.mEventHandler != null) {
319            Message m = c.mEventHandler.obtainMessage(what, arg1, arg2, obj);
320            c.mEventHandler.sendMessage(m);
321        }
322    }
323
324    /**
325     * Handles the callback for the camera auto focus.
326     */
327    public interface AutoFocusCallback
328    {
329        /**
330         * Callback for the camera auto focus. If the camera does not support
331         * auto-focus and autoFocus is called, onAutoFocus will be called
332         * immediately with success.
333         *
334         * @param success true if focus was successful, false if otherwise
335         * @param camera  the Camera service object
336         */
337        void onAutoFocus(boolean success, Camera camera);
338    };
339
340    /**
341     * Starts auto-focus function and registers a callback function to run when
342     * camera is focused. Only valid after startPreview() has been called. If
343     * the camera does not support auto-focus, it is a no-op and {@link
344     * AutoFocusCallback#onAutoFocus} callback will be called immediately.
345     *
346     * @param cb the callback to run
347     */
348    public final void autoFocus(AutoFocusCallback cb)
349    {
350        mAutoFocusCallback = cb;
351        native_autoFocus();
352    }
353    private native final void native_autoFocus();
354
355    /**
356     * An interface which contains a callback for the shutter closing after taking a picture.
357     */
358    public interface ShutterCallback
359    {
360        /**
361         * Can be used to play a shutter sound as soon as the image has been captured, but before
362         * the data is available.
363         */
364        void onShutter();
365    }
366
367    /**
368     * Handles the callback for when a picture is taken.
369     */
370    public interface PictureCallback {
371        /**
372         * Callback for when a picture is taken.
373         *
374         * @param data   a byte array of the picture data
375         * @param camera the Camera service object
376         */
377        void onPictureTaken(byte[] data, Camera camera);
378    };
379
380    /**
381     * Triggers an asynchronous image capture. The camera service will initiate
382     * a series of callbacks to the application as the image capture progresses.
383     * The shutter callback occurs after the image is captured. This can be used
384     * to trigger a sound to let the user know that image has been captured. The
385     * raw callback occurs when the raw image data is available (NOTE: the data
386     * may be null if the hardware does not have enough memory to make a copy).
387     * The jpeg callback occurs when the compressed image is available. If the
388     * application does not need a particular callback, a null can be passed
389     * instead of a callback method.
390     *
391     * @param shutter   callback after the image is captured, may be null
392     * @param raw       callback with raw image data, may be null
393     * @param jpeg      callback with jpeg image data, may be null
394     */
395    public final void takePicture(ShutterCallback shutter, PictureCallback raw,
396            PictureCallback jpeg) {
397        takePicture(shutter, raw, null, jpeg);
398    }
399    private native final void native_takePicture();
400
401    /**
402     * Triggers an asynchronous image capture. The camera service will initiate
403     * a series of callbacks to the application as the image capture progresses.
404     * The shutter callback occurs after the image is captured. This can be used
405     * to trigger a sound to let the user know that image has been captured. The
406     * raw callback occurs when the raw image data is available (NOTE: the data
407     * may be null if the hardware does not have enough memory to make a copy).
408     * The postview callback occurs when a scaled, fully processed postview
409     * image is available (NOTE: not all hardware supports this). The jpeg
410     * callback occurs when the compressed image is available. If the
411     * application does not need a particular callback, a null can be passed
412     * instead of a callback method.
413     *
414     * @param shutter   callback after the image is captured, may be null
415     * @param raw       callback with raw image data, may be null
416     * @param postview  callback with postview image data, may be null
417     * @param jpeg      callback with jpeg image data, may be null
418     */
419    public final void takePicture(ShutterCallback shutter, PictureCallback raw,
420            PictureCallback postview, PictureCallback jpeg) {
421        mShutterCallback = shutter;
422        mRawImageCallback = raw;
423        mPostviewCallback = postview;
424        mJpegCallback = jpeg;
425        native_takePicture();
426    }
427
428    /**
429     * Handles the zoom callback.
430     */
431    public interface ZoomCallback
432    {
433        /**
434         * Callback for zoom updates
435         * @param zoomLevel   new zoom level in 1/1000 increments,
436         * e.g. a zoom of 3.2x is stored as 3200. Accuracy of the
437         * value is dependent on the hardware implementation. Not
438         * all devices will generate this callback.
439         * @param camera  the Camera service object
440         */
441        void onZoomUpdate(int zoomLevel, Camera camera);
442    };
443
444    /**
445     * Registers a callback to be invoked when the zoom
446     * level is updated by the camera driver.
447     * @param cb the callback to run
448     */
449    public final void setZoomCallback(ZoomCallback cb)
450    {
451        mZoomCallback = cb;
452    }
453
454    // These match the enum in include/ui/Camera.h
455    /** Unspecified camerar error.  @see #ErrorCallback */
456    public static final int CAMERA_ERROR_UNKNOWN = 1;
457    /** Media server died. In this case, the application must release the
458     * Camera object and instantiate a new one. @see #ErrorCallback */
459    public static final int CAMERA_ERROR_SERVER_DIED = 100;
460
461    /**
462     * Handles the camera error callback.
463     */
464    public interface ErrorCallback
465    {
466        /**
467         * Callback for camera errors.
468         * @param error   error code:
469         * <ul>
470         * <li>{@link #CAMERA_ERROR_UNKNOWN}
471         * <li>{@link #CAMERA_ERROR_SERVER_DIED}
472         * </ul>
473         * @param camera  the Camera service object
474         */
475        void onError(int error, Camera camera);
476    };
477
478    /**
479     * Registers a callback to be invoked when an error occurs.
480     * @param cb the callback to run
481     */
482    public final void setErrorCallback(ErrorCallback cb)
483    {
484        mErrorCallback = cb;
485    }
486
487    private native final void native_setParameters(String params);
488    private native final String native_getParameters();
489
490    /**
491     * Sets the Parameters for pictures from this Camera service.
492     *
493     * @param params the Parameters to use for this Camera service
494     */
495    public void setParameters(Parameters params) {
496        native_setParameters(params.flatten());
497    }
498
499    /**
500     * Returns the picture Parameters for this Camera service.
501     */
502    public Parameters getParameters() {
503        Parameters p = new Parameters();
504        String s = native_getParameters();
505        p.unflatten(s);
506        return p;
507    }
508
509    /**
510     * Handles the picture size (dimensions).
511     */
512    public class Size {
513        /**
514         * Sets the dimensions for pictures.
515         *
516         * @param w the photo width (pixels)
517         * @param h the photo height (pixels)
518         */
519        public Size(int w, int h) {
520            width = w;
521            height = h;
522        }
523        /** width of the picture */
524        public int width;
525        /** height of the picture */
526        public int height;
527    };
528
529    /**
530     * Handles the parameters for pictures created by a Camera service.
531     *
532     * <p>To make camera parameters take effect, applications have to call
533     * Camera.setParameters. For example, after setWhiteBalance is called, white
534     * balance is not changed until Camera.setParameters() is called.
535     *
536     * <p>Different devices may have different camera capabilities, such as
537     * picture size or flash modes. The application should query the camera
538     * capabilities before setting parameters. For example, the application
539     * should call getSupportedColorEffects before calling setEffect. If the
540     * camera does not support color effects, getSupportedColorEffects will
541     * return null.
542     */
543    public class Parameters {
544        // Parameter keys to communicate with the camera driver.
545        private static final String KEY_PREVIEW_SIZE = "preview-size";
546        private static final String KEY_PREVIEW_FORMAT = "preview-format";
547        private static final String KEY_PREVIEW_FRAME_RATE = "preview-frame-rate";
548        private static final String KEY_PICTURE_SIZE = "picture-size";
549        private static final String KEY_PICTURE_FORMAT = "picture-format";
550        private static final String KEY_JPEG_THUMBNAIL_WIDTH = "jpeg-thumbnail-width";
551        private static final String KEY_JPEG_THUMBNAIL_HEIGHT = "jpeg-thumbnail-height";
552        private static final String KEY_JPEG_THUMBNAIL_QUALITY = "jpeg-thumbnail-quality";
553        private static final String KEY_JPEG_QUALITY = "jpeg-quality";
554        private static final String KEY_ROTATION = "rotation";
555        private static final String KEY_GPS_LATITUDE = "gps-latitude";
556        private static final String KEY_GPS_LONGITUDE = "gps-longitude";
557        private static final String KEY_GPS_ALTITUDE = "gps-altitude";
558        private static final String KEY_GPS_TIMESTAMP = "gps-timestamp";
559        private static final String KEY_WHITE_BALANCE = "whitebalance";
560        private static final String KEY_EFFECT = "effect";
561        private static final String KEY_ANTIBANDING = "antibanding";
562        private static final String KEY_SCENE_MODE = "scene-mode";
563        private static final String KEY_FLASH_MODE = "flash-mode";
564        // Parameter key suffix for supported values.
565        private static final String SUPPORTED_VALUES_SUFFIX = "-values";
566
567        // Values for white balance settings.
568        public static final String WHITE_BALANCE_AUTO = "auto";
569        public static final String WHITE_BALANCE_INCANDESCENT = "incandescent";
570        public static final String WHITE_BALANCE_FLUORESCENT = "fluorescent";
571        public static final String WHITE_BALANCE_WARM_FLUORESCENT = "warm-fluorescent";
572        public static final String WHITE_BALANCE_DAYLIGHT = "daylight";
573        public static final String WHITE_BALANCE_CLOUDY_DAYLIGHT = "cloudy-daylight";
574        public static final String WHITE_BALANCE_TWILIGHT = "twilight";
575        public static final String WHITE_BALANCE_SHADE = "shade";
576
577        // Values for color effect settings.
578        public static final String EFFECT_NONE = "none";
579        public static final String EFFECT_MONO = "mono";
580        public static final String EFFECT_NEGATIVE = "negative";
581        public static final String EFFECT_SOLARIZE = "solarize";
582        public static final String EFFECT_SEPIA = "sepia";
583        public static final String EFFECT_POSTERIZE = "posterize";
584        public static final String EFFECT_WHITEBOARD = "whiteboard";
585        public static final String EFFECT_BLACKBOARD = "blackboard";
586        public static final String EFFECT_AQUA = "aqua";
587
588        // Values for antibanding settings.
589        public static final String ANTIBANDING_AUTO = "auto";
590        public static final String ANTIBANDING_50HZ = "50hz";
591        public static final String ANTIBANDING_60HZ = "60hz";
592        public static final String ANTIBANDING_OFF = "off";
593
594        // Values for flash mode settings.
595        /**
596         * Flash will not be fired.
597         */
598        public static final String FLASH_MODE_OFF = "off";
599        /**
600         * Flash will be fired automatically when required. The timing is
601         * decided by camera driver.
602         */
603        public static final String FLASH_MODE_AUTO = "auto";
604        /**
605         * Flash will always be fired. The timing is decided by camera driver.
606         */
607        public static final String FLASH_MODE_ON = "on";
608        /**
609         * Flash will be fired in red-eye reduction mode.
610         */
611        public static final String FLASH_MODE_RED_EYE = "red-eye";
612
613        // Values for scene mode settings.
614        public static final String SCENE_MODE_AUTO = "auto";
615        public static final String SCENE_MODE_ACTION = "action";
616        public static final String SCENE_MODE_PORTRAIT = "portrait";
617        public static final String SCENE_MODE_LANDSCAPE = "landscape";
618        public static final String SCENE_MODE_NIGHT = "night";
619        public static final String SCENE_MODE_NIGHT_PORTRAIT = "night-portrait";
620        public static final String SCENE_MODE_THEATRE = "theatre";
621        public static final String SCENE_MODE_BEACH = "beach";
622        public static final String SCENE_MODE_SNOW = "snow";
623        public static final String SCENE_MODE_SUNSET = "sunset";
624        public static final String SCENE_MODE_STEADYPHOTO = "steadyphoto";
625        public static final String SCENE_MODE_FIREWORKS = "fireworks";
626        public static final String SCENE_MODE_SPORTS = "sports";
627        public static final String SCENE_MODE_PARTY = "party";
628        public static final String SCENE_MODE_CANDLELIGHT = "candlelight";
629
630        // Formats for setPreviewFormat and setPictureFormat.
631        private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp";
632        private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp";
633        private static final String PIXEL_FORMAT_RGB565 = "rgb565";
634        private static final String PIXEL_FORMAT_JPEG = "jpeg";
635
636        private HashMap<String, String> mMap;
637
638        private Parameters() {
639            mMap = new HashMap<String, String>();
640        }
641
642        /**
643         * Writes the current Parameters to the log.
644         * @hide
645         * @deprecated
646         */
647        public void dump() {
648            Log.e(TAG, "dump: size=" + mMap.size());
649            for (String k : mMap.keySet()) {
650                Log.e(TAG, "dump: " + k + "=" + mMap.get(k));
651            }
652        }
653
654        /**
655         * Creates a single string with all the parameters set in
656         * this Parameters object.
657         * <p>The {@link #unflatten(String)} method does the reverse.</p>
658         *
659         * @return a String with all values from this Parameters object, in
660         *         semi-colon delimited key-value pairs
661         */
662        public String flatten() {
663            StringBuilder flattened = new StringBuilder();
664            for (String k : mMap.keySet()) {
665                flattened.append(k);
666                flattened.append("=");
667                flattened.append(mMap.get(k));
668                flattened.append(";");
669            }
670            // chop off the extra semicolon at the end
671            flattened.deleteCharAt(flattened.length()-1);
672            return flattened.toString();
673        }
674
675        /**
676         * Takes a flattened string of parameters and adds each one to
677         * this Parameters object.
678         * <p>The {@link #flatten()} method does the reverse.</p>
679         *
680         * @param flattened a String of parameters (key-value paired) that
681         *                  are semi-colon delimited
682         */
683        public void unflatten(String flattened) {
684            mMap.clear();
685
686            StringTokenizer tokenizer = new StringTokenizer(flattened, ";");
687            while (tokenizer.hasMoreElements()) {
688                String kv = tokenizer.nextToken();
689                int pos = kv.indexOf('=');
690                if (pos == -1) {
691                    continue;
692                }
693                String k = kv.substring(0, pos);
694                String v = kv.substring(pos + 1);
695                mMap.put(k, v);
696            }
697        }
698
699        public void remove(String key) {
700            mMap.remove(key);
701        }
702
703        /**
704         * Sets a String parameter.
705         *
706         * @param key   the key name for the parameter
707         * @param value the String value of the parameter
708         */
709        public void set(String key, String value) {
710            if (key.indexOf('=') != -1 || key.indexOf(';') != -1) {
711                Log.e(TAG, "Key \"" + key + "\" contains invalid character (= or ;)");
712                return;
713            }
714            if (value.indexOf('=') != -1 || value.indexOf(';') != -1) {
715                Log.e(TAG, "Value \"" + value + "\" contains invalid character (= or ;)");
716                return;
717            }
718
719            mMap.put(key, value);
720        }
721
722        /**
723         * Sets an integer parameter.
724         *
725         * @param key   the key name for the parameter
726         * @param value the int value of the parameter
727         */
728        public void set(String key, int value) {
729            mMap.put(key, Integer.toString(value));
730        }
731
732        /**
733         * Returns the value of a String parameter.
734         *
735         * @param key the key name for the parameter
736         * @return the String value of the parameter
737         */
738        public String get(String key) {
739            return mMap.get(key);
740        }
741
742        /**
743         * Returns the value of an integer parameter.
744         *
745         * @param key the key name for the parameter
746         * @return the int value of the parameter
747         */
748        public int getInt(String key) {
749            return Integer.parseInt(mMap.get(key));
750        }
751
752        /**
753         * Sets the dimensions for preview pictures.
754         *
755         * @param width  the width of the pictures, in pixels
756         * @param height the height of the pictures, in pixels
757         */
758        public void setPreviewSize(int width, int height) {
759            String v = Integer.toString(width) + "x" + Integer.toString(height);
760            set(KEY_PREVIEW_SIZE, v);
761        }
762
763        /**
764         * Returns the dimensions setting for preview pictures.
765         *
766         * @return a Size object with the height and width setting
767         *          for the preview picture
768         */
769        public Size getPreviewSize() {
770            String pair = get(KEY_PREVIEW_SIZE);
771            return strToSize(pair);
772        }
773
774        /**
775         * Gets the supported preview sizes.
776         *
777         * @return a List of Size object. null if preview size setting is not
778         *         supported.
779         */
780        public List<Size> getSupportedPreviewSizes() {
781            String str = get(KEY_PREVIEW_SIZE + SUPPORTED_VALUES_SUFFIX);
782            return splitSize(str);
783        }
784
785        /**
786         * Sets the dimensions for EXIF thumbnail in Jpeg picture.
787         *
788         * @param width  the width of the thumbnail, in pixels
789         * @param height the height of the thumbnail, in pixels
790         */
791        public void setJpegThumbnailSize(int width, int height) {
792            set(KEY_JPEG_THUMBNAIL_WIDTH, width);
793            set(KEY_JPEG_THUMBNAIL_HEIGHT, height);
794        }
795
796        /**
797         * Returns the dimensions for EXIF thumbnail in Jpeg picture.
798         *
799         * @return a Size object with the height and width setting for the EXIF
800         *         thumbnails
801         */
802        public Size getJpegThumbnailSize() {
803            return new Size(getInt(KEY_JPEG_THUMBNAIL_WIDTH),
804                            getInt(KEY_JPEG_THUMBNAIL_HEIGHT));
805        }
806
807        /**
808         * Sets the quality of the EXIF thumbnail in Jpeg picture.
809         *
810         * @param quality the JPEG quality of the EXIF thumbnail. The range is 1
811         *                to 100, with 100 being the best.
812         */
813        public void setJpegThumbnailQuality(int quality) {
814            set(KEY_JPEG_THUMBNAIL_QUALITY, quality);
815        }
816
817        /**
818         * Returns the quality setting for the EXIF thumbnail in Jpeg picture.
819         *
820         * @return the JPEG quality setting of the EXIF thumbnail.
821         */
822        public int getJpegThumbnailQuality() {
823            return getInt(KEY_JPEG_THUMBNAIL_QUALITY);
824        }
825
826        /**
827         * Sets Jpeg quality of captured picture.
828         *
829         * @param quality the JPEG quality of captured picture. The range is 1
830         *                to 100, with 100 being the best.
831         */
832        public void setJpegQuality(int quality) {
833            set(KEY_JPEG_QUALITY, quality);
834        }
835
836        /**
837         * Returns the quality setting for the JPEG picture.
838         *
839         * @return the JPEG picture quality setting.
840         */
841        public int getJpegQuality() {
842            return getInt(KEY_JPEG_QUALITY);
843        }
844
845        /**
846         * Sets the rate at which preview frames are received.
847         *
848         * @param fps the frame rate (frames per second)
849         */
850        public void setPreviewFrameRate(int fps) {
851            set(KEY_PREVIEW_FRAME_RATE, fps);
852        }
853
854        /**
855         * Returns the setting for the rate at which preview frames
856         * are received.
857         *
858         * @return the frame rate setting (frames per second)
859         */
860        public int getPreviewFrameRate() {
861            return getInt(KEY_PREVIEW_FRAME_RATE);
862        }
863
864        /**
865         * Gets the supported preview frame rates.
866         *
867         * @return a List of Integer objects (preview frame rates). null if
868         *         preview frame rate setting is not supported.
869         */
870        public List<Integer> getSupportedPreviewFrameRates() {
871            String str = get(KEY_PREVIEW_FRAME_RATE + SUPPORTED_VALUES_SUFFIX);
872            return splitInt(str);
873        }
874
875        /**
876         * Sets the image format for preview pictures. If this is never called,
877         * the default will be the YCbCr_420_SP (NV21) format.
878         *
879         * @param pixel_format the desired preview picture format
880         *                     (<var>PixelFormat.YCbCr_420_SP (NV21)</var>,
881         *                      <var>PixelFormat.RGB_565</var>, or
882         *                      <var>PixelFormat.JPEG</var>)
883         * @see android.graphics.PixelFormat
884         */
885        public void setPreviewFormat(int pixel_format) {
886            String s = cameraFormatForPixelFormat(pixel_format);
887            if (s == null) {
888                throw new IllegalArgumentException(
889                        "Invalid pixel_format=" + pixel_format);
890            }
891
892            set(KEY_PREVIEW_FORMAT, s);
893        }
894
895        /**
896         * Returns the image format for preview pictures got from
897         * {@link PreviewCallback}.
898         *
899         * @return the PixelFormat int representing the preview picture format
900         * @see android.graphics.PixelFormat
901         */
902        public int getPreviewFormat() {
903            return pixelFormatForCameraFormat(get(KEY_PREVIEW_FORMAT));
904        }
905
906        /**
907         * Gets the supported preview formats.
908         *
909         * @return a List of Integer objects. null if preview format setting is
910         *         not supported.
911         */
912        public List<Integer> getSupportedPreviewFormats() {
913            String str = get(KEY_PREVIEW_FORMAT + SUPPORTED_VALUES_SUFFIX);
914            return splitInt(str);
915        }
916
917        /**
918         * Sets the dimensions for pictures.
919         *
920         * @param width  the width for pictures, in pixels
921         * @param height the height for pictures, in pixels
922         */
923        public void setPictureSize(int width, int height) {
924            String v = Integer.toString(width) + "x" + Integer.toString(height);
925            set(KEY_PICTURE_SIZE, v);
926        }
927
928        /**
929         * Returns the dimension setting for pictures.
930         *
931         * @return a Size object with the height and width setting
932         *          for pictures
933         */
934        public Size getPictureSize() {
935            String pair = get(KEY_PICTURE_SIZE);
936            return strToSize(pair);
937        }
938
939        /**
940         * Gets the supported picture sizes.
941         *
942         * @return a List of Size objects. null if picture size setting is not
943         *         supported.
944         */
945        public List<Size> getSupportedPictureSizes() {
946            String str = get(KEY_PICTURE_SIZE + SUPPORTED_VALUES_SUFFIX);
947            return splitSize(str);
948        }
949
950        /**
951         * Sets the image format for pictures.
952         *
953         * @param pixel_format the desired picture format
954         *                     (<var>PixelFormat.YCbCr_420_SP (NV21)</var>,
955         *                      <var>PixelFormat.RGB_565</var>, or
956         *                      <var>PixelFormat.JPEG</var>)
957         * @see android.graphics.PixelFormat
958         */
959        public void setPictureFormat(int pixel_format) {
960            String s = cameraFormatForPixelFormat(pixel_format);
961            if (s == null) {
962                throw new IllegalArgumentException(
963                        "Invalid pixel_format=" + pixel_format);
964            }
965
966            set(KEY_PICTURE_FORMAT, s);
967        }
968
969        /**
970         * Returns the image format for pictures.
971         *
972         * @return the PixelFormat int representing the picture format
973         */
974        public int getPictureFormat() {
975            return pixelFormatForCameraFormat(get(KEY_PICTURE_FORMAT));
976        }
977
978        /**
979         * Gets the supported picture formats.
980         *
981         * @return a List of Integer objects (values are PixelFormat.XXX). null
982         *         if picture setting is not supported.
983         */
984        public List<Integer> getSupportedPictureFormats() {
985            String str = get(KEY_PICTURE_SIZE + SUPPORTED_VALUES_SUFFIX);
986            return splitInt(str);
987        }
988
989        private String cameraFormatForPixelFormat(int pixel_format) {
990            switch(pixel_format) {
991            case PixelFormat.YCbCr_422_SP: return PIXEL_FORMAT_YUV422SP;
992            case PixelFormat.YCbCr_420_SP: return PIXEL_FORMAT_YUV420SP;
993            case PixelFormat.RGB_565:      return PIXEL_FORMAT_RGB565;
994            case PixelFormat.JPEG:         return PIXEL_FORMAT_JPEG;
995            default:                       return null;
996            }
997        }
998
999        private int pixelFormatForCameraFormat(String format) {
1000            if (format == null)
1001                return PixelFormat.UNKNOWN;
1002
1003            if (format.equals(PIXEL_FORMAT_YUV422SP))
1004                return PixelFormat.YCbCr_422_SP;
1005
1006            if (format.equals(PIXEL_FORMAT_YUV420SP))
1007                return PixelFormat.YCbCr_420_SP;
1008
1009            if (format.equals(PIXEL_FORMAT_RGB565))
1010                return PixelFormat.RGB_565;
1011
1012            if (format.equals(PIXEL_FORMAT_JPEG))
1013                return PixelFormat.JPEG;
1014
1015            return PixelFormat.UNKNOWN;
1016        }
1017
1018        /**
1019         * Sets the orientation of the device in degrees, which instructs the
1020         * camera driver to rotate the picture and thumbnail, in order to match
1021         * what the user sees from the viewfinder. For example, suppose the
1022         * natural position of the device is landscape. If the user takes a
1023         * picture in landscape mode in 2048x1536 resolution, the rotation
1024         * should be set to 0. If the user rotates the phone 90 degrees
1025         * clockwise, the rotation should be set to 90. Applications can use
1026         * {@link android.view.OrientationEventListener} to set this parameter.
1027         *
1028         * Since the picture is rotated, the orientation in the EXIF header is
1029         * missing or always 1 (row #0 is top and column #0 is left side).
1030         *
1031         * @param rotation The orientation of the device in degrees. Rotation
1032         *                 can only be 0, 90, 180 or 270.
1033         * @throws IllegalArgumentException if rotation value is invalid.
1034         * @see android.view.OrientationEventListener
1035         */
1036        public void setRotation(int rotation) {
1037            if (rotation == 0 || rotation == 90 || rotation == 180
1038                    || rotation == 270) {
1039                set(KEY_ROTATION, Integer.toString(rotation));
1040            } else {
1041                throw new IllegalArgumentException(
1042                        "Invalid rotation=" + rotation);
1043            }
1044        }
1045
1046        /**
1047         * Sets GPS latitude coordinate. This will be stored in JPEG EXIF
1048         * header.
1049         *
1050         * @param latitude GPS latitude coordinate.
1051         */
1052        public void setGpsLatitude(double latitude) {
1053            set(KEY_GPS_LATITUDE, Double.toString(latitude));
1054        }
1055
1056        /**
1057         * Sets GPS longitude coordinate. This will be stored in JPEG EXIF
1058         * header.
1059         *
1060         * @param longitude GPS longitude coordinate.
1061         */
1062        public void setGpsLongitude(double longitude) {
1063            set(KEY_GPS_LONGITUDE, Double.toString(longitude));
1064        }
1065
1066        /**
1067         * Sets GPS altitude. This will be stored in JPEG EXIF header.
1068         *
1069         * @param altitude GPS altitude in meters.
1070         */
1071        public void setGpsAltitude(double altitude) {
1072            set(KEY_GPS_ALTITUDE, Double.toString(altitude));
1073        }
1074
1075        /**
1076         * Sets GPS timestamp. This will be stored in JPEG EXIF header.
1077         *
1078         * @param timestamp GPS timestamp (UTC in seconds since January 1,
1079         *                  1970).
1080         */
1081        public void setGpsTimestamp(long timestamp) {
1082            set(KEY_GPS_TIMESTAMP, Long.toString(timestamp));
1083        }
1084
1085        /**
1086         * Removes GPS latitude, longitude, altitude, and timestamp from the
1087         * parameters.
1088         */
1089        public void removeGpsData() {
1090            remove(KEY_GPS_LATITUDE);
1091            remove(KEY_GPS_LONGITUDE);
1092            remove(KEY_GPS_ALTITUDE);
1093            remove(KEY_GPS_TIMESTAMP);
1094        }
1095
1096        /**
1097         * Gets the current white balance setting.
1098         *
1099         * @return one of WHITE_BALANCE_XXX string constant. null if white
1100         *         balance setting is not supported.
1101         */
1102        public String getWhiteBalance() {
1103            return get(KEY_WHITE_BALANCE);
1104        }
1105
1106        /**
1107         * Sets the white balance.
1108         *
1109         * @param value WHITE_BALANCE_XXX string constant.
1110         */
1111        public void setWhiteBalance(String value) {
1112            set(KEY_WHITE_BALANCE, value);
1113        }
1114
1115        /**
1116         * Gets the supported white balance.
1117         *
1118         * @return a List of WHITE_BALANCE_XXX string constants. null if white
1119         *         balance setting is not supported.
1120         */
1121        public List<String> getSupportedWhiteBalance() {
1122            String str = get(KEY_WHITE_BALANCE + SUPPORTED_VALUES_SUFFIX);
1123            return split(str);
1124        }
1125
1126        /**
1127         * Gets the current color effect setting.
1128         *
1129         * @return one of EFFECT_XXX string constant. null if color effect
1130         *         setting is not supported.
1131         */
1132        public String getColorEffect() {
1133            return get(KEY_EFFECT);
1134        }
1135
1136        /**
1137         * Sets the current color effect setting.
1138         *
1139         * @param value EFFECT_XXX string constants.
1140         */
1141        public void setColorEffect(String value) {
1142            set(KEY_EFFECT, value);
1143        }
1144
1145        /**
1146         * Gets the supported color effects.
1147         *
1148         * @return a List of EFFECT_XXX string constants. null if color effect
1149         *         setting is not supported.
1150         */
1151        public List<String> getSupportedColorEffects() {
1152            String str = get(KEY_EFFECT + SUPPORTED_VALUES_SUFFIX);
1153            return split(str);
1154        }
1155
1156
1157        /**
1158         * Gets the current antibanding setting.
1159         *
1160         * @return one of ANTIBANDING_XXX string constant. null if antibanding
1161         *         setting is not supported.
1162         */
1163        public String getAntibanding() {
1164            return get(KEY_ANTIBANDING);
1165        }
1166
1167        /**
1168         * Sets the antibanding.
1169         *
1170         * @param antibanding ANTIBANDING_XXX string constant.
1171         */
1172        public void setAntibanding(String antibanding) {
1173            set(KEY_ANTIBANDING, antibanding);
1174        }
1175
1176        /**
1177         * Gets the supported antibanding values.
1178         *
1179         * @return a List of ANTIBANDING_XXX string constants. null if
1180         *         antibanding setting is not supported.
1181         */
1182        public List<String> getSupportedAntibanding() {
1183            String str = get(KEY_ANTIBANDING + SUPPORTED_VALUES_SUFFIX);
1184            return split(str);
1185        }
1186
1187        /**
1188         * Gets the current scene mode setting.
1189         *
1190         * @return one of SCENE_MODE_XXX string constant. null if scene mode
1191         *         setting is not supported.
1192         */
1193        public String getSceneMode() {
1194            return get(KEY_SCENE_MODE);
1195        }
1196
1197        /**
1198         * Sets the scene mode.
1199         *
1200         * @param value SCENE_MODE_XXX string constants.
1201         */
1202        public void setSceneMode(String value) {
1203            set(KEY_SCENE_MODE, value);
1204        }
1205
1206        /**
1207         * Gets the supported scene modes.
1208         *
1209         * @return a List of SCENE_MODE_XXX string constant. null if scene mode
1210         *         setting is not supported.
1211         */
1212        public List<String> getSupportedSceneModes() {
1213            String str = get(KEY_SCENE_MODE + SUPPORTED_VALUES_SUFFIX);
1214            return split(str);
1215        }
1216
1217        /**
1218         * Gets the current flash mode setting.
1219         *
1220         * @return one of FLASH_MODE_XXX string constant. null if flash mode
1221         *         setting is not supported.
1222         */
1223        public String getFlashMode() {
1224            return get(KEY_FLASH_MODE);
1225        }
1226
1227        /**
1228         * Sets the flash mode.
1229         *
1230         * @param value FLASH_MODE_XXX string constants.
1231         */
1232        public void setFlashMode(String value) {
1233            set(KEY_FLASH_MODE, value);
1234        }
1235
1236        /**
1237         * Gets the supported flash modes.
1238         *
1239         * @return a List of FLASH_MODE_XXX string constants. null if flash mode
1240         *         setting is not supported.
1241         */
1242        public List<String> getSupportedFlashModes() {
1243            String str = get(KEY_FLASH_MODE + SUPPORTED_VALUES_SUFFIX);
1244            return split(str);
1245        }
1246
1247        // Splits a comma delimited string to an ArrayList of String.
1248        // Return null if the passing string is null or the size is 0.
1249        private ArrayList<String> split(String str) {
1250            if (str == null) return null;
1251
1252            // Use StringTokenizer because it is faster than split.
1253            StringTokenizer tokenizer = new StringTokenizer(str, ",");
1254            ArrayList<String> substrings = new ArrayList<String>();
1255            while (tokenizer.hasMoreElements()) {
1256                substrings.add(tokenizer.nextToken());
1257            }
1258            return substrings;
1259        }
1260
1261        // Splits a comma delimited string to an ArrayList of Integer.
1262        // Return null if the passing string is null or the size is 0.
1263        private ArrayList<Integer> splitInt(String str) {
1264            if (str == null) return null;
1265
1266            StringTokenizer tokenizer = new StringTokenizer(str, ",");
1267            ArrayList<Integer> substrings = new ArrayList<Integer>();
1268            while (tokenizer.hasMoreElements()) {
1269                String token = tokenizer.nextToken();
1270                substrings.add(Integer.parseInt(token));
1271            }
1272            if (substrings.size() == 0) return null;
1273            return substrings;
1274        }
1275
1276        // Splits a comma delimited string to an ArrayList of Size.
1277        // Return null if the passing string is null or the size is 0.
1278        private ArrayList<Size> splitSize(String str) {
1279            if (str == null) return null;
1280
1281            StringTokenizer tokenizer = new StringTokenizer(str, ",");
1282            ArrayList<Size> sizeList = new ArrayList<Size>();
1283            while (tokenizer.hasMoreElements()) {
1284                Size size = strToSize(tokenizer.nextToken());
1285                if (size != null) sizeList.add(size);
1286            }
1287            if (sizeList.size() == 0) return null;
1288            return sizeList;
1289        }
1290
1291        // Parses a string (ex: "480x320") to Size object.
1292        // Return null if the passing string is null.
1293        private Size strToSize(String str) {
1294            if (str == null) return null;
1295
1296            int pos = str.indexOf('x');
1297            if (pos != -1) {
1298                String width = str.substring(0, pos);
1299                String height = str.substring(pos + 1);
1300                return new Size(Integer.parseInt(width),
1301                                Integer.parseInt(height));
1302            }
1303            Log.e(TAG, "Invalid size parameter string=" + str);
1304            return null;
1305        }
1306    };
1307}
1308
1309
1310