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