Camera.java revision bfcbeffc54e93b1c2e2d95fdc301786df4376d6f
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.ImageFormat;
30import android.os.Handler;
31import android.os.Looper;
32import android.os.Message;
33
34/**
35 * The Camera class is used to set image capture settings, start/stop preview,
36 * snap pictures, and retrieve frames for encoding for video.  This class is a
37 * client for the Camera service, which manages the actual camera hardware.
38 *
39 * <p>To access the device camera, you must declare the
40 * {@link android.Manifest.permission#CAMERA} permission in your Android
41 * Manifest. Also be sure to include the
42 * <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature></a>
43 * manifest element to declare camera features used by your application.
44 * For example, if you use the camera and auto-focus feature, your Manifest
45 * should include the following:</p>
46 * <pre> &lt;uses-permission android:name="android.permission.CAMERA" />
47 * &lt;uses-feature android:name="android.hardware.camera" />
48 * &lt;uses-feature android:name="android.hardware.camera.autofocus" /></pre>
49 *
50 * <p>To take pictures with this class, use the following steps:</p>
51 *
52 * <ol>
53 * <li>Obtain an instance of Camera from {@link #open()}.
54 *
55 * <li>Get existing (default) settings with {@link #getParameters()}.
56 *
57 * <li>If necessary, modify the returned {@link Camera.Parameters} object and call
58 * {@link #setParameters(Camera.Parameters)}.
59 *
60 * <li>If desired, call {@link #setDisplayOrientation(int)}.
61 *
62 * <li><b>Important</b>: Pass a fully initialized {@link SurfaceHolder} to
63 * {@link #setPreviewDisplay(SurfaceHolder)}.  Without a surface, the camera
64 * will be unable to start the preview.
65 *
66 * <li><b>Important</b>: Call {@link #startPreview()} to start updating the
67 * preview surface.  Preview must be started before you can take a picture.
68 *
69 * <li>When you want, call {@link #takePicture(Camera.ShutterCallback,
70 * Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback)} to
71 * capture a photo.  Wait for the callbacks to provide the actual image data.
72 *
73 * <li>After taking a picture, preview display will have stopped.  To take more
74 * photos, call {@link #startPreview()} again first.
75 *
76 * <li>Call {@link #stopPreview()} to stop updating the preview surface.
77 *
78 * <li><b>Important:</b> Call {@link #release()} to release the camera for
79 * use by other applications.  Applications should release the camera
80 * immediately in {@link android.app.Activity#onPause()} (and re-{@link #open()}
81 * it in {@link android.app.Activity#onResume()}).
82 * </ol>
83 *
84 * <p>To quickly switch to video recording mode, use these steps:</p>
85 *
86 * <ol>
87 * <li>Obtain and initialize a Camera and start preview as described above.
88 *
89 * <li>Call {@link #unlock()} to allow the media process to access the camera.
90 *
91 * <li>Pass the camera to {@link android.media.MediaRecorder#setCamera(Camera)}.
92 * See {@link android.media.MediaRecorder} information about video recording.
93 *
94 * <li>When finished recording, call {@link #reconnect()} to re-acquire
95 * and re-lock the camera.
96 *
97 * <li>If desired, restart preview and take more photos or videos.
98 *
99 * <li>Call {@link #stopPreview()} and {@link #release()} as described above.
100 * </ol>
101 *
102 * <p>This class is not thread-safe, and is meant for use from one event thread.
103 * Most long-running operations (preview, focus, photo capture, etc) happen
104 * asynchronously and invoke callbacks as necessary.  Callbacks will be invoked
105 * on the event thread {@link #open()} was called from.  This class's methods
106 * must never be called from multiple threads at once.</p>
107 *
108 * <p class="caution"><strong>Caution:</strong> Different Android-powered devices
109 * may have different hardware specifications, such as megapixel ratings and
110 * auto-focus capabilities. In order for your application to be compatible with
111 * more devices, you should not make assumptions about the device camera
112 * specifications.</p>
113 */
114public class Camera {
115    private static final String TAG = "Camera";
116
117    // These match the enums in frameworks/base/include/ui/Camera.h
118    private static final int CAMERA_MSG_ERROR            = 0x001;
119    private static final int CAMERA_MSG_SHUTTER          = 0x002;
120    private static final int CAMERA_MSG_FOCUS            = 0x004;
121    private static final int CAMERA_MSG_ZOOM             = 0x008;
122    private static final int CAMERA_MSG_PREVIEW_FRAME    = 0x010;
123    private static final int CAMERA_MSG_VIDEO_FRAME      = 0x020;
124    private static final int CAMERA_MSG_POSTVIEW_FRAME   = 0x040;
125    private static final int CAMERA_MSG_RAW_IMAGE        = 0x080;
126    private static final int CAMERA_MSG_COMPRESSED_IMAGE = 0x100;
127    private static final int CAMERA_MSG_ALL_MSGS         = 0x1FF;
128
129    private int mNativeContext; // accessed by native methods
130    private EventHandler mEventHandler;
131    private ShutterCallback mShutterCallback;
132    private PictureCallback mRawImageCallback;
133    private PictureCallback mJpegCallback;
134    private PreviewCallback mPreviewCallback;
135    private PictureCallback mPostviewCallback;
136    private AutoFocusCallback mAutoFocusCallback;
137    private OnZoomChangeListener mZoomListener;
138    private ErrorCallback mErrorCallback;
139    private boolean mOneShot;
140    private boolean mWithBuffer;
141
142    /**
143     * Creates a new Camera object.
144     *
145     * <p>You must call {@link #release()} when you are done using the camera,
146     * otherwise it will remain locked and be unavailable to other applications.
147     *
148     * <p>Your application should only have one Camera object active at a time.
149     *
150     * <p>Callbacks from other methods are delivered to the event loop of the
151     * thread which called open().  If this thread has no event loop, then
152     * callbacks are delivered to the main application event loop.  If there
153     * is no main application event loop, callbacks are not delivered.
154     *
155     * <p class="caution"><b>Caution:</b> On some devices, this method may
156     * take a long time to complete.  It is best to call this method from a
157     * worker thread (possibly using {@link android.os.AsyncTask}) to avoid
158     * blocking the main application UI thread.
159     *
160     * @return a new Camera object, connected, locked and ready for use.
161     * @throws RuntimeException if connection to the camera service fails (for
162     *     example, if the camera is in use by another process).
163     */
164    public static Camera open() {
165        return new Camera();
166    }
167
168    Camera() {
169        mShutterCallback = null;
170        mRawImageCallback = null;
171        mJpegCallback = null;
172        mPreviewCallback = null;
173        mPostviewCallback = null;
174        mZoomListener = null;
175
176        Looper looper;
177        if ((looper = Looper.myLooper()) != null) {
178            mEventHandler = new EventHandler(this, looper);
179        } else if ((looper = Looper.getMainLooper()) != null) {
180            mEventHandler = new EventHandler(this, looper);
181        } else {
182            mEventHandler = null;
183        }
184
185        native_setup(new WeakReference<Camera>(this));
186    }
187
188    protected void finalize() {
189        native_release();
190    }
191
192    private native final void native_setup(Object camera_this);
193    private native final void native_release();
194
195
196    /**
197     * Disconnects and releases the Camera object resources.
198     *
199     * <p>You must call this as soon as you're done with the Camera object.</p>
200     */
201    public final void release() {
202        native_release();
203    }
204
205    /**
206     * Unlocks the camera to allow another process to access it.
207     * Normally, the camera is locked to the process with an active Camera
208     * object until {@link #release()} is called.  To allow rapid handoff
209     * between processes, you can call this method to release the camera
210     * temporarily for another process to use; once the other process is done
211     * you can call {@link #reconnect()} to reclaim the camera.
212     *
213     * <p>This must be done before calling
214     * {@link android.media.MediaRecorder#setCamera(Camera)}.
215     *
216     * <p>If you are not recording video, you probably do not need this method.
217     *
218     * @throws RuntimeException if the camera cannot be unlocked.
219     */
220    public native final void unlock();
221
222    /**
223     * Re-locks the camera to prevent other processes from accessing it.
224     * Camera objects are locked by default unless {@link #unlock()} is
225     * called.  Normally {@link #reconnect()} is used instead.
226     *
227     * <p>If you are not recording video, you probably do not need this method.
228     *
229     * @throws RuntimeException if the camera cannot be re-locked (for
230     *     example, if the camera is still in use by another process).
231     */
232    public native final void lock();
233
234    /**
235     * Reconnects to the camera service after another process used it.
236     * After {@link #unlock()} is called, another process may use the
237     * camera; when the process is done, you must reconnect to the camera,
238     * which will re-acquire the lock and allow you to continue using the
239     * camera.
240     *
241     * <p>This must be done after {@link android.media.MediaRecorder} is
242     * done recording if {@link android.media.MediaRecorder#setCamera(Camera)}
243     * was used.
244     *
245     * <p>If you are not recording video, you probably do not need this method.
246     *
247     * @throws IOException if a connection cannot be re-established (for
248     *     example, if the camera is still in use by another process).
249     */
250    public native final void reconnect() throws IOException;
251
252    /**
253     * Sets the {@link Surface} to be used for live preview.
254     * A surface is necessary for preview, and preview is necessary to take
255     * pictures.  The same surface can be re-set without harm.
256     *
257     * <p>The {@link SurfaceHolder} must already contain a surface when this
258     * method is called.  If you are using {@link android.view.SurfaceView},
259     * you will need to register a {@link SurfaceHolder.Callback} with
260     * {@link SurfaceHolder#addCallback(SurfaceHolder.Callback)} and wait for
261     * {@link SurfaceHolder.Callback#surfaceCreated(SurfaceHolder)} before
262     * calling setPreviewDisplay() or starting preview.
263     *
264     * <p>This method must be called before {@link #startPreview()}.  The
265     * one exception is that if the preview surface is not set (or set to null)
266     * before startPreview() is called, then this method may be called once
267     * with a non-null parameter to set the preview surface.  (This allows
268     * camera setup and surface creation to happen in parallel, saving time.)
269     * The preview surface may not otherwise change while preview is running.
270     *
271     * @param holder containing the Surface on which to place the preview,
272     *     or null to remove the preview surface
273     * @throws IOException if the method fails (for example, if the surface
274     *     is unavailable or unsuitable).
275     */
276    public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
277        if (holder != null) {
278            setPreviewDisplay(holder.getSurface());
279        } else {
280            setPreviewDisplay((Surface)null);
281        }
282    }
283
284    private native final void setPreviewDisplay(Surface surface);
285
286    /**
287     * Callback interface used to deliver copies of preview frames as
288     * they are displayed.
289     *
290     * @see #setPreviewCallback(Camera.PreviewCallback)
291     * @see #setOneShotPreviewCallback(Camera.PreviewCallback)
292     * @see #setPreviewCallbackWithBuffer(Camera.PreviewCallback)
293     * @see #startPreview()
294     */
295    public interface PreviewCallback
296    {
297        /**
298         * Called as preview frames are displayed.  This callback is invoked
299         * on the event thread {@link #open()} was called from.
300         *
301         * @param data the contents of the preview frame in the format defined
302         *  by {@link android.graphics.ImageFormat}, which can be queried
303         *  with {@link android.hardware.Camera.Parameters#getPreviewFormat()}.
304         *  If {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}
305         *             is never called, the default will be the YCbCr_420_SP
306         *             (NV21) format.
307         * @param camera the Camera service object.
308         */
309        void onPreviewFrame(byte[] data, Camera camera);
310    };
311
312    /**
313     * Starts capturing and drawing preview frames to the screen.
314     * Preview will not actually start until a surface is supplied with
315     * {@link #setPreviewDisplay(SurfaceHolder)}.
316     *
317     * <p>If {@link #setPreviewCallback(Camera.PreviewCallback)},
318     * {@link #setOneShotPreviewCallback(Camera.PreviewCallback)}, or
319     * {@link #setPreviewCallbackWithBuffer(Camera.PreviewCallback)} were
320     * called, {@link Camera.PreviewCallback#onPreviewFrame(byte[], Camera)}
321     * will be called when preview data becomes available.
322     */
323    public native final void startPreview();
324
325    /**
326     * Stops capturing and drawing preview frames to the surface, and
327     * resets the camera for a future call to {@link #startPreview()}.
328     */
329    public native final void stopPreview();
330
331    /**
332     * Return current preview state.
333     *
334     * FIXME: Unhide before release
335     * @hide
336     */
337    public native final boolean previewEnabled();
338
339    /**
340     * Installs a callback to be invoked for every preview frame in addition
341     * to displaying them on the screen.  The callback will be repeatedly called
342     * for as long as preview is active.  This method can be called at any time,
343     * even while preview is live.  Any other preview callbacks are overridden.
344     *
345     * @param cb a callback object that receives a copy of each preview frame,
346     *     or null to stop receiving callbacks.
347     */
348    public final void setPreviewCallback(PreviewCallback cb) {
349        mPreviewCallback = cb;
350        mOneShot = false;
351        mWithBuffer = false;
352        // Always use one-shot mode. We fake camera preview mode by
353        // doing one-shot preview continuously.
354        setHasPreviewCallback(cb != null, false);
355    }
356
357    /**
358     * Installs a callback to be invoked for the next preview frame in addition
359     * to displaying it on the screen.  After one invocation, the callback is
360     * cleared. This method can be called any time, even when preview is live.
361     * Any other preview callbacks are overridden.
362     *
363     * @param cb a callback object that receives a copy of the next preview frame,
364     *     or null to stop receiving callbacks.
365     */
366    public final void setOneShotPreviewCallback(PreviewCallback cb) {
367        mPreviewCallback = cb;
368        mOneShot = true;
369        mWithBuffer = false;
370        setHasPreviewCallback(cb != null, false);
371    }
372
373    private native final void setHasPreviewCallback(boolean installed, boolean manualBuffer);
374
375    /**
376     * Installs a callback to be invoked for every preview frame, using buffers
377     * supplied with {@link #addCallbackBuffer(byte[])}, in addition to
378     * displaying them on the screen.  The callback will be repeatedly called
379     * for as long as preview is active and buffers are available.
380     * Any other preview callbacks are overridden.
381     *
382     * <p>The purpose of this method is to improve preview efficiency and frame
383     * rate by allowing preview frame memory reuse.  You must call
384     * {@link #addCallbackBuffer(byte[])} at some point -- before or after
385     * calling this method -- or no callbacks will received.
386     *
387     * The buffer queue will be cleared if this method is called with a null
388     * callback, {@link #setPreviewCallback(Camera.PreviewCallback)} is called,
389     * or {@link #setOneShotPreviewCallback(Camera.PreviewCallback)} is called.
390     *
391     * @param cb a callback object that receives a copy of the preview frame,
392     *     or null to stop receiving callbacks and clear the buffer queue.
393     * @see #addCallbackBuffer(byte[])
394     */
395    public final void setPreviewCallbackWithBuffer(PreviewCallback cb) {
396        mPreviewCallback = cb;
397        mOneShot = false;
398        mWithBuffer = true;
399        setHasPreviewCallback(cb != null, true);
400    }
401
402    /**
403     * Adds a pre-allocated buffer to the preview callback buffer queue.
404     * Applications can add one or more buffers to the queue. When a preview
405     * frame arrives and there is still at least one available buffer, the
406     * buffer will be used and removed from the queue. Then preview callback is
407     * invoked with the buffer. If a frame arrives and there is no buffer left,
408     * the frame is discarded. Applications should add buffers back when they
409     * finish processing the data in them.
410     *
411     * <p>The size of the buffer is determined by multiplying the preview
412     * image width, height, and bytes per pixel.  The width and height can be
413     * read from {@link Camera.Parameters#getPreviewSize()}.  Bytes per pixel
414     * can be computed from
415     * {@link android.graphics.ImageFormat#getBitsPerPixel(int)} / 8,
416     * using the image format from {@link Camera.Parameters#getPreviewFormat()}.
417     *
418     * <p>This method is only necessary when
419     * {@link #setPreviewCallbackWithBuffer(PreviewCallback)} is used.  When
420     * {@link #setPreviewCallback(PreviewCallback)} or
421     * {@link #setOneShotPreviewCallback(PreviewCallback)} are used, buffers
422     * are automatically allocated.
423     *
424     * @param callbackBuffer the buffer to add to the queue.
425     *     The size should be width * height * bits_per_pixel / 8.
426     * @see #setPreviewCallbackWithBuffer(PreviewCallback)
427     */
428    public native final void addCallbackBuffer(byte[] callbackBuffer);
429
430    private class EventHandler extends Handler
431    {
432        private Camera mCamera;
433
434        public EventHandler(Camera c, Looper looper) {
435            super(looper);
436            mCamera = c;
437        }
438
439        @Override
440        public void handleMessage(Message msg) {
441            switch(msg.what) {
442            case CAMERA_MSG_SHUTTER:
443                if (mShutterCallback != null) {
444                    mShutterCallback.onShutter();
445                }
446                return;
447
448            case CAMERA_MSG_RAW_IMAGE:
449                if (mRawImageCallback != null) {
450                    mRawImageCallback.onPictureTaken((byte[])msg.obj, mCamera);
451                }
452                return;
453
454            case CAMERA_MSG_COMPRESSED_IMAGE:
455                if (mJpegCallback != null) {
456                    mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera);
457                }
458                return;
459
460            case CAMERA_MSG_PREVIEW_FRAME:
461                if (mPreviewCallback != null) {
462                    PreviewCallback cb = mPreviewCallback;
463                    if (mOneShot) {
464                        // Clear the callback variable before the callback
465                        // in case the app calls setPreviewCallback from
466                        // the callback function
467                        mPreviewCallback = null;
468                    } else if (!mWithBuffer) {
469                        // We're faking the camera preview mode to prevent
470                        // the app from being flooded with preview frames.
471                        // Set to oneshot mode again.
472                        setHasPreviewCallback(true, false);
473                    }
474                    cb.onPreviewFrame((byte[])msg.obj, mCamera);
475                }
476                return;
477
478            case CAMERA_MSG_POSTVIEW_FRAME:
479                if (mPostviewCallback != null) {
480                    mPostviewCallback.onPictureTaken((byte[])msg.obj, mCamera);
481                }
482                return;
483
484            case CAMERA_MSG_FOCUS:
485                if (mAutoFocusCallback != null) {
486                    mAutoFocusCallback.onAutoFocus(msg.arg1 == 0 ? false : true, mCamera);
487                }
488                return;
489
490            case CAMERA_MSG_ZOOM:
491                if (mZoomListener != null) {
492                    mZoomListener.onZoomChange(msg.arg1, msg.arg2 != 0, mCamera);
493                }
494                return;
495
496            case CAMERA_MSG_ERROR :
497                Log.e(TAG, "Error " + msg.arg1);
498                if (mErrorCallback != null) {
499                    mErrorCallback.onError(msg.arg1, mCamera);
500                }
501                return;
502
503            default:
504                Log.e(TAG, "Unknown message type " + msg.what);
505                return;
506            }
507        }
508    }
509
510    private static void postEventFromNative(Object camera_ref,
511                                            int what, int arg1, int arg2, Object obj)
512    {
513        Camera c = (Camera)((WeakReference)camera_ref).get();
514        if (c == null)
515            return;
516
517        if (c.mEventHandler != null) {
518            Message m = c.mEventHandler.obtainMessage(what, arg1, arg2, obj);
519            c.mEventHandler.sendMessage(m);
520        }
521    }
522
523    /**
524     * Callback interface used to notify on completion of camera auto focus.
525     *
526     * <p>Devices that do not support auto-focus will receive a "fake"
527     * callback to this interface. If your application needs auto-focus and
528     * should not be installed on devices <em>without</em> auto-focus, you must
529     * declare that your app uses the
530     * {@code android.hardware.camera.autofocus} feature, in the
531     * <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature></a>
532     * manifest element.</p>
533     *
534     * @see #autoFocus(AutoFocusCallback)
535     */
536    public interface AutoFocusCallback
537    {
538        /**
539         * Called when the camera auto focus completes.  If the camera does not
540         * support auto-focus and autoFocus is called, onAutoFocus will be
541         * called immediately with success.
542         *
543         * @param success true if focus was successful, false if otherwise
544         * @param camera  the Camera service object
545         */
546        void onAutoFocus(boolean success, Camera camera);
547    };
548
549    /**
550     * Starts camera auto-focus and registers a callback function to run when
551     * the camera is focused.  This method is only valid when preview is active
552     * (between {@link #startPreview()} and before {@link #stopPreview()}).
553     *
554     * <p>Callers should check
555     * {@link android.hardware.Camera.Parameters#getFocusMode()} to determine if
556     * this method should be called. If the camera does not support auto-focus,
557     * it is a no-op and {@link AutoFocusCallback#onAutoFocus(boolean, Camera)}
558     * callback will be called immediately.
559     *
560     * <p>If your application should not be installed
561     * on devices without auto-focus, you must declare that your application
562     * uses auto-focus with the
563     * <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature></a>
564     * manifest element.</p>
565     *
566     * <p>If the current flash mode is not
567     * {@link android.hardware.Camera.Parameters#FLASH_MODE_OFF}, flash may be
568     * fired during auto-focus, depending on the driver and camera hardware.<p>
569     *
570     * @param cb the callback to run
571     * @see #cancelAutoFocus()
572     */
573    public final void autoFocus(AutoFocusCallback cb)
574    {
575        mAutoFocusCallback = cb;
576        native_autoFocus();
577    }
578    private native final void native_autoFocus();
579
580    /**
581     * Cancels any auto-focus function in progress.
582     * Whether or not auto-focus is currently in progress,
583     * this function will return the focus position to the default.
584     * If the camera does not support auto-focus, this is a no-op.
585     *
586     * @see #autoFocus(Camera.AutoFocusCallback)
587     */
588    public final void cancelAutoFocus()
589    {
590        mAutoFocusCallback = null;
591        native_cancelAutoFocus();
592    }
593    private native final void native_cancelAutoFocus();
594
595    /**
596     * Callback interface used to signal the moment of actual image capture.
597     *
598     * @see #takePicture(ShutterCallback, PictureCallback, PictureCallback, PictureCallback)
599     */
600    public interface ShutterCallback
601    {
602        /**
603         * Called as near as possible to the moment when a photo is captured
604         * from the sensor.  This is a good opportunity to play a shutter sound
605         * or give other feedback of camera operation.  This may be some time
606         * after the photo was triggered, but some time before the actual data
607         * is available.
608         */
609        void onShutter();
610    }
611
612    /**
613     * Callback interface used to supply image data from a photo capture.
614     *
615     * @see #takePicture(ShutterCallback, PictureCallback, PictureCallback, PictureCallback)
616     */
617    public interface PictureCallback {
618        /**
619         * Called when image data is available after a picture is taken.
620         * The format of the data depends on the context of the callback
621         * and {@link Camera.Parameters} settings.
622         *
623         * @param data   a byte array of the picture data
624         * @param camera the Camera service object
625         */
626        void onPictureTaken(byte[] data, Camera camera);
627    };
628
629    /**
630     * Equivalent to takePicture(shutter, raw, null, jpeg).
631     *
632     * @see #takePicture(ShutterCallback, PictureCallback, PictureCallback, PictureCallback)
633     */
634    public final void takePicture(ShutterCallback shutter, PictureCallback raw,
635            PictureCallback jpeg) {
636        takePicture(shutter, raw, null, jpeg);
637    }
638    private native final void native_takePicture();
639
640    /**
641     * Triggers an asynchronous image capture. The camera service will initiate
642     * a series of callbacks to the application as the image capture progresses.
643     * The shutter callback occurs after the image is captured. This can be used
644     * to trigger a sound to let the user know that image has been captured. The
645     * raw callback occurs when the raw image data is available (NOTE: the data
646     * may be null if the hardware does not have enough memory to make a copy).
647     * The postview callback occurs when a scaled, fully processed postview
648     * image is available (NOTE: not all hardware supports this). The jpeg
649     * callback occurs when the compressed image is available. If the
650     * application does not need a particular callback, a null can be passed
651     * instead of a callback method.
652     *
653     * <p>This method is only valid when preview is active (after
654     * {@link #startPreview()}).  Preview will be stopped after the image is
655     * taken; callers must call {@link #startPreview()} again if they want to
656     * re-start preview or take more pictures.
657     *
658     * <p>After calling this method, you must not call {@link #startPreview()}
659     * or take another picture until the JPEG callback has returned.
660     *
661     * @param shutter   the callback for image capture moment, or null
662     * @param raw       the callback for raw (uncompressed) image data, or null
663     * @param postview  callback with postview image data, may be null
664     * @param jpeg      the callback for JPEG image data, or null
665     */
666    public final void takePicture(ShutterCallback shutter, PictureCallback raw,
667            PictureCallback postview, PictureCallback jpeg) {
668        mShutterCallback = shutter;
669        mRawImageCallback = raw;
670        mPostviewCallback = postview;
671        mJpegCallback = jpeg;
672        native_takePicture();
673    }
674
675    /**
676     * Zooms to the requested value smoothly. The driver will notify {@link
677     * OnZoomChangeListener} of the zoom value and whether zoom is stopped at
678     * the time. For example, suppose the current zoom is 0 and startSmoothZoom
679     * is called with value 3. The
680     * {@link Camera.OnZoomChangeListener#onZoomChange(int, boolean, Camera)}
681     * method will be called three times with zoom values 1, 2, and 3.
682     * Applications can call {@link #stopSmoothZoom} to stop the zoom earlier.
683     * Applications should not call startSmoothZoom again or change the zoom
684     * value before zoom stops. If the supplied zoom value equals to the current
685     * zoom value, no zoom callback will be generated. This method is supported
686     * if {@link android.hardware.Camera.Parameters#isSmoothZoomSupported}
687     * returns true.
688     *
689     * @param value zoom value. The valid range is 0 to {@link
690     *              android.hardware.Camera.Parameters#getMaxZoom}.
691     * @throws IllegalArgumentException if the zoom value is invalid.
692     * @throws RuntimeException if the method fails.
693     * @see #setZoomChangeListener(OnZoomChangeListener)
694     */
695    public native final void startSmoothZoom(int value);
696
697    /**
698     * Stops the smooth zoom. Applications should wait for the {@link
699     * OnZoomChangeListener} to know when the zoom is actually stopped. This
700     * method is supported if {@link
701     * android.hardware.Camera.Parameters#isSmoothZoomSupported} is true.
702     *
703     * @throws RuntimeException if the method fails.
704     */
705    public native final void stopSmoothZoom();
706
707    /**
708     * Set the display orientation. This affects the preview frames and the
709     * picture displayed after snapshot. This method is useful for portrait
710     * mode applications.
711     *
712     * This does not affect the order of byte array passed in
713     * {@link PreviewCallback#onPreviewFrame}. This method is not allowed to
714     * be called during preview.
715     *
716     * @param degrees the angle that the picture will be rotated clockwise.
717     *                Valid values are 0, 90, 180, and 270. The starting
718     *                position is 0 (landscape).
719     */
720    public native final void setDisplayOrientation(int degrees);
721
722    /**
723     * Callback interface for zoom changes during a smooth zoom operation.
724     *
725     * @see #setZoomChangeListener(OnZoomChangeListener)
726     * @see #startSmoothZoom(int)
727     */
728    public interface OnZoomChangeListener
729    {
730        /**
731         * Called when the zoom value has changed during a smooth zoom.
732         *
733         * @param zoomValue the current zoom value. In smooth zoom mode, camera
734         *                  calls this for every new zoom value.
735         * @param stopped whether smooth zoom is stopped. If the value is true,
736         *                this is the last zoom update for the application.
737         * @param camera  the Camera service object
738         */
739        void onZoomChange(int zoomValue, boolean stopped, Camera camera);
740    };
741
742    /**
743     * Registers a listener to be notified when the zoom value is updated by the
744     * camera driver during smooth zoom.
745     *
746     * @param listener the listener to notify
747     * @see #startSmoothZoom(int)
748     */
749    public final void setZoomChangeListener(OnZoomChangeListener listener)
750    {
751        mZoomListener = listener;
752    }
753
754    // Error codes match the enum in include/ui/Camera.h
755
756    /**
757     * Unspecified camera error.
758     * @see Camera.ErrorCallback
759     */
760    public static final int CAMERA_ERROR_UNKNOWN = 1;
761
762    /**
763     * Media server died. In this case, the application must release the
764     * Camera object and instantiate a new one.
765     * @see Camera.ErrorCallback
766     */
767    public static final int CAMERA_ERROR_SERVER_DIED = 100;
768
769    /**
770     * Callback interface for camera error notification.
771     *
772     * @see #setErrorCallback(ErrorCallback)
773     */
774    public interface ErrorCallback
775    {
776        /**
777         * Callback for camera errors.
778         * @param error   error code:
779         * <ul>
780         * <li>{@link #CAMERA_ERROR_UNKNOWN}
781         * <li>{@link #CAMERA_ERROR_SERVER_DIED}
782         * </ul>
783         * @param camera  the Camera service object
784         */
785        void onError(int error, Camera camera);
786    };
787
788    /**
789     * Registers a callback to be invoked when an error occurs.
790     * @param cb The callback to run
791     */
792    public final void setErrorCallback(ErrorCallback cb)
793    {
794        mErrorCallback = cb;
795    }
796
797    private native final void native_setParameters(String params);
798    private native final String native_getParameters();
799
800    /**
801     * Changes the settings for this Camera service.
802     *
803     * @param params the Parameters to use for this Camera service
804     * @see #getParameters()
805     */
806    public void setParameters(Parameters params) {
807        native_setParameters(params.flatten());
808    }
809
810    /**
811     * Returns the current settings for this Camera service.
812     * If modifications are made to the returned Parameters, they must be passed
813     * to {@link #setParameters(Camera.Parameters)} to take effect.
814     *
815     * @see #setParameters(Camera.Parameters)
816     */
817    public Parameters getParameters() {
818        Parameters p = new Parameters();
819        String s = native_getParameters();
820        p.unflatten(s);
821        return p;
822    }
823
824    /**
825     * Image size (width and height dimensions).
826     */
827    public class Size {
828        /**
829         * Sets the dimensions for pictures.
830         *
831         * @param w the photo width (pixels)
832         * @param h the photo height (pixels)
833         */
834        public Size(int w, int h) {
835            width = w;
836            height = h;
837        }
838        /**
839         * Compares {@code obj} to this size.
840         *
841         * @param obj the object to compare this size with.
842         * @return {@code true} if the width and height of {@code obj} is the
843         *         same as those of this size. {@code false} otherwise.
844         */
845        @Override
846        public boolean equals(Object obj) {
847            if (!(obj instanceof Size)) {
848                return false;
849            }
850            Size s = (Size) obj;
851            return width == s.width && height == s.height;
852        }
853        @Override
854        public int hashCode() {
855            return width * 32713 + height;
856        }
857        /** width of the picture */
858        public int width;
859        /** height of the picture */
860        public int height;
861    };
862
863    /**
864     * Camera service settings.
865     *
866     * <p>To make camera parameters take effect, applications have to call
867     * {@link Camera#setParameters(Camera.Parameters)}. For example, after
868     * {@link Camera.Parameters#setWhiteBalance} is called, white balance is not
869     * actually changed until {@link Camera#setParameters(Camera.Parameters)}
870     * is called with the changed parameters object.
871     *
872     * <p>Different devices may have different camera capabilities, such as
873     * picture size or flash modes. The application should query the camera
874     * capabilities before setting parameters. For example, the application
875     * should call {@link Camera.Parameters#getSupportedColorEffects()} before
876     * calling {@link Camera.Parameters#setColorEffect(String)}. If the
877     * camera does not support color effects,
878     * {@link Camera.Parameters#getSupportedColorEffects()} will return null.
879     */
880    public class Parameters {
881        // Parameter keys to communicate with the camera driver.
882        private static final String KEY_PREVIEW_SIZE = "preview-size";
883        private static final String KEY_PREVIEW_FORMAT = "preview-format";
884        private static final String KEY_PREVIEW_FRAME_RATE = "preview-frame-rate";
885        private static final String KEY_PICTURE_SIZE = "picture-size";
886        private static final String KEY_PICTURE_FORMAT = "picture-format";
887        private static final String KEY_JPEG_THUMBNAIL_SIZE = "jpeg-thumbnail-size";
888        private static final String KEY_JPEG_THUMBNAIL_WIDTH = "jpeg-thumbnail-width";
889        private static final String KEY_JPEG_THUMBNAIL_HEIGHT = "jpeg-thumbnail-height";
890        private static final String KEY_JPEG_THUMBNAIL_QUALITY = "jpeg-thumbnail-quality";
891        private static final String KEY_JPEG_QUALITY = "jpeg-quality";
892        private static final String KEY_ROTATION = "rotation";
893        private static final String KEY_GPS_LATITUDE = "gps-latitude";
894        private static final String KEY_GPS_LONGITUDE = "gps-longitude";
895        private static final String KEY_GPS_ALTITUDE = "gps-altitude";
896        private static final String KEY_GPS_TIMESTAMP = "gps-timestamp";
897        private static final String KEY_GPS_PROCESSING_METHOD = "gps-processing-method";
898        private static final String KEY_WHITE_BALANCE = "whitebalance";
899        private static final String KEY_EFFECT = "effect";
900        private static final String KEY_ANTIBANDING = "antibanding";
901        private static final String KEY_SCENE_MODE = "scene-mode";
902        private static final String KEY_FLASH_MODE = "flash-mode";
903        private static final String KEY_FOCUS_MODE = "focus-mode";
904        private static final String KEY_FOCAL_LENGTH = "focal-length";
905        private static final String KEY_HORIZONTAL_VIEW_ANGLE = "horizontal-view-angle";
906        private static final String KEY_VERTICAL_VIEW_ANGLE = "vertical-view-angle";
907        private static final String KEY_EXPOSURE_COMPENSATION = "exposure-compensation";
908        private static final String KEY_MAX_EXPOSURE_COMPENSATION = "max-exposure-compensation";
909        private static final String KEY_MIN_EXPOSURE_COMPENSATION = "min-exposure-compensation";
910        private static final String KEY_EXPOSURE_COMPENSATION_STEP = "exposure-compensation-step";
911        private static final String KEY_ZOOM = "zoom";
912        private static final String KEY_MAX_ZOOM = "max-zoom";
913        private static final String KEY_ZOOM_RATIOS = "zoom-ratios";
914        private static final String KEY_ZOOM_SUPPORTED = "zoom-supported";
915        private static final String KEY_SMOOTH_ZOOM_SUPPORTED = "smooth-zoom-supported";
916        // Parameter key suffix for supported values.
917        private static final String SUPPORTED_VALUES_SUFFIX = "-values";
918
919        private static final String TRUE = "true";
920
921        // Values for white balance settings.
922        public static final String WHITE_BALANCE_AUTO = "auto";
923        public static final String WHITE_BALANCE_INCANDESCENT = "incandescent";
924        public static final String WHITE_BALANCE_FLUORESCENT = "fluorescent";
925        public static final String WHITE_BALANCE_WARM_FLUORESCENT = "warm-fluorescent";
926        public static final String WHITE_BALANCE_DAYLIGHT = "daylight";
927        public static final String WHITE_BALANCE_CLOUDY_DAYLIGHT = "cloudy-daylight";
928        public static final String WHITE_BALANCE_TWILIGHT = "twilight";
929        public static final String WHITE_BALANCE_SHADE = "shade";
930
931        // Values for color effect settings.
932        public static final String EFFECT_NONE = "none";
933        public static final String EFFECT_MONO = "mono";
934        public static final String EFFECT_NEGATIVE = "negative";
935        public static final String EFFECT_SOLARIZE = "solarize";
936        public static final String EFFECT_SEPIA = "sepia";
937        public static final String EFFECT_POSTERIZE = "posterize";
938        public static final String EFFECT_WHITEBOARD = "whiteboard";
939        public static final String EFFECT_BLACKBOARD = "blackboard";
940        public static final String EFFECT_AQUA = "aqua";
941
942        // Values for antibanding settings.
943        public static final String ANTIBANDING_AUTO = "auto";
944        public static final String ANTIBANDING_50HZ = "50hz";
945        public static final String ANTIBANDING_60HZ = "60hz";
946        public static final String ANTIBANDING_OFF = "off";
947
948        // Values for flash mode settings.
949        /**
950         * Flash will not be fired.
951         */
952        public static final String FLASH_MODE_OFF = "off";
953
954        /**
955         * Flash will be fired automatically when required. The flash may be fired
956         * during preview, auto-focus, or snapshot depending on the driver.
957         */
958        public static final String FLASH_MODE_AUTO = "auto";
959
960        /**
961         * Flash will always be fired during snapshot. The flash may also be
962         * fired during preview or auto-focus depending on the driver.
963         */
964        public static final String FLASH_MODE_ON = "on";
965
966        /**
967         * Flash will be fired in red-eye reduction mode.
968         */
969        public static final String FLASH_MODE_RED_EYE = "red-eye";
970
971        /**
972         * Constant emission of light during preview, auto-focus and snapshot.
973         * This can also be used for video recording.
974         */
975        public static final String FLASH_MODE_TORCH = "torch";
976
977        // Values for scene mode settings.
978        public static final String SCENE_MODE_AUTO = "auto";
979        public static final String SCENE_MODE_ACTION = "action";
980        public static final String SCENE_MODE_PORTRAIT = "portrait";
981        public static final String SCENE_MODE_LANDSCAPE = "landscape";
982        public static final String SCENE_MODE_NIGHT = "night";
983        public static final String SCENE_MODE_NIGHT_PORTRAIT = "night-portrait";
984        public static final String SCENE_MODE_THEATRE = "theatre";
985        public static final String SCENE_MODE_BEACH = "beach";
986        public static final String SCENE_MODE_SNOW = "snow";
987        public static final String SCENE_MODE_SUNSET = "sunset";
988        public static final String SCENE_MODE_STEADYPHOTO = "steadyphoto";
989        public static final String SCENE_MODE_FIREWORKS = "fireworks";
990        public static final String SCENE_MODE_SPORTS = "sports";
991        public static final String SCENE_MODE_PARTY = "party";
992        public static final String SCENE_MODE_CANDLELIGHT = "candlelight";
993
994        /**
995         * Applications are looking for a barcode. Camera driver will be
996         * optimized for barcode reading.
997         */
998        public static final String SCENE_MODE_BARCODE = "barcode";
999
1000        // Values for focus mode settings.
1001        /**
1002         * Auto-focus mode.
1003         */
1004        public static final String FOCUS_MODE_AUTO = "auto";
1005
1006        /**
1007         * Focus is set at infinity. Applications should not call
1008         * {@link #autoFocus(AutoFocusCallback)} in this mode.
1009         */
1010        public static final String FOCUS_MODE_INFINITY = "infinity";
1011        public static final String FOCUS_MODE_MACRO = "macro";
1012
1013        /**
1014         * Focus is fixed. The camera is always in this mode if the focus is not
1015         * adjustable. If the camera has auto-focus, this mode can fix the
1016         * focus, which is usually at hyperfocal distance. Applications should
1017         * not call {@link #autoFocus(AutoFocusCallback)} in this mode.
1018         */
1019        public static final String FOCUS_MODE_FIXED = "fixed";
1020
1021        /**
1022         * Extended depth of field (EDOF). Focusing is done digitally and
1023         * continuously. Applications should not call {@link
1024         * #autoFocus(AutoFocusCallback)} in this mode.
1025         */
1026        public static final String FOCUS_MODE_EDOF = "edof";
1027
1028        // Formats for setPreviewFormat and setPictureFormat.
1029        private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp";
1030        private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp";
1031        private static final String PIXEL_FORMAT_YUV422I = "yuv422i-yuyv";
1032        private static final String PIXEL_FORMAT_RGB565 = "rgb565";
1033        private static final String PIXEL_FORMAT_JPEG = "jpeg";
1034
1035        private HashMap<String, String> mMap;
1036
1037        private Parameters() {
1038            mMap = new HashMap<String, String>();
1039        }
1040
1041        /**
1042         * Writes the current Parameters to the log.
1043         * @hide
1044         * @deprecated
1045         */
1046        public void dump() {
1047            Log.e(TAG, "dump: size=" + mMap.size());
1048            for (String k : mMap.keySet()) {
1049                Log.e(TAG, "dump: " + k + "=" + mMap.get(k));
1050            }
1051        }
1052
1053        /**
1054         * Creates a single string with all the parameters set in
1055         * this Parameters object.
1056         * <p>The {@link #unflatten(String)} method does the reverse.</p>
1057         *
1058         * @return a String with all values from this Parameters object, in
1059         *         semi-colon delimited key-value pairs
1060         */
1061        public String flatten() {
1062            StringBuilder flattened = new StringBuilder();
1063            for (String k : mMap.keySet()) {
1064                flattened.append(k);
1065                flattened.append("=");
1066                flattened.append(mMap.get(k));
1067                flattened.append(";");
1068            }
1069            // chop off the extra semicolon at the end
1070            flattened.deleteCharAt(flattened.length()-1);
1071            return flattened.toString();
1072        }
1073
1074        /**
1075         * Takes a flattened string of parameters and adds each one to
1076         * this Parameters object.
1077         * <p>The {@link #flatten()} method does the reverse.</p>
1078         *
1079         * @param flattened a String of parameters (key-value paired) that
1080         *                  are semi-colon delimited
1081         */
1082        public void unflatten(String flattened) {
1083            mMap.clear();
1084
1085            StringTokenizer tokenizer = new StringTokenizer(flattened, ";");
1086            while (tokenizer.hasMoreElements()) {
1087                String kv = tokenizer.nextToken();
1088                int pos = kv.indexOf('=');
1089                if (pos == -1) {
1090                    continue;
1091                }
1092                String k = kv.substring(0, pos);
1093                String v = kv.substring(pos + 1);
1094                mMap.put(k, v);
1095            }
1096        }
1097
1098        public void remove(String key) {
1099            mMap.remove(key);
1100        }
1101
1102        /**
1103         * Sets a String parameter.
1104         *
1105         * @param key   the key name for the parameter
1106         * @param value the String value of the parameter
1107         */
1108        public void set(String key, String value) {
1109            if (key.indexOf('=') != -1 || key.indexOf(';') != -1) {
1110                Log.e(TAG, "Key \"" + key + "\" contains invalid character (= or ;)");
1111                return;
1112            }
1113            if (value.indexOf('=') != -1 || value.indexOf(';') != -1) {
1114                Log.e(TAG, "Value \"" + value + "\" contains invalid character (= or ;)");
1115                return;
1116            }
1117
1118            mMap.put(key, value);
1119        }
1120
1121        /**
1122         * Sets an integer parameter.
1123         *
1124         * @param key   the key name for the parameter
1125         * @param value the int value of the parameter
1126         */
1127        public void set(String key, int value) {
1128            mMap.put(key, Integer.toString(value));
1129        }
1130
1131        /**
1132         * Returns the value of a String parameter.
1133         *
1134         * @param key the key name for the parameter
1135         * @return the String value of the parameter
1136         */
1137        public String get(String key) {
1138            return mMap.get(key);
1139        }
1140
1141        /**
1142         * Returns the value of an integer parameter.
1143         *
1144         * @param key the key name for the parameter
1145         * @return the int value of the parameter
1146         */
1147        public int getInt(String key) {
1148            return Integer.parseInt(mMap.get(key));
1149        }
1150
1151        /**
1152         * Sets the dimensions for preview pictures.
1153         *
1154         * @param width  the width of the pictures, in pixels
1155         * @param height the height of the pictures, in pixels
1156         */
1157        public void setPreviewSize(int width, int height) {
1158            String v = Integer.toString(width) + "x" + Integer.toString(height);
1159            set(KEY_PREVIEW_SIZE, v);
1160        }
1161
1162        /**
1163         * Returns the dimensions setting for preview pictures.
1164         *
1165         * @return a Size object with the height and width setting
1166         *          for the preview picture
1167         */
1168        public Size getPreviewSize() {
1169            String pair = get(KEY_PREVIEW_SIZE);
1170            return strToSize(pair);
1171        }
1172
1173        /**
1174         * Gets the supported preview sizes.
1175         *
1176         * @return a list of Size object. This method will always return a list
1177         *         with at least one element.
1178         */
1179        public List<Size> getSupportedPreviewSizes() {
1180            String str = get(KEY_PREVIEW_SIZE + SUPPORTED_VALUES_SUFFIX);
1181            return splitSize(str);
1182        }
1183
1184        /**
1185         * Sets the dimensions for EXIF thumbnail in Jpeg picture. If
1186         * applications set both width and height to 0, EXIF will not contain
1187         * thumbnail.
1188         *
1189         * @param width  the width of the thumbnail, in pixels
1190         * @param height the height of the thumbnail, in pixels
1191         */
1192        public void setJpegThumbnailSize(int width, int height) {
1193            set(KEY_JPEG_THUMBNAIL_WIDTH, width);
1194            set(KEY_JPEG_THUMBNAIL_HEIGHT, height);
1195        }
1196
1197        /**
1198         * Returns the dimensions for EXIF thumbnail in Jpeg picture.
1199         *
1200         * @return a Size object with the height and width setting for the EXIF
1201         *         thumbnails
1202         */
1203        public Size getJpegThumbnailSize() {
1204            return new Size(getInt(KEY_JPEG_THUMBNAIL_WIDTH),
1205                            getInt(KEY_JPEG_THUMBNAIL_HEIGHT));
1206        }
1207
1208        /**
1209         * Gets the supported jpeg thumbnail sizes.
1210         *
1211         * @return a list of Size object. This method will always return a list
1212         *         with at least two elements. Size 0,0 (no thumbnail) is always
1213         *         supported.
1214         */
1215        public List<Size> getSupportedJpegThumbnailSizes() {
1216            String str = get(KEY_JPEG_THUMBNAIL_SIZE + SUPPORTED_VALUES_SUFFIX);
1217            return splitSize(str);
1218        }
1219
1220        /**
1221         * Sets the quality of the EXIF thumbnail in Jpeg picture.
1222         *
1223         * @param quality the JPEG quality of the EXIF thumbnail. The range is 1
1224         *                to 100, with 100 being the best.
1225         */
1226        public void setJpegThumbnailQuality(int quality) {
1227            set(KEY_JPEG_THUMBNAIL_QUALITY, quality);
1228        }
1229
1230        /**
1231         * Returns the quality setting for the EXIF thumbnail in Jpeg picture.
1232         *
1233         * @return the JPEG quality setting of the EXIF thumbnail.
1234         */
1235        public int getJpegThumbnailQuality() {
1236            return getInt(KEY_JPEG_THUMBNAIL_QUALITY);
1237        }
1238
1239        /**
1240         * Sets Jpeg quality of captured picture.
1241         *
1242         * @param quality the JPEG quality of captured picture. The range is 1
1243         *                to 100, with 100 being the best.
1244         */
1245        public void setJpegQuality(int quality) {
1246            set(KEY_JPEG_QUALITY, quality);
1247        }
1248
1249        /**
1250         * Returns the quality setting for the JPEG picture.
1251         *
1252         * @return the JPEG picture quality setting.
1253         */
1254        public int getJpegQuality() {
1255            return getInt(KEY_JPEG_QUALITY);
1256        }
1257
1258        /**
1259         * Sets the rate at which preview frames are received. This is the
1260         * target frame rate. The actual frame rate depends on the driver.
1261         *
1262         * @param fps the frame rate (frames per second)
1263         */
1264        public void setPreviewFrameRate(int fps) {
1265            set(KEY_PREVIEW_FRAME_RATE, fps);
1266        }
1267
1268        /**
1269         * Returns the setting for the rate at which preview frames are
1270         * received. This is the target frame rate. The actual frame rate
1271         * depends on the driver.
1272         *
1273         * @return the frame rate setting (frames per second)
1274         */
1275        public int getPreviewFrameRate() {
1276            return getInt(KEY_PREVIEW_FRAME_RATE);
1277        }
1278
1279        /**
1280         * Gets the supported preview frame rates.
1281         *
1282         * @return a list of supported preview frame rates. null if preview
1283         *         frame rate setting is not supported.
1284         */
1285        public List<Integer> getSupportedPreviewFrameRates() {
1286            String str = get(KEY_PREVIEW_FRAME_RATE + SUPPORTED_VALUES_SUFFIX);
1287            return splitInt(str);
1288        }
1289
1290        /**
1291         * Sets the image format for preview pictures.
1292         * <p>If this is never called, the default format will be
1293         * {@link android.graphics.ImageFormat#NV21}, which
1294         * uses the NV21 encoding format.</p>
1295         *
1296         * @param pixel_format the desired preview picture format, defined
1297         *   by one of the {@link android.graphics.ImageFormat} constants.
1298         *   (E.g., <var>ImageFormat.NV21</var> (default),
1299         *                      <var>ImageFormat.RGB_565</var>, or
1300         *                      <var>ImageFormat.JPEG</var>)
1301         * @see android.graphics.ImageFormat
1302         */
1303        public void setPreviewFormat(int pixel_format) {
1304            String s = cameraFormatForPixelFormat(pixel_format);
1305            if (s == null) {
1306                throw new IllegalArgumentException(
1307                        "Invalid pixel_format=" + pixel_format);
1308            }
1309
1310            set(KEY_PREVIEW_FORMAT, s);
1311        }
1312
1313        /**
1314         * Returns the image format for preview frames got from
1315         * {@link PreviewCallback}.
1316         *
1317         * @return the preview format.
1318         * @see android.graphics.ImageFormat
1319         */
1320        public int getPreviewFormat() {
1321            return pixelFormatForCameraFormat(get(KEY_PREVIEW_FORMAT));
1322        }
1323
1324        /**
1325         * Gets the supported preview formats.
1326         *
1327         * @return a list of supported preview formats. This method will always
1328         *         return a list with at least one element.
1329         * @see android.graphics.ImageFormat
1330         */
1331        public List<Integer> getSupportedPreviewFormats() {
1332            String str = get(KEY_PREVIEW_FORMAT + SUPPORTED_VALUES_SUFFIX);
1333            ArrayList<Integer> formats = new ArrayList<Integer>();
1334            for (String s : split(str)) {
1335                int f = pixelFormatForCameraFormat(s);
1336                if (f == ImageFormat.UNKNOWN) continue;
1337                formats.add(f);
1338            }
1339            return formats;
1340        }
1341
1342        /**
1343         * Sets the dimensions for pictures.
1344         *
1345         * @param width  the width for pictures, in pixels
1346         * @param height the height for pictures, in pixels
1347         */
1348        public void setPictureSize(int width, int height) {
1349            String v = Integer.toString(width) + "x" + Integer.toString(height);
1350            set(KEY_PICTURE_SIZE, v);
1351        }
1352
1353        /**
1354         * Returns the dimension setting for pictures.
1355         *
1356         * @return a Size object with the height and width setting
1357         *          for pictures
1358         */
1359        public Size getPictureSize() {
1360            String pair = get(KEY_PICTURE_SIZE);
1361            return strToSize(pair);
1362        }
1363
1364        /**
1365         * Gets the supported picture sizes.
1366         *
1367         * @return a list of supported picture sizes. This method will always
1368         *         return a list with at least one element.
1369         */
1370        public List<Size> getSupportedPictureSizes() {
1371            String str = get(KEY_PICTURE_SIZE + SUPPORTED_VALUES_SUFFIX);
1372            return splitSize(str);
1373        }
1374
1375        /**
1376         * Sets the image format for pictures.
1377         *
1378         * @param pixel_format the desired picture format
1379         *                     (<var>ImageFormat.NV21</var>,
1380         *                      <var>ImageFormat.RGB_565</var>, or
1381         *                      <var>ImageFormat.JPEG</var>)
1382         * @see android.graphics.ImageFormat
1383         */
1384        public void setPictureFormat(int pixel_format) {
1385            String s = cameraFormatForPixelFormat(pixel_format);
1386            if (s == null) {
1387                throw new IllegalArgumentException(
1388                        "Invalid pixel_format=" + pixel_format);
1389            }
1390
1391            set(KEY_PICTURE_FORMAT, s);
1392        }
1393
1394        /**
1395         * Returns the image format for pictures.
1396         *
1397         * @return the picture format
1398         * @see android.graphics.ImageFormat
1399         */
1400        public int getPictureFormat() {
1401            return pixelFormatForCameraFormat(get(KEY_PICTURE_FORMAT));
1402        }
1403
1404        /**
1405         * Gets the supported picture formats.
1406         *
1407         * @return supported picture formats. This method will always return a
1408         *         list with at least one element.
1409         * @see android.graphics.ImageFormat
1410         */
1411        public List<Integer> getSupportedPictureFormats() {
1412            String str = get(KEY_PICTURE_FORMAT + SUPPORTED_VALUES_SUFFIX);
1413            ArrayList<Integer> formats = new ArrayList<Integer>();
1414            for (String s : split(str)) {
1415                int f = pixelFormatForCameraFormat(s);
1416                if (f == ImageFormat.UNKNOWN) continue;
1417                formats.add(f);
1418            }
1419            return formats;
1420        }
1421
1422        private String cameraFormatForPixelFormat(int pixel_format) {
1423            switch(pixel_format) {
1424            case ImageFormat.NV16:      return PIXEL_FORMAT_YUV422SP;
1425            case ImageFormat.NV21:      return PIXEL_FORMAT_YUV420SP;
1426            case ImageFormat.YUY2:      return PIXEL_FORMAT_YUV422I;
1427            case ImageFormat.RGB_565:   return PIXEL_FORMAT_RGB565;
1428            case ImageFormat.JPEG:      return PIXEL_FORMAT_JPEG;
1429            default:                    return null;
1430            }
1431        }
1432
1433        private int pixelFormatForCameraFormat(String format) {
1434            if (format == null)
1435                return ImageFormat.UNKNOWN;
1436
1437            if (format.equals(PIXEL_FORMAT_YUV422SP))
1438                return ImageFormat.NV16;
1439
1440            if (format.equals(PIXEL_FORMAT_YUV420SP))
1441                return ImageFormat.NV21;
1442
1443            if (format.equals(PIXEL_FORMAT_YUV422I))
1444                return ImageFormat.YUY2;
1445
1446            if (format.equals(PIXEL_FORMAT_RGB565))
1447                return ImageFormat.RGB_565;
1448
1449            if (format.equals(PIXEL_FORMAT_JPEG))
1450                return ImageFormat.JPEG;
1451
1452            return ImageFormat.UNKNOWN;
1453        }
1454
1455        /**
1456         * Sets the orientation of the device in degrees. For example, suppose
1457         * the natural position of the device is landscape. If the user takes a
1458         * picture in landscape mode in 2048x1536 resolution, the rotation
1459         * should be set to 0. If the user rotates the phone 90 degrees
1460         * clockwise, the rotation should be set to 90. Applications can use
1461         * {@link android.view.OrientationEventListener} to set this parameter.
1462         *
1463         * The camera driver may set orientation in the EXIF header without
1464         * rotating the picture. Or the driver may rotate the picture and
1465         * the EXIF thumbnail. If the Jpeg picture is rotated, the orientation
1466         * in the EXIF header will be missing or 1 (row #0 is top and column #0
1467         * is left side).
1468         *
1469         * @param rotation The orientation of the device in degrees. Rotation
1470         *                 can only be 0, 90, 180 or 270.
1471         * @throws IllegalArgumentException if rotation value is invalid.
1472         * @see android.view.OrientationEventListener
1473         */
1474        public void setRotation(int rotation) {
1475            if (rotation == 0 || rotation == 90 || rotation == 180
1476                    || rotation == 270) {
1477                set(KEY_ROTATION, Integer.toString(rotation));
1478            } else {
1479                throw new IllegalArgumentException(
1480                        "Invalid rotation=" + rotation);
1481            }
1482        }
1483
1484        /**
1485         * Sets GPS latitude coordinate. This will be stored in JPEG EXIF
1486         * header.
1487         *
1488         * @param latitude GPS latitude coordinate.
1489         */
1490        public void setGpsLatitude(double latitude) {
1491            set(KEY_GPS_LATITUDE, Double.toString(latitude));
1492        }
1493
1494        /**
1495         * Sets GPS longitude coordinate. This will be stored in JPEG EXIF
1496         * header.
1497         *
1498         * @param longitude GPS longitude coordinate.
1499         */
1500        public void setGpsLongitude(double longitude) {
1501            set(KEY_GPS_LONGITUDE, Double.toString(longitude));
1502        }
1503
1504        /**
1505         * Sets GPS altitude. This will be stored in JPEG EXIF header.
1506         *
1507         * @param altitude GPS altitude in meters.
1508         */
1509        public void setGpsAltitude(double altitude) {
1510            set(KEY_GPS_ALTITUDE, Double.toString(altitude));
1511        }
1512
1513        /**
1514         * Sets GPS timestamp. This will be stored in JPEG EXIF header.
1515         *
1516         * @param timestamp GPS timestamp (UTC in seconds since January 1,
1517         *                  1970).
1518         */
1519        public void setGpsTimestamp(long timestamp) {
1520            set(KEY_GPS_TIMESTAMP, Long.toString(timestamp));
1521        }
1522
1523        /**
1524         * Sets GPS processing method. It will store up to 32 characters
1525         * in JPEG EXIF header.
1526         *
1527         * @param processing_method The processing method to get this location.
1528         */
1529        public void setGpsProcessingMethod(String processing_method) {
1530            set(KEY_GPS_PROCESSING_METHOD, processing_method);
1531        }
1532
1533        /**
1534         * Removes GPS latitude, longitude, altitude, and timestamp from the
1535         * parameters.
1536         */
1537        public void removeGpsData() {
1538            remove(KEY_GPS_LATITUDE);
1539            remove(KEY_GPS_LONGITUDE);
1540            remove(KEY_GPS_ALTITUDE);
1541            remove(KEY_GPS_TIMESTAMP);
1542            remove(KEY_GPS_PROCESSING_METHOD);
1543        }
1544
1545        /**
1546         * Gets the current white balance setting.
1547         *
1548         * @return current white balance. null if white balance setting is not
1549         *         supported.
1550         * @see #WHITE_BALANCE_AUTO
1551         * @see #WHITE_BALANCE_INCANDESCENT
1552         * @see #WHITE_BALANCE_FLUORESCENT
1553         * @see #WHITE_BALANCE_WARM_FLUORESCENT
1554         * @see #WHITE_BALANCE_DAYLIGHT
1555         * @see #WHITE_BALANCE_CLOUDY_DAYLIGHT
1556         * @see #WHITE_BALANCE_TWILIGHT
1557         * @see #WHITE_BALANCE_SHADE
1558         *
1559         */
1560        public String getWhiteBalance() {
1561            return get(KEY_WHITE_BALANCE);
1562        }
1563
1564        /**
1565         * Sets the white balance.
1566         *
1567         * @param value new white balance.
1568         * @see #getWhiteBalance()
1569         */
1570        public void setWhiteBalance(String value) {
1571            set(KEY_WHITE_BALANCE, value);
1572        }
1573
1574        /**
1575         * Gets the supported white balance.
1576         *
1577         * @return a list of supported white balance. null if white balance
1578         *         setting is not supported.
1579         * @see #getWhiteBalance()
1580         */
1581        public List<String> getSupportedWhiteBalance() {
1582            String str = get(KEY_WHITE_BALANCE + SUPPORTED_VALUES_SUFFIX);
1583            return split(str);
1584        }
1585
1586        /**
1587         * Gets the current color effect setting.
1588         *
1589         * @return current color effect. null if color effect
1590         *         setting is not supported.
1591         * @see #EFFECT_NONE
1592         * @see #EFFECT_MONO
1593         * @see #EFFECT_NEGATIVE
1594         * @see #EFFECT_SOLARIZE
1595         * @see #EFFECT_SEPIA
1596         * @see #EFFECT_POSTERIZE
1597         * @see #EFFECT_WHITEBOARD
1598         * @see #EFFECT_BLACKBOARD
1599         * @see #EFFECT_AQUA
1600         */
1601        public String getColorEffect() {
1602            return get(KEY_EFFECT);
1603        }
1604
1605        /**
1606         * Sets the current color effect setting.
1607         *
1608         * @param value new color effect.
1609         * @see #getColorEffect()
1610         */
1611        public void setColorEffect(String value) {
1612            set(KEY_EFFECT, value);
1613        }
1614
1615        /**
1616         * Gets the supported color effects.
1617         *
1618         * @return a list of supported color effects. null if color effect
1619         *         setting is not supported.
1620         * @see #getColorEffect()
1621         */
1622        public List<String> getSupportedColorEffects() {
1623            String str = get(KEY_EFFECT + SUPPORTED_VALUES_SUFFIX);
1624            return split(str);
1625        }
1626
1627
1628        /**
1629         * Gets the current antibanding setting.
1630         *
1631         * @return current antibanding. null if antibanding setting is not
1632         *         supported.
1633         * @see #ANTIBANDING_AUTO
1634         * @see #ANTIBANDING_50HZ
1635         * @see #ANTIBANDING_60HZ
1636         * @see #ANTIBANDING_OFF
1637         */
1638        public String getAntibanding() {
1639            return get(KEY_ANTIBANDING);
1640        }
1641
1642        /**
1643         * Sets the antibanding.
1644         *
1645         * @param antibanding new antibanding value.
1646         * @see #getAntibanding()
1647         */
1648        public void setAntibanding(String antibanding) {
1649            set(KEY_ANTIBANDING, antibanding);
1650        }
1651
1652        /**
1653         * Gets the supported antibanding values.
1654         *
1655         * @return a list of supported antibanding values. null if antibanding
1656         *         setting is not supported.
1657         * @see #getAntibanding()
1658         */
1659        public List<String> getSupportedAntibanding() {
1660            String str = get(KEY_ANTIBANDING + SUPPORTED_VALUES_SUFFIX);
1661            return split(str);
1662        }
1663
1664        /**
1665         * Gets the current scene mode setting.
1666         *
1667         * @return one of SCENE_MODE_XXX string constant. null if scene mode
1668         *         setting is not supported.
1669         * @see #SCENE_MODE_AUTO
1670         * @see #SCENE_MODE_ACTION
1671         * @see #SCENE_MODE_PORTRAIT
1672         * @see #SCENE_MODE_LANDSCAPE
1673         * @see #SCENE_MODE_NIGHT
1674         * @see #SCENE_MODE_NIGHT_PORTRAIT
1675         * @see #SCENE_MODE_THEATRE
1676         * @see #SCENE_MODE_BEACH
1677         * @see #SCENE_MODE_SNOW
1678         * @see #SCENE_MODE_SUNSET
1679         * @see #SCENE_MODE_STEADYPHOTO
1680         * @see #SCENE_MODE_FIREWORKS
1681         * @see #SCENE_MODE_SPORTS
1682         * @see #SCENE_MODE_PARTY
1683         * @see #SCENE_MODE_CANDLELIGHT
1684         */
1685        public String getSceneMode() {
1686            return get(KEY_SCENE_MODE);
1687        }
1688
1689        /**
1690         * Sets the scene mode. Changing scene mode may override other
1691         * parameters (such as flash mode, focus mode, white balance). For
1692         * example, suppose originally flash mode is on and supported flash
1693         * modes are on/off. In night scene mode, both flash mode and supported
1694         * flash mode may be changed to off. After setting scene mode,
1695         * applications should call getParameters to know if some parameters are
1696         * changed.
1697         *
1698         * @param value scene mode.
1699         * @see #getSceneMode()
1700         */
1701        public void setSceneMode(String value) {
1702            set(KEY_SCENE_MODE, value);
1703        }
1704
1705        /**
1706         * Gets the supported scene modes.
1707         *
1708         * @return a list of supported scene modes. null if scene mode setting
1709         *         is not supported.
1710         * @see #getSceneMode()
1711         */
1712        public List<String> getSupportedSceneModes() {
1713            String str = get(KEY_SCENE_MODE + SUPPORTED_VALUES_SUFFIX);
1714            return split(str);
1715        }
1716
1717        /**
1718         * Gets the current flash mode setting.
1719         *
1720         * @return current flash mode. null if flash mode setting is not
1721         *         supported.
1722         * @see #FLASH_MODE_OFF
1723         * @see #FLASH_MODE_AUTO
1724         * @see #FLASH_MODE_ON
1725         * @see #FLASH_MODE_RED_EYE
1726         * @see #FLASH_MODE_TORCH
1727         */
1728        public String getFlashMode() {
1729            return get(KEY_FLASH_MODE);
1730        }
1731
1732        /**
1733         * Sets the flash mode.
1734         *
1735         * @param value flash mode.
1736         * @see #getFlashMode()
1737         */
1738        public void setFlashMode(String value) {
1739            set(KEY_FLASH_MODE, value);
1740        }
1741
1742        /**
1743         * Gets the supported flash modes.
1744         *
1745         * @return a list of supported flash modes. null if flash mode setting
1746         *         is not supported.
1747         * @see #getFlashMode()
1748         */
1749        public List<String> getSupportedFlashModes() {
1750            String str = get(KEY_FLASH_MODE + SUPPORTED_VALUES_SUFFIX);
1751            return split(str);
1752        }
1753
1754        /**
1755         * Gets the current focus mode setting.
1756         *
1757         * @return current focus mode. If the camera does not support
1758         *         auto-focus, this should return {@link #FOCUS_MODE_FIXED}. If
1759         *         the focus mode is not FOCUS_MODE_FIXED or {@link
1760         *         #FOCUS_MODE_INFINITY}, applications should call {@link
1761         *         #autoFocus(AutoFocusCallback)} to start the focus.
1762         * @see #FOCUS_MODE_AUTO
1763         * @see #FOCUS_MODE_INFINITY
1764         * @see #FOCUS_MODE_MACRO
1765         * @see #FOCUS_MODE_FIXED
1766         */
1767        public String getFocusMode() {
1768            return get(KEY_FOCUS_MODE);
1769        }
1770
1771        /**
1772         * Sets the focus mode.
1773         *
1774         * @param value focus mode.
1775         * @see #getFocusMode()
1776         */
1777        public void setFocusMode(String value) {
1778            set(KEY_FOCUS_MODE, value);
1779        }
1780
1781        /**
1782         * Gets the supported focus modes.
1783         *
1784         * @return a list of supported focus modes. This method will always
1785         *         return a list with at least one element.
1786         * @see #getFocusMode()
1787         */
1788        public List<String> getSupportedFocusModes() {
1789            String str = get(KEY_FOCUS_MODE + SUPPORTED_VALUES_SUFFIX);
1790            return split(str);
1791        }
1792
1793        /**
1794         * Gets the focal length (in millimeter) of the camera.
1795         *
1796         * @return the focal length. This method will always return a valid
1797         *         value.
1798         */
1799        public float getFocalLength() {
1800            return Float.parseFloat(get(KEY_FOCAL_LENGTH));
1801        }
1802
1803        /**
1804         * Gets the horizontal angle of view in degrees.
1805         *
1806         * @return horizontal angle of view. This method will always return a
1807         *         valid value.
1808         */
1809        public float getHorizontalViewAngle() {
1810            return Float.parseFloat(get(KEY_HORIZONTAL_VIEW_ANGLE));
1811        }
1812
1813        /**
1814         * Gets the vertical angle of view in degrees.
1815         *
1816         * @return vertical angle of view. This method will always return a
1817         *         valid value.
1818         */
1819        public float getVerticalViewAngle() {
1820            return Float.parseFloat(get(KEY_VERTICAL_VIEW_ANGLE));
1821        }
1822
1823        /**
1824         * Gets the current exposure compensation index.
1825         *
1826         * @return current exposure compensation index. The range is {@link
1827         *         #getMinExposureCompensation} to {@link
1828         *         #getMaxExposureCompensation}. 0 means exposure is not
1829         *         adjusted.
1830         */
1831        public int getExposureCompensation() {
1832            return getInt(KEY_EXPOSURE_COMPENSATION, 0);
1833        }
1834
1835        /**
1836         * Sets the exposure compensation index.
1837         *
1838         * @param value exposure compensation index. The valid value range is
1839         *        from {@link #getMinExposureCompensation} (inclusive) to {@link
1840         *        #getMaxExposureCompensation} (inclusive). 0 means exposure is
1841         *        not adjusted. Application should call
1842         *        getMinExposureCompensation and getMaxExposureCompensation to
1843         *        know if exposure compensation is supported.
1844         */
1845        public void setExposureCompensation(int value) {
1846            set(KEY_EXPOSURE_COMPENSATION, value);
1847        }
1848
1849        /**
1850         * Gets the maximum exposure compensation index.
1851         *
1852         * @return maximum exposure compensation index (>=0). If both this
1853         *         method and {@link #getMinExposureCompensation} return 0,
1854         *         exposure compensation is not supported.
1855         */
1856        public int getMaxExposureCompensation() {
1857            return getInt(KEY_MAX_EXPOSURE_COMPENSATION, 0);
1858        }
1859
1860        /**
1861         * Gets the minimum exposure compensation index.
1862         *
1863         * @return minimum exposure compensation index (<=0). If both this
1864         *         method and {@link #getMaxExposureCompensation} return 0,
1865         *         exposure compensation is not supported.
1866         */
1867        public int getMinExposureCompensation() {
1868            return getInt(KEY_MIN_EXPOSURE_COMPENSATION, 0);
1869        }
1870
1871        /**
1872         * Gets the exposure compensation step.
1873         *
1874         * @return exposure compensation step. Applications can get EV by
1875         *         multiplying the exposure compensation index and step. Ex: if
1876         *         exposure compensation index is -6 and step is 0.333333333, EV
1877         *         is -2.
1878         */
1879        public float getExposureCompensationStep() {
1880            return getFloat(KEY_EXPOSURE_COMPENSATION_STEP, 0);
1881        }
1882
1883        /**
1884         * Gets current zoom value. This also works when smooth zoom is in
1885         * progress. Applications should check {@link #isZoomSupported} before
1886         * using this method.
1887         *
1888         * @return the current zoom value. The range is 0 to {@link
1889         *         #getMaxZoom}. 0 means the camera is not zoomed.
1890         */
1891        public int getZoom() {
1892            return getInt(KEY_ZOOM, 0);
1893        }
1894
1895        /**
1896         * Sets current zoom value. If the camera is zoomed (value > 0), the
1897         * actual picture size may be smaller than picture size setting.
1898         * Applications can check the actual picture size after picture is
1899         * returned from {@link PictureCallback}. The preview size remains the
1900         * same in zoom. Applications should check {@link #isZoomSupported}
1901         * before using this method.
1902         *
1903         * @param value zoom value. The valid range is 0 to {@link #getMaxZoom}.
1904         */
1905        public void setZoom(int value) {
1906            set(KEY_ZOOM, value);
1907        }
1908
1909        /**
1910         * Returns true if zoom is supported. Applications should call this
1911         * before using other zoom methods.
1912         *
1913         * @return true if zoom is supported.
1914         */
1915        public boolean isZoomSupported() {
1916            String str = get(KEY_ZOOM_SUPPORTED);
1917            return TRUE.equals(str);
1918        }
1919
1920        /**
1921         * Gets the maximum zoom value allowed for snapshot. This is the maximum
1922         * value that applications can set to {@link #setZoom(int)}.
1923         * Applications should call {@link #isZoomSupported} before using this
1924         * method. This value may change in different preview size. Applications
1925         * should call this again after setting preview size.
1926         *
1927         * @return the maximum zoom value supported by the camera.
1928         */
1929        public int getMaxZoom() {
1930            return getInt(KEY_MAX_ZOOM, 0);
1931        }
1932
1933        /**
1934         * Gets the zoom ratios of all zoom values. Applications should check
1935         * {@link #isZoomSupported} before using this method.
1936         *
1937         * @return the zoom ratios in 1/100 increments. Ex: a zoom of 3.2x is
1938         *         returned as 320. The number of elements is {@link
1939         *         #getMaxZoom} + 1. The list is sorted from small to large. The
1940         *         first element is always 100. The last element is the zoom
1941         *         ratio of the maximum zoom value.
1942         */
1943        public List<Integer> getZoomRatios() {
1944            return splitInt(get(KEY_ZOOM_RATIOS));
1945        }
1946
1947        /**
1948         * Returns true if smooth zoom is supported. Applications should call
1949         * this before using other smooth zoom methods.
1950         *
1951         * @return true if smooth zoom is supported.
1952         */
1953        public boolean isSmoothZoomSupported() {
1954            String str = get(KEY_SMOOTH_ZOOM_SUPPORTED);
1955            return TRUE.equals(str);
1956        }
1957
1958        // Splits a comma delimited string to an ArrayList of String.
1959        // Return null if the passing string is null or the size is 0.
1960        private ArrayList<String> split(String str) {
1961            if (str == null) return null;
1962
1963            // Use StringTokenizer because it is faster than split.
1964            StringTokenizer tokenizer = new StringTokenizer(str, ",");
1965            ArrayList<String> substrings = new ArrayList<String>();
1966            while (tokenizer.hasMoreElements()) {
1967                substrings.add(tokenizer.nextToken());
1968            }
1969            return substrings;
1970        }
1971
1972        // Splits a comma delimited string to an ArrayList of Integer.
1973        // Return null if the passing string is null or the size is 0.
1974        private ArrayList<Integer> splitInt(String str) {
1975            if (str == null) return null;
1976
1977            StringTokenizer tokenizer = new StringTokenizer(str, ",");
1978            ArrayList<Integer> substrings = new ArrayList<Integer>();
1979            while (tokenizer.hasMoreElements()) {
1980                String token = tokenizer.nextToken();
1981                substrings.add(Integer.parseInt(token));
1982            }
1983            if (substrings.size() == 0) return null;
1984            return substrings;
1985        }
1986
1987        // Returns the value of a float parameter.
1988        private float getFloat(String key, float defaultValue) {
1989            try {
1990                return Float.parseFloat(mMap.get(key));
1991            } catch (NumberFormatException ex) {
1992                return defaultValue;
1993            }
1994        }
1995
1996        // Returns the value of a integer parameter.
1997        private int getInt(String key, int defaultValue) {
1998            try {
1999                return Integer.parseInt(mMap.get(key));
2000            } catch (NumberFormatException ex) {
2001                return defaultValue;
2002            }
2003        }
2004
2005        // Splits a comma delimited string to an ArrayList of Size.
2006        // Return null if the passing string is null or the size is 0.
2007        private ArrayList<Size> splitSize(String str) {
2008            if (str == null) return null;
2009
2010            StringTokenizer tokenizer = new StringTokenizer(str, ",");
2011            ArrayList<Size> sizeList = new ArrayList<Size>();
2012            while (tokenizer.hasMoreElements()) {
2013                Size size = strToSize(tokenizer.nextToken());
2014                if (size != null) sizeList.add(size);
2015            }
2016            if (sizeList.size() == 0) return null;
2017            return sizeList;
2018        }
2019
2020        // Parses a string (ex: "480x320") to Size object.
2021        // Return null if the passing string is null.
2022        private Size strToSize(String str) {
2023            if (str == null) return null;
2024
2025            int pos = str.indexOf('x');
2026            if (pos != -1) {
2027                String width = str.substring(0, pos);
2028                String height = str.substring(pos + 1);
2029                return new Size(Integer.parseInt(width),
2030                                Integer.parseInt(height));
2031            }
2032            Log.e(TAG, "Invalid size parameter string=" + str);
2033            return null;
2034        }
2035    };
2036}
2037