Camera.java revision da996f390e17e16f2dfa60e972e7ebc4f868f37e
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 enum in libs/android_runtime/android_hardware_Camera.cpp 43 private static final int SHUTTER_CALLBACK = 0; 44 private static final int RAW_PICTURE_CALLBACK = 1; 45 private static final int JPEG_PICTURE_CALLBACK = 2; 46 private static final int PREVIEW_CALLBACK = 3; 47 private static final int AUTOFOCUS_CALLBACK = 4; 48 private static final int ERROR_CALLBACK = 5; 49 50 private int mNativeContext; // accessed by native methods 51 private int mListenerContext; 52 private EventHandler mEventHandler; 53 private ShutterCallback mShutterCallback; 54 private PictureCallback mRawImageCallback; 55 private PictureCallback mJpegCallback; 56 private PreviewCallback mPreviewCallback; 57 private AutoFocusCallback mAutoFocusCallback; 58 private ErrorCallback mErrorCallback; 59 private boolean mOneShot; 60 61 /** 62 * Returns a new Camera object. 63 */ 64 public static Camera open() { 65 return new Camera(); 66 } 67 68 Camera() { 69 mShutterCallback = null; 70 mRawImageCallback = null; 71 mJpegCallback = null; 72 mPreviewCallback = null; 73 74 Looper looper; 75 if ((looper = Looper.myLooper()) != null) { 76 mEventHandler = new EventHandler(this, looper); 77 } else if ((looper = Looper.getMainLooper()) != null) { 78 mEventHandler = new EventHandler(this, looper); 79 } else { 80 mEventHandler = null; 81 } 82 83 native_setup(new WeakReference<Camera>(this)); 84 } 85 86 protected void finalize() { 87 native_release(); 88 } 89 90 private native final void native_setup(Object camera_this); 91 private native final void native_release(); 92 93 94 /** 95 * Disconnects and releases the Camera object resources. 96 * <p>It is recommended that you call this as soon as you're done with the 97 * Camera object.</p> 98 */ 99 public final void release() { 100 native_release(); 101 } 102 103 /** 104 * Reconnect to the camera after passing it to MediaRecorder. To save 105 * setup/teardown time, a client of Camera can pass an initialized Camera 106 * object to a MediaRecorder to use for video recording. Once the 107 * MediaRecorder is done with the Camera, this method can be used to 108 * re-establish a connection with the camera hardware. NOTE: The Camera 109 * object must first be unlocked by the process that owns it before it 110 * can be connected to another proces. 111 * 112 * @throws IOException if the method fails. 113 * 114 * FIXME: Unhide after approval 115 * @hide 116 */ 117 public native final void reconnect() throws IOException; 118 119 /** 120 * Lock the camera to prevent other processes from accessing it. To save 121 * setup/teardown time, a client of Camera can pass an initialized Camera 122 * object to another process. This method is used to re-lock the Camera 123 * object prevent other processes from accessing it. By default, the 124 * Camera object is locked. Locking it again from the same process will 125 * have no effect. Attempting to lock it from another process if it has 126 * not been unlocked will fail. 127 * Returns 0 if lock was successful. 128 * 129 * FIXME: Unhide after approval 130 * @hide 131 */ 132 public native final int lock(); 133 134 /** 135 * Unlock the camera to allow aother process to access it. To save 136 * setup/teardown time, a client of Camera can pass an initialized Camera 137 * object to another process. This method is used to unlock the Camera 138 * object before handing off the Camera object to the other process. 139 140 * Returns 0 if unlock was successful. 141 * 142 * FIXME: Unhide after approval 143 * @hide 144 */ 145 public native final int unlock(); 146 147 /** 148 * Sets the SurfaceHolder to be used for a picture preview. If the surface 149 * changed since the last call, the screen will blank. Nothing happens 150 * if the same surface is re-set. 151 * 152 * @param holder the SurfaceHolder upon which to place the picture preview 153 * @throws IOException if the method fails. 154 */ 155 public final void setPreviewDisplay(SurfaceHolder holder) throws IOException { 156 setPreviewDisplay(holder.getSurface()); 157 } 158 159 private native final void setPreviewDisplay(Surface surface); 160 161 /** 162 * Used to get a copy of each preview frame. 163 */ 164 public interface PreviewCallback 165 { 166 /** 167 * The callback that delivers the preview frames. 168 * 169 * @param data The contents of the preview frame in getPreviewFormat() 170 * format. 171 * @param camera The Camera service object. 172 */ 173 void onPreviewFrame(byte[] data, Camera camera); 174 }; 175 176 /** 177 * Start drawing preview frames to the surface. 178 */ 179 public native final void startPreview(); 180 181 /** 182 * Stop drawing preview frames to the surface. 183 */ 184 public native final void stopPreview(); 185 186 /** 187 * Return current preview state. 188 * 189 * FIXME: Unhide before release 190 * @hide 191 */ 192 public native final boolean previewEnabled(); 193 194 /** 195 * Can be called at any time to instruct the camera to use a callback for 196 * each preview frame in addition to displaying it. 197 * 198 * @param cb A callback object that receives a copy of each preview frame. 199 * Pass null to stop receiving callbacks at any time. 200 */ 201 public final void setPreviewCallback(PreviewCallback cb) { 202 mPreviewCallback = cb; 203 mOneShot = false; 204 setHasPreviewCallback(cb != null, false); 205 } 206 207 /** 208 * Installs a callback to retrieve a single preview frame, after which the 209 * callback is cleared. 210 * 211 * @param cb A callback object that receives a copy of the preview frame. 212 */ 213 public final void setOneShotPreviewCallback(PreviewCallback cb) { 214 if (cb != null) { 215 mPreviewCallback = cb; 216 mOneShot = true; 217 setHasPreviewCallback(true, true); 218 } 219 } 220 221 private native final void setHasPreviewCallback(boolean installed, boolean oneshot); 222 223 private class EventHandler extends Handler 224 { 225 private Camera mCamera; 226 227 public EventHandler(Camera c, Looper looper) { 228 super(looper); 229 mCamera = c; 230 } 231 232 @Override 233 public void handleMessage(Message msg) { 234 switch(msg.what) { 235 case SHUTTER_CALLBACK: 236 if (mShutterCallback != null) { 237 mShutterCallback.onShutter(); 238 } 239 return; 240 case RAW_PICTURE_CALLBACK: 241 if (mRawImageCallback != null) 242 mRawImageCallback.onPictureTaken((byte[])msg.obj, mCamera); 243 return; 244 245 case JPEG_PICTURE_CALLBACK: 246 if (mJpegCallback != null) 247 mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera); 248 return; 249 250 case PREVIEW_CALLBACK: 251 if (mPreviewCallback != null) { 252 mPreviewCallback.onPreviewFrame((byte[])msg.obj, mCamera); 253 if (mOneShot) { 254 mPreviewCallback = null; 255 } 256 } 257 return; 258 259 case AUTOFOCUS_CALLBACK: 260 if (mAutoFocusCallback != null) 261 mAutoFocusCallback.onAutoFocus(msg.arg1 == 0 ? false : true, mCamera); 262 return; 263 264 case ERROR_CALLBACK: 265 Log.e(TAG, "Error " + msg.arg1); 266 if (mErrorCallback != null) 267 mErrorCallback.onError(msg.arg1, mCamera); 268 return; 269 270 default: 271 Log.e(TAG, "Unknown message type " + msg.what); 272 return; 273 } 274 } 275 } 276 277 private static void postEventFromNative(Object camera_ref, 278 int what, int arg1, int arg2, Object obj) 279 { 280 Camera c = (Camera)((WeakReference)camera_ref).get(); 281 if (c == null) 282 return; 283 284 if (c.mEventHandler != null) { 285 Message m = c.mEventHandler.obtainMessage(what, arg1, arg2, obj); 286 c.mEventHandler.sendMessage(m); 287 } 288 } 289 290 /** 291 * Handles the callback for the camera auto focus. 292 */ 293 public interface AutoFocusCallback 294 { 295 /** 296 * Callback for the camera auto focus. 297 * 298 * @param success true if focus was successful, false if otherwise 299 * @param camera the Camera service object 300 */ 301 void onAutoFocus(boolean success, Camera camera); 302 }; 303 304 /** 305 * Starts auto-focus function and registers a callback function to 306 * run when camera is focused. Only valid after startPreview() has 307 * been called. 308 * 309 * @param cb the callback to run 310 */ 311 public final void autoFocus(AutoFocusCallback cb) 312 { 313 mAutoFocusCallback = cb; 314 native_autoFocus(); 315 } 316 private native final void native_autoFocus(); 317 318 /** 319 * An interface which contains a callback for the shutter closing after taking a picture. 320 */ 321 public interface ShutterCallback 322 { 323 /** 324 * Can be used to play a shutter sound as soon as the image has been captured, but before 325 * the data is available. 326 */ 327 void onShutter(); 328 } 329 330 /** 331 * Handles the callback for when a picture is taken. 332 */ 333 public interface PictureCallback { 334 /** 335 * Callback for when a picture is taken. 336 * 337 * @param data a byte array of the picture data 338 * @param camera the Camera service object 339 */ 340 void onPictureTaken(byte[] data, Camera camera); 341 }; 342 343 /** 344 * Triggers an asynchronous image capture. The camera service 345 * will initiate a series of callbacks to the application as the 346 * image capture progresses. The shutter callback occurs after 347 * the image is captured. This can be used to trigger a sound 348 * to let the user know that image has been captured. The raw 349 * callback occurs when the raw image data is available. The jpeg 350 * callback occurs when the compressed image is available. If the 351 * application does not need a particular callback, a null can be 352 * passed instead of a callback method. 353 * 354 * @param shutter callback after the image is captured, may be null 355 * @param raw callback with raw image data, may be null 356 * @param jpeg callback with jpeg image data, may be null 357 */ 358 public final void takePicture(ShutterCallback shutter, PictureCallback raw, 359 PictureCallback jpeg) { 360 mShutterCallback = shutter; 361 mRawImageCallback = raw; 362 mJpegCallback = jpeg; 363 native_takePicture(); 364 } 365 private native final void native_takePicture(); 366 367 // These match the enum in libs/android_runtime/android_hardware_Camera.cpp 368 /** Unspecified camerar error. @see #ErrorCallback */ 369 public static final int CAMERA_ERROR_UNKNOWN = 1; 370 /** Media server died. In this case, the application must release the 371 * Camera object and instantiate a new one. @see #ErrorCallback */ 372 public static final int CAMERA_ERROR_SERVER_DIED = 100; 373 374 /** 375 * Handles the camera error callback. 376 */ 377 public interface ErrorCallback 378 { 379 /** 380 * Callback for camera errors. 381 * @param error error code: 382 * <ul> 383 * <li>{@link #CAMERA_ERROR_UNKNOWN} 384 * <li>{@link #CAMERA_ERROR_SERVER_DIED} 385 * </ul> 386 * @param camera the Camera service object 387 */ 388 void onError(int error, Camera camera); 389 }; 390 391 /** 392 * Registers a callback to be invoked when an error occurs. 393 * @param cb the callback to run 394 */ 395 public final void setErrorCallback(ErrorCallback cb) 396 { 397 mErrorCallback = cb; 398 } 399 400 private native final void native_setParameters(String params); 401 private native final String native_getParameters(); 402 403 /** 404 * Sets the Parameters for pictures from this Camera service. 405 * 406 * @param params the Parameters to use for this Camera service 407 */ 408 public void setParameters(Parameters params) { 409 Log.e(TAG, "setParameters()"); 410 //params.dump(); 411 native_setParameters(params.flatten()); 412 } 413 414 /** 415 * Returns the picture Parameters for this Camera service. 416 */ 417 public Parameters getParameters() { 418 Parameters p = new Parameters(); 419 String s = native_getParameters(); 420 Log.e(TAG, "_getParameters: " + s); 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