Camera.java revision b798689749c64baba81f02e10cf2157c747d6b46
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.HashMap;
21import java.io.IOException;
22
23import android.util.Log;
24import android.view.Surface;
25import android.view.SurfaceHolder;
26import android.graphics.PixelFormat;
27import android.os.Handler;
28import android.os.Looper;
29import android.os.Message;
30
31/**
32 * The Camera class is used to connect/disconnect with the camera service,
33 * set capture settings, start/stop preview, snap a picture, and retrieve
34 * frames for encoding for video.
35 * <p>There is no default constructor for this class. Use {@link #open()} to
36 * get a Camera object.</p>
37 */
38public class Camera {
39    private static final String TAG = "Camera";
40
41    // These match the enum in libs/android_runtime/android_hardware_Camera.cpp
42    private static final int SHUTTER_CALLBACK = 0;
43    private static final int RAW_PICTURE_CALLBACK = 1;
44    private static final int JPEG_PICTURE_CALLBACK = 2;
45    private static final int PREVIEW_CALLBACK = 3;
46    private static final int AUTOFOCUS_CALLBACK = 4;
47    private static final int ERROR_CALLBACK = 5;
48
49    private int mNativeContext; // accessed by native methods
50    private int mListenerContext;
51    private EventHandler mEventHandler;
52    private ShutterCallback mShutterCallback;
53    private PictureCallback mRawImageCallback;
54    private PictureCallback mJpegCallback;
55    private PreviewCallback mPreviewCallback;
56    private AutoFocusCallback mAutoFocusCallback;
57    private ErrorCallback mErrorCallback;
58
59    /**
60     * Returns a new Camera object.
61     */
62    public static Camera open() {
63        return new Camera();
64    }
65
66    Camera() {
67        mShutterCallback = null;
68        mRawImageCallback = null;
69        mJpegCallback = null;
70        mPreviewCallback = null;
71
72        Looper looper;
73        if ((looper = Looper.myLooper()) != null) {
74            mEventHandler = new EventHandler(this, looper);
75        } else if ((looper = Looper.getMainLooper()) != null) {
76            mEventHandler = new EventHandler(this, looper);
77        } else {
78            mEventHandler = null;
79        }
80
81        native_setup(new WeakReference<Camera>(this));
82    }
83
84    protected void finalize() {
85        native_release();
86    }
87
88    private native final void native_setup(Object camera_this);
89    private native final void native_release();
90
91
92    /**
93     * Disconnects and releases the Camera object resources.
94     * <p>It is recommended that you call this as soon as you're done with the
95     * Camera object.</p>
96     */
97    public final void release() {
98        native_release();
99    }
100
101    /**
102     * Reconnect to the camera after passing it to MediaRecorder. To save
103     * setup/teardown time, a client of Camera can pass an initialized Camera
104     * object to a MediaRecorder to use for video recording. Once the
105     * MediaRecorder is done with the Camera, this method can be used to
106     * re-establish a connection with the camera hardware. NOTE: The Camera
107     * object must first be unlocked by the process that owns it before it
108     * can be connected to another proces.
109     *
110     * @throws IOException if the method fails.
111     *
112     * FIXME: Unhide after approval
113     * @hide
114     */
115    public native final void reconnect() throws IOException;
116
117    /**
118     * Lock the camera to prevent other processes from accessing it. To save
119     * setup/teardown time, a client of Camera can pass an initialized Camera
120     * object to another process. This method is used to re-lock the Camera
121     * object prevent other processes from accessing it. By default, the
122     * Camera object is locked. Locking it again from the same process will
123     * have no effect. Attempting to lock it from another process if it has
124     * not been unlocked will fail.
125     * Returns 0 if lock was successful.
126     *
127     * FIXME: Unhide after approval
128     * @hide
129     */
130    public native final int lock();
131
132    /**
133     * Unlock the camera to allow aother process to access it. To save
134     * setup/teardown time, a client of Camera can pass an initialized Camera
135     * object to another process. This method is used to unlock the Camera
136     * object before handing off the Camera object to the other process.
137
138     * Returns 0 if unlock was successful.
139     *
140     * FIXME: Unhide after approval
141     * @hide
142     */
143    public native final int unlock();
144
145    /**
146     * Sets the SurfaceHolder to be used for a picture preview. If the surface
147     * changed since the last call, the screen will blank. Nothing happens
148     * if the same surface is re-set.
149     *
150     * @param holder the SurfaceHolder upon which to place the picture preview
151     * @throws IOException if the method fails.
152     */
153    public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
154        setPreviewDisplay(holder.getSurface());
155    }
156
157    private native final void setPreviewDisplay(Surface surface);
158
159    /**
160     * Used to get a copy of each preview frame.
161     */
162    public interface PreviewCallback
163    {
164        /**
165         * The callback that delivers the preview frames.
166         *
167         * @param data The contents of the preview frame in getPreviewFormat()
168         *             format.
169         * @param camera The Camera service object.
170         */
171        void onPreviewFrame(byte[] data, Camera camera);
172    };
173
174    /**
175     * Start drawing preview frames to the surface.
176     */
177    public native final void startPreview();
178
179    /**
180     * Stop drawing preview frames to the surface.
181     */
182    public native final void stopPreview();
183
184    /**
185     * Return current preview state.
186     *
187     * FIXME: Unhide before release
188     * @hide
189     */
190    public native final boolean previewEnabled();
191
192    /**
193     * Can be called at any time to instruct the camera to use a callback for
194     * each preview frame in addition to displaying it.
195     *
196     * @param cb A callback object that receives a copy of each preview frame.
197     *           Pass null to stop receiving callbacks at any time.
198     */
199    public final void setPreviewCallback(PreviewCallback cb) {
200        mPreviewCallback = cb;
201        setHasPreviewCallback(cb != null);
202    }
203    private native final void setHasPreviewCallback(boolean installed);
204
205    private class EventHandler extends Handler
206    {
207        private Camera mCamera;
208
209        public EventHandler(Camera c, Looper looper) {
210            super(looper);
211            mCamera = c;
212        }
213
214        @Override
215        public void handleMessage(Message msg) {
216            switch(msg.what) {
217            case SHUTTER_CALLBACK:
218                if (mShutterCallback != null) {
219                    mShutterCallback.onShutter();
220                }
221                return;
222            case RAW_PICTURE_CALLBACK:
223                if (mRawImageCallback != null)
224                    mRawImageCallback.onPictureTaken((byte[])msg.obj, mCamera);
225                return;
226
227            case JPEG_PICTURE_CALLBACK:
228                if (mJpegCallback != null)
229                    mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera);
230                return;
231
232            case PREVIEW_CALLBACK:
233                if (mPreviewCallback != null)
234                    mPreviewCallback.onPreviewFrame((byte[])msg.obj, mCamera);
235                return;
236
237            case AUTOFOCUS_CALLBACK:
238                if (mAutoFocusCallback != null)
239                    mAutoFocusCallback.onAutoFocus(msg.arg1 == 0 ? false : true, mCamera);
240                return;
241
242            case ERROR_CALLBACK:
243                Log.e(TAG, "Error " + msg.arg1);
244                if (mErrorCallback != null)
245                    mErrorCallback.onError(msg.arg1, mCamera);
246                return;
247
248            default:
249                Log.e(TAG, "Unknown message type " + msg.what);
250                return;
251            }
252        }
253    }
254
255    private static void postEventFromNative(Object camera_ref,
256                                            int what, int arg1, int arg2, Object obj)
257    {
258        Camera c = (Camera)((WeakReference)camera_ref).get();
259        if (c == null)
260            return;
261
262        if (c.mEventHandler != null) {
263            Message m = c.mEventHandler.obtainMessage(what, arg1, arg2, obj);
264            c.mEventHandler.sendMessage(m);
265        }
266    }
267
268    /**
269     * Handles the callback for the camera auto focus.
270     */
271    public interface AutoFocusCallback
272    {
273        /**
274         * Callback for the camera auto focus.
275         *
276         * @param success true if focus was successful, false if otherwise
277         * @param camera  the Camera service object
278         */
279        void onAutoFocus(boolean success, Camera camera);
280    };
281
282    /**
283     * Starts auto-focus function and registers a callback function to
284     * run when camera is focused. Only valid after startPreview() has
285     * been called.
286     *
287     * @param cb the callback to run
288     */
289    public final void autoFocus(AutoFocusCallback cb)
290    {
291        mAutoFocusCallback = cb;
292        native_autoFocus();
293    }
294    private native final void native_autoFocus();
295
296    /**
297     * An interface which contains a callback for the shutter closing after taking a picture.
298     */
299    public interface ShutterCallback
300    {
301        /**
302         * Can be used to play a shutter sound as soon as the image has been captured, but before
303         * the data is available.
304         */
305        void onShutter();
306    }
307
308    /**
309     * Handles the callback for when a picture is taken.
310     */
311    public interface PictureCallback {
312        /**
313         * Callback for when a picture is taken.
314         *
315         * @param data   a byte array of the picture data
316         * @param camera the Camera service object
317         */
318        void onPictureTaken(byte[] data, Camera camera);
319    };
320
321    /**
322     * Triggers an asynchronous image capture. The camera service
323     * will initiate a series of callbacks to the application as the
324     * image capture progresses. The shutter callback occurs after
325     * the image is captured. This can be used to trigger a sound
326     * to let the user know that image has been captured. The raw
327     * callback occurs when the raw image data is available. The jpeg
328     * callback occurs when the compressed image is available. If the
329     * application does not need a particular callback, a null can be
330     * passed instead of a callback method.
331     *
332     * @param shutter   callback after the image is captured, may be null
333     * @param raw       callback with raw image data, may be null
334     * @param jpeg      callback with jpeg image data, may be null
335     */
336    public final void takePicture(ShutterCallback shutter, PictureCallback raw,
337            PictureCallback jpeg) {
338        mShutterCallback = shutter;
339        mRawImageCallback = raw;
340        mJpegCallback = jpeg;
341        native_takePicture();
342    }
343    private native final void native_takePicture();
344
345    // These match the enum in libs/android_runtime/android_hardware_Camera.cpp
346    /** Unspecified camerar error.  @see #ErrorCallback */
347    public static final int CAMERA_ERROR_UNKNOWN = 1;
348    /** Media server died. In this case, the application must release the
349     * Camera object and instantiate a new one. @see #ErrorCallback */
350    public static final int CAMERA_ERROR_SERVER_DIED = 100;
351
352    /**
353     * Handles the camera error callback.
354     */
355    public interface ErrorCallback
356    {
357        /**
358         * Callback for camera errors.
359         * @param error   error code:
360         * <ul>
361         * <li>{@link #CAMERA_ERROR_UNKNOWN}
362         * <li>{@link #CAMERA_ERROR_SERVER_DIED}
363         * </ul>
364         * @param camera  the Camera service object
365         */
366        void onError(int error, Camera camera);
367    };
368
369    /**
370     * Registers a callback to be invoked when an error occurs.
371     * @param cb the callback to run
372     */
373    public final void setErrorCallback(ErrorCallback cb)
374    {
375        mErrorCallback = cb;
376    }
377
378    private native final void native_setParameters(String params);
379    private native final String native_getParameters();
380
381    /**
382     * Sets the Parameters for pictures from this Camera service.
383     *
384     * @param params the Parameters to use for this Camera service
385     */
386    public void setParameters(Parameters params) {
387        Log.e(TAG, "setParameters()");
388        //params.dump();
389        native_setParameters(params.flatten());
390    }
391
392    /**
393     * Returns the picture Parameters for this Camera service.
394     */
395    public Parameters getParameters() {
396        Parameters p = new Parameters();
397        String s = native_getParameters();
398        Log.e(TAG, "_getParameters: " + s);
399        p.unflatten(s);
400        return p;
401    }
402
403    /**
404     * Handles the picture size (dimensions).
405     */
406    public class Size {
407        /**
408         * Sets the dimensions for pictures.
409         *
410         * @param w the photo width (pixels)
411         * @param h the photo height (pixels)
412         */
413        public Size(int w, int h) {
414            width = w;
415            height = h;
416        }
417        /** width of the picture */
418        public int width;
419        /** height of the picture */
420        public int height;
421    };
422
423    /**
424     * Handles the parameters for pictures created by a Camera service.
425     */
426    public class Parameters {
427        private HashMap<String, String> mMap;
428
429        private Parameters() {
430            mMap = new HashMap<String, String>();
431        }
432
433        /**
434         * Writes the current Parameters to the log.
435         * @hide
436         * @deprecated
437         */
438        public void dump() {
439            Log.e(TAG, "dump: size=" + mMap.size());
440            for (String k : mMap.keySet()) {
441                Log.e(TAG, "dump: " + k + "=" + mMap.get(k));
442            }
443        }
444
445        /**
446         * Creates a single string with all the parameters set in
447         * this Parameters object.
448         * <p>The {@link #unflatten(String)} method does the reverse.</p>
449         *
450         * @return a String with all values from this Parameters object, in
451         *         semi-colon delimited key-value pairs
452         */
453        public String flatten() {
454            StringBuilder flattened = new StringBuilder();
455            for (String k : mMap.keySet()) {
456                flattened.append(k);
457                flattened.append("=");
458                flattened.append(mMap.get(k));
459                flattened.append(";");
460            }
461            // chop off the extra semicolon at the end
462            flattened.deleteCharAt(flattened.length()-1);
463            return flattened.toString();
464        }
465
466        /**
467         * Takes a flattened string of parameters and adds each one to
468         * this Parameters object.
469         * <p>The {@link #flatten()} method does the reverse.</p>
470         *
471         * @param flattened a String of parameters (key-value paired) that
472         *                  are semi-colon delimited
473         */
474        public void unflatten(String flattened) {
475            mMap.clear();
476            String[] pairs = flattened.split(";");
477            for (String p : pairs) {
478                String[] kv = p.split("=");
479                if (kv.length == 2)
480                    mMap.put(kv[0], kv[1]);
481            }
482        }
483
484        public void remove(String key) {
485            mMap.remove(key);
486        }
487
488        /**
489         * Sets a String parameter.
490         *
491         * @param key   the key name for the parameter
492         * @param value the String value of the parameter
493         */
494        public void set(String key, String value) {
495            if (key.indexOf('=') != -1 || key.indexOf(';') != -1) {
496                Log.e(TAG, "Key \"" + key + "\" contains invalid character (= or ;)");
497                return;
498            }
499            if (value.indexOf('=') != -1 || value.indexOf(';') != -1) {
500                Log.e(TAG, "Value \"" + value + "\" contains invalid character (= or ;)");
501                return;
502            }
503
504            mMap.put(key, value);
505        }
506
507        /**
508         * Sets an integer parameter.
509         *
510         * @param key   the key name for the parameter
511         * @param value the int value of the parameter
512         */
513        public void set(String key, int value) {
514            mMap.put(key, Integer.toString(value));
515        }
516
517        /**
518         * Returns the value of a String parameter.
519         *
520         * @param key the key name for the parameter
521         * @return the String value of the parameter
522         */
523        public String get(String key) {
524            return mMap.get(key);
525        }
526
527        /**
528         * Returns the value of an integer parameter.
529         *
530         * @param key the key name for the parameter
531         * @return the int value of the parameter
532         */
533        public int getInt(String key) {
534            return Integer.parseInt(mMap.get(key));
535        }
536
537        /**
538         * Sets the dimensions for preview pictures.
539         *
540         * @param width  the width of the pictures, in pixels
541         * @param height the height of the pictures, in pixels
542         */
543        public void setPreviewSize(int width, int height) {
544            String v = Integer.toString(width) + "x" + Integer.toString(height);
545            set("preview-size", v);
546        }
547
548        /**
549         * Returns the dimensions setting for preview pictures.
550         *
551         * @return a Size object with the height and width setting
552         *          for the preview picture
553         */
554        public Size getPreviewSize() {
555            String pair = get("preview-size");
556            if (pair == null)
557                return null;
558            String[] dims = pair.split("x");
559            if (dims.length != 2)
560                return null;
561
562            return new Size(Integer.parseInt(dims[0]),
563                            Integer.parseInt(dims[1]));
564
565        }
566
567        /**
568         * Sets the dimensions for EXIF thumbnails.
569         *
570         * @param width  the width of the thumbnail, in pixels
571         * @param height the height of the thumbnail, in pixels
572         *
573         * FIXME: unhide before release
574         * @hide
575         */
576        public void setThumbnailSize(int width, int height) {
577            set("jpeg-thumbnail-width", width);
578            set("jpeg-thumbnail-height", height);
579        }
580
581        /**
582         * Returns the dimensions for EXIF thumbnail
583         *
584         * @return a Size object with the height and width setting
585         *          for the EXIF thumbnails
586         *
587         * FIXME: unhide before release
588         * @hide
589         */
590        public Size getThumbnailSize() {
591            return new Size(getInt("jpeg-thumbnail-width"),
592                            getInt("jpeg-thumbnail-height"));
593        }
594
595        /**
596         * Sets the quality of the EXIF thumbnail
597         *
598         * @param quality the JPEG quality of the EXIT thumbnail
599         *
600         * FIXME: unhide before release
601         * @hide
602         */
603        public void setThumbnailQuality(int quality) {
604            set("jpeg-thumbnail-quality", quality);
605        }
606
607        /**
608         * Returns the quality setting for the EXIF thumbnail
609         *
610         * @return the JPEG quality setting of the EXIF thumbnail
611         *
612         * FIXME: unhide before release
613         * @hide
614         */
615        public int getThumbnailQuality() {
616            return getInt("jpeg-thumbnail-quality");
617        }
618
619        /**
620         * Sets the rate at which preview frames are received.
621         *
622         * @param fps the frame rate (frames per second)
623         */
624        public void setPreviewFrameRate(int fps) {
625            set("preview-frame-rate", fps);
626        }
627
628        /**
629         * Returns the setting for the rate at which preview frames
630         * are received.
631         *
632         * @return the frame rate setting (frames per second)
633         */
634        public int getPreviewFrameRate() {
635            return getInt("preview-frame-rate");
636        }
637
638        /**
639         * Sets the image format for preview pictures.
640         *
641         * @param pixel_format the desired preview picture format
642         *                     (<var>PixelFormat.YCbCr_420_SP</var>,
643         *                      <var>PixelFormat.RGB_565</var>, or
644         *                      <var>PixelFormat.JPEG</var>)
645         * @see android.graphics.PixelFormat
646         */
647        public void setPreviewFormat(int pixel_format) {
648            String s = cameraFormatForPixelFormat(pixel_format);
649            if (s == null) {
650                throw new IllegalArgumentException();
651            }
652
653            set("preview-format", s);
654        }
655
656        /**
657         * Returns the image format for preview pictures.
658         *
659         * @return the PixelFormat int representing the preview picture format
660         */
661        public int getPreviewFormat() {
662            return pixelFormatForCameraFormat(get("preview-format"));
663        }
664
665        /**
666         * Sets the dimensions for pictures.
667         *
668         * @param width  the width for pictures, in pixels
669         * @param height the height for pictures, in pixels
670         */
671        public void setPictureSize(int width, int height) {
672            String v = Integer.toString(width) + "x" + Integer.toString(height);
673            set("picture-size", v);
674        }
675
676        /**
677         * Returns the dimension setting for pictures.
678         *
679         * @return a Size object with the height and width setting
680         *          for pictures
681         */
682        public Size getPictureSize() {
683            String pair = get("picture-size");
684            if (pair == null)
685                return null;
686            String[] dims = pair.split("x");
687            if (dims.length != 2)
688                return null;
689
690            return new Size(Integer.parseInt(dims[0]),
691                            Integer.parseInt(dims[1]));
692
693        }
694
695        /**
696         * Sets the image format for pictures.
697         *
698         * @param pixel_format the desired picture format
699         *                     (<var>PixelFormat.YCbCr_420_SP</var>,
700         *                      <var>PixelFormat.RGB_565</var>, or
701         *                      <var>PixelFormat.JPEG</var>)
702         * @see android.graphics.PixelFormat
703         */
704        public void setPictureFormat(int pixel_format) {
705            String s = cameraFormatForPixelFormat(pixel_format);
706            if (s == null) {
707                throw new IllegalArgumentException();
708            }
709
710            set("picture-format", s);
711        }
712
713        /**
714         * Returns the image format for pictures.
715         *
716         * @return the PixelFormat int representing the picture format
717         */
718        public int getPictureFormat() {
719            return pixelFormatForCameraFormat(get("picture-format"));
720        }
721
722        private String cameraFormatForPixelFormat(int pixel_format) {
723            switch(pixel_format) {
724            case PixelFormat.YCbCr_422_SP: return "yuv422sp";
725            case PixelFormat.YCbCr_420_SP: return "yuv420sp";
726            case PixelFormat.RGB_565:      return "rgb565";
727            case PixelFormat.JPEG:         return "jpeg";
728            default:                       return null;
729            }
730        }
731
732        private int pixelFormatForCameraFormat(String format) {
733            if (format == null)
734                return PixelFormat.UNKNOWN;
735
736            if (format.equals("yuv422sp"))
737                return PixelFormat.YCbCr_422_SP;
738
739            if (format.equals("yuv420sp"))
740                return PixelFormat.YCbCr_420_SP;
741
742            if (format.equals("rgb565"))
743                return PixelFormat.RGB_565;
744
745            if (format.equals("jpeg"))
746                return PixelFormat.JPEG;
747
748            return PixelFormat.UNKNOWN;
749        }
750
751    };
752}
753
754
755