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