CameraAgent.java revision 25ee73acd2dbd6f60deef5306994fbf3a7997936
1/* 2 * Copyright (C) 2012 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 com.android.ex.camera2.portability; 18 19import android.annotation.TargetApi; 20import android.graphics.SurfaceTexture; 21import android.hardware.Camera; 22import android.hardware.Camera.OnZoomChangeListener; 23import android.os.Build; 24import android.os.Handler; 25import android.os.Looper; 26import android.view.SurfaceHolder; 27 28import com.android.ex.camera2.portability.debug.Log; 29 30/** 31 * An interface which provides possible camera device operations. 32 * 33 * The client should call {@code CameraAgent.openCamera} to get an instance 34 * of {@link CameraAgent.CameraProxy} to control the camera. Classes 35 * implementing this interface should have its own one unique {@code Thread} 36 * other than the main thread for camera operations. Camera device callbacks 37 * are wrapped since the client should not deal with 38 * {@code android.hardware.Camera} directly. 39 * 40 * TODO: provide callback interfaces for: 41 * {@code android.hardware.Camera.ErrorCallback}, 42 * {@code android.hardware.Camera.OnZoomChangeListener}, and 43 */ 44public abstract class CameraAgent { 45 public static final long CAMERA_OPERATION_TIMEOUT_MS = 2500; 46 47 private static final Log.Tag TAG = new Log.Tag("CamAgnt"); 48 49 public static class CameraStartPreviewCallbackForward 50 implements CameraStartPreviewCallback { 51 private final Handler mHandler; 52 private final CameraStartPreviewCallback mCallback; 53 54 public static CameraStartPreviewCallbackForward getNewInstance( 55 Handler handler, CameraStartPreviewCallback cb) { 56 if (handler == null || cb == null) { 57 return null; 58 } 59 return new CameraStartPreviewCallbackForward(handler, cb); 60 } 61 62 private CameraStartPreviewCallbackForward(Handler h, 63 CameraStartPreviewCallback cb) { 64 mHandler = h; 65 mCallback = cb; 66 } 67 68 @Override 69 public void onPreviewStarted() { 70 mHandler.post(new Runnable() { 71 @Override 72 public void run() { 73 mCallback.onPreviewStarted(); 74 }}); 75 } 76 } 77 78 /** 79 * A callback helps to invoke the original callback on another 80 * {@link android.os.Handler}. 81 */ 82 public static class CameraOpenCallbackForward implements CameraOpenCallback { 83 private final Handler mHandler; 84 private final CameraOpenCallback mCallback; 85 86 /** 87 * Returns a new instance of {@link FaceDetectionCallbackForward}. 88 * 89 * @param handler The handler in which the callback will be invoked in. 90 * @param cb The callback to be invoked. 91 * @return The instance of the {@link FaceDetectionCallbackForward}, or 92 * null if any parameter is null. 93 */ 94 public static CameraOpenCallbackForward getNewInstance( 95 Handler handler, CameraOpenCallback cb) { 96 if (handler == null || cb == null) { 97 return null; 98 } 99 return new CameraOpenCallbackForward(handler, cb); 100 } 101 102 private CameraOpenCallbackForward(Handler h, CameraOpenCallback cb) { 103 // Given that we are using the main thread handler, we can create it 104 // here instead of holding onto the PhotoModule objects. In this 105 // way, we can avoid memory leak. 106 mHandler = new Handler(Looper.getMainLooper()); 107 mCallback = cb; 108 } 109 110 @Override 111 public void onCameraOpened(final CameraProxy camera) { 112 mHandler.post(new Runnable() { 113 @Override 114 public void run() { 115 mCallback.onCameraOpened(camera); 116 }}); 117 } 118 119 @Override 120 public void onCameraDisabled(final int cameraId) { 121 mHandler.post(new Runnable() { 122 @Override 123 public void run() { 124 mCallback.onCameraDisabled(cameraId); 125 }}); 126 } 127 128 @Override 129 public void onDeviceOpenFailure(final int cameraId, final String info) { 130 mHandler.post(new Runnable() { 131 @Override 132 public void run() { 133 mCallback.onDeviceOpenFailure(cameraId, info); 134 }}); 135 } 136 137 @Override 138 public void onDeviceOpenedAlready(final int cameraId, final String info) { 139 mHandler.post(new Runnable() { 140 @Override 141 public void run() { 142 mCallback.onDeviceOpenedAlready(cameraId, info); 143 }}); 144 } 145 146 @Override 147 public void onReconnectionFailure(final CameraAgent mgr, final String info) { 148 mHandler.post(new Runnable() { 149 @Override 150 public void run() { 151 mCallback.onReconnectionFailure(mgr, info); 152 }}); 153 } 154 } 155 156 /** 157 * A handler for all camera api runtime exceptions. 158 * The default behavior is to throw the runtime exception. 159 */ 160 public static interface CameraExceptionCallback { 161 public void onCameraException(RuntimeException e); 162 } 163 164 /** 165 * An interface which wraps 166 * {@link android.hardware.Camera.ErrorCallback} 167 */ 168 public static interface CameraErrorCallback { 169 public void onError(int error, CameraProxy camera); 170 } 171 172 /** 173 * An interface which wraps 174 * {@link android.hardware.Camera.AutoFocusCallback}. 175 */ 176 public static interface CameraAFCallback { 177 public void onAutoFocus(boolean focused, CameraProxy camera); 178 } 179 180 /** 181 * An interface which wraps 182 * {@link android.hardware.Camera.AutoFocusMoveCallback}. 183 */ 184 public static interface CameraAFMoveCallback { 185 public void onAutoFocusMoving(boolean moving, CameraProxy camera); 186 } 187 188 /** 189 * An interface which wraps 190 * {@link android.hardware.Camera.ShutterCallback}. 191 */ 192 public static interface CameraShutterCallback { 193 public void onShutter(CameraProxy camera); 194 } 195 196 /** 197 * An interface which wraps 198 * {@link android.hardware.Camera.PictureCallback}. 199 */ 200 public static interface CameraPictureCallback { 201 public void onPictureTaken(byte[] data, CameraProxy camera); 202 } 203 204 /** 205 * An interface which wraps 206 * {@link android.hardware.Camera.PreviewCallback}. 207 */ 208 public static interface CameraPreviewDataCallback { 209 public void onPreviewFrame(byte[] data, CameraProxy camera); 210 } 211 212 /** 213 * An interface which wraps 214 * {@link android.hardware.Camera.FaceDetectionListener}. 215 */ 216 public static interface CameraFaceDetectionCallback { 217 /** 218 * Callback for face detection. 219 * 220 * @param faces Recognized face in the preview. 221 * @param camera The camera which the preview image comes from. 222 */ 223 public void onFaceDetection(Camera.Face[] faces, CameraProxy camera); 224 } 225 226 /** 227 * An interface to be called when the camera preview has started. 228 */ 229 public static interface CameraStartPreviewCallback { 230 /** 231 * Callback when the preview starts. 232 */ 233 public void onPreviewStarted(); 234 } 235 236 /** 237 * An interface to be called for any events when opening or closing the 238 * camera device. This error callback is different from the one defined 239 * in the framework, {@link android.hardware.Camera.ErrorCallback}, which 240 * is used after the camera is opened. 241 */ 242 public static interface CameraOpenCallback { 243 /** 244 * Callback when camera open succeeds. 245 */ 246 public void onCameraOpened(CameraProxy camera); 247 248 /** 249 * Callback when {@link com.android.camera.CameraDisabledException} is 250 * caught. 251 * 252 * @param cameraId The disabled camera. 253 */ 254 public void onCameraDisabled(int cameraId); 255 256 /** 257 * Callback when {@link com.android.camera.CameraHardwareException} is 258 * caught. 259 * 260 * @param cameraId The camera with the hardware failure. 261 * @param info The extra info regarding this failure. 262 */ 263 public void onDeviceOpenFailure(int cameraId, String info); 264 265 /** 266 * Callback when trying to open the camera which is already opened. 267 * 268 * @param cameraId The camera which is causing the open error. 269 */ 270 public void onDeviceOpenedAlready(int cameraId, String info); 271 272 /** 273 * Callback when {@link java.io.IOException} is caught during 274 * {@link android.hardware.Camera#reconnect()}. 275 * 276 * @param mgr The {@link CameraAgent} 277 * with the reconnect failure. 278 */ 279 public void onReconnectionFailure(CameraAgent mgr, String info); 280 } 281 282 /** 283 * Opens the camera of the specified ID asynchronously. The camera device 284 * will be opened in the camera handler thread and will be returned through 285 * the {@link CameraAgent.CameraOpenCallback# 286 * onCameraOpened(com.android.camera.cameradevice.CameraAgent.CameraProxy)}. 287 * 288 * @param handler The {@link android.os.Handler} in which the callback 289 * was handled. 290 * @param callback The callback for the result. 291 * @param cameraId The camera ID to open. 292 */ 293 public void openCamera(final Handler handler, final int cameraId, 294 final CameraOpenCallback callback) { 295 getDispatchThread().runJob(new Runnable() { 296 @Override 297 public void run() { 298 getCameraHandler().obtainMessage(CameraActions.OPEN_CAMERA, cameraId, 0, 299 CameraOpenCallbackForward.getNewInstance(handler, callback)).sendToTarget(); 300 }}); 301 } 302 303 /** 304 * Closes the camera device. 305 * 306 * @param camera The camera to close. {@code null} means all. 307 * @param synced Whether this call should be synchronous. 308 */ 309 public void closeCamera(CameraProxy camera, boolean synced) { 310 if (synced) { 311 final WaitDoneBundle bundle = new WaitDoneBundle(); 312 313 getDispatchThread().runJobSync(new Runnable() { 314 @Override 315 public void run() { 316 getCameraHandler().obtainMessage(CameraActions.RELEASE).sendToTarget(); 317 getCameraHandler().post(bundle.mUnlockRunnable); 318 }}, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "camera release"); 319 } else { 320 getDispatchThread().runJob(new Runnable() { 321 @Override 322 public void run() { 323 getCameraHandler().removeCallbacksAndMessages(null); 324 getCameraHandler().obtainMessage(CameraActions.RELEASE).sendToTarget(); 325 }}); 326 } 327 } 328 329 /** 330 * Sets a callback for handling camera api runtime exceptions on 331 * a handler. 332 */ 333 public abstract void setCameraDefaultExceptionCallback(CameraExceptionCallback callback, 334 Handler handler); 335 336 /** 337 * Recycles the resources used by this instance. CameraAgent will be in 338 * an unusable state after calling this. 339 */ 340 public abstract void recycle(); 341 342 /** 343 * @return The camera devices info. 344 */ 345 public abstract CameraDeviceInfo getCameraDeviceInfo(); 346 347 /** 348 * @return The handler to which camera tasks should be posted. 349 */ 350 protected abstract Handler getCameraHandler(); 351 352 /** 353 * @return The thread used on which client callbacks are served. 354 */ 355 protected abstract DispatchThread getDispatchThread(); 356 357 /** 358 * An interface that takes camera operation requests and post messages to the 359 * camera handler thread. All camera operations made through this interface is 360 * asynchronous by default except those mentioned specifically. 361 */ 362 public static abstract class CameraProxy { 363 364 /** 365 * Returns the underlying {@link android.hardware.Camera} object used 366 * by this proxy. This method should only be used when handing the 367 * camera device over to {@link android.media.MediaRecorder} for 368 * recording. 369 */ 370 @Deprecated 371 public abstract android.hardware.Camera getCamera(); 372 373 /** 374 * @return The camera ID associated to by this 375 * {@link CameraAgent.CameraProxy}. 376 */ 377 public abstract int getCameraId(); 378 379 /** 380 * @return The camera characteristics. 381 */ 382 public abstract CameraDeviceInfo.Characteristics getCharacteristics(); 383 384 /** 385 * @return The camera capabilities. 386 */ 387 public abstract CameraCapabilities getCapabilities(); 388 389 /** 390 * Reconnects to the camera device. On success, the camera device will 391 * be returned through {@link CameraAgent 392 * .CameraOpenCallback#onCameraOpened(com.android.camera.cameradevice.CameraAgent 393 * .CameraProxy)}. 394 * @see android.hardware.Camera#reconnect() 395 * 396 * @param handler The {@link android.os.Handler} in which the callback 397 * was handled. 398 * @param cb The callback when any error happens. 399 */ 400 public void reconnect(final Handler handler, final CameraOpenCallback cb) { 401 getDispatchThread().runJob(new Runnable() { 402 @Override 403 public void run() { 404 getCameraHandler().obtainMessage(CameraActions.RECONNECT, getCameraId(), 0, 405 CameraOpenCallbackForward.getNewInstance(handler, cb)).sendToTarget(); 406 }}); 407 } 408 409 /** 410 * Unlocks the camera device. 411 * 412 * @see android.hardware.Camera#unlock() 413 */ 414 public void unlock() { 415 final WaitDoneBundle bundle = new WaitDoneBundle(); 416 getDispatchThread().runJobSync(new Runnable() { 417 @Override 418 public void run() { 419 getCameraHandler().sendEmptyMessage(CameraActions.UNLOCK); 420 getCameraHandler().post(bundle.mUnlockRunnable); 421 }}, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "camera unlock"); 422 } 423 424 /** 425 * Locks the camera device. 426 * @see android.hardware.Camera#lock() 427 */ 428 public void lock() { 429 getDispatchThread().runJob(new Runnable() { 430 @Override 431 public void run() { 432 getCameraHandler().sendEmptyMessage(CameraActions.LOCK); 433 }}); 434 } 435 436 /** 437 * Sets the {@link android.graphics.SurfaceTexture} for preview. 438 * 439 * <p>Note that, once this operation has been performed, it is no longer 440 * possible to change the preview or photo sizes in the 441 * {@link CameraSettings} instance for this camera, and the mutators for 442 * these fields are allowed to ignore all further invocations until the 443 * preview is stopped with {@link #stopPreview}.</p> 444 * 445 * @param surfaceTexture The {@link SurfaceTexture} for preview. 446 * 447 * @see CameraSettings#setPhotoSize 448 * @see CameraSettings#setPreviewSize 449 */ 450 // XXX: Despite the above documentation about locking the sizes, the API 451 // 1 implementation doesn't currently enforce this at all, although the 452 // Camera class warns that preview sizes shouldn't be changed while a 453 // preview is running. Furthermore, the API 2 implementation doesn't yet 454 // unlock the sizes when stopPreview() is invoked (see related FIXME on 455 // the STOP_PREVIEW case in its handler; in the meantime, changing API 2 456 // sizes would require closing and reopening the camera. 457 public void setPreviewTexture(final SurfaceTexture surfaceTexture) { 458 getDispatchThread().runJob(new Runnable() { 459 @Override 460 public void run() { 461 getCameraHandler() 462 .obtainMessage(CameraActions.SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture) 463 .sendToTarget(); 464 }}); 465 } 466 467 /** 468 * Blocks until a {@link android.graphics.SurfaceTexture} has been set 469 * for preview. 470 * 471 * <p>Note that, once this operation has been performed, it is no longer 472 * possible to change the preview or photo sizes in the 473 * {@link CameraSettings} instance for this camera, and the mutators for 474 * these fields are allowed to ignore all further invocations.</p> 475 * 476 * @param surfaceTexture The {@link SurfaceTexture} for preview. 477 * 478 * @see CameraSettings#setPhotoSize 479 * @see CameraSettings#setPreviewSize 480 */ 481 public void setPreviewTextureSync(final SurfaceTexture surfaceTexture) { 482 final WaitDoneBundle bundle = new WaitDoneBundle(); 483 getDispatchThread().runJobSync(new Runnable() { 484 @Override 485 public void run() { 486 getCameraHandler() 487 .obtainMessage(CameraActions.SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture) 488 .sendToTarget(); 489 getCameraHandler().post(bundle.mUnlockRunnable); 490 }}, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "set preview texture"); 491 } 492 493 /** 494 * Sets the {@link android.view.SurfaceHolder} for preview. 495 * 496 * @param surfaceHolder The {@link SurfaceHolder} for preview. 497 */ 498 public void setPreviewDisplay(final SurfaceHolder surfaceHolder) { 499 getDispatchThread().runJob(new Runnable() { 500 @Override 501 public void run() { 502 getCameraHandler() 503 .obtainMessage(CameraActions.SET_PREVIEW_DISPLAY_ASYNC, surfaceHolder) 504 .sendToTarget(); 505 }}); 506 } 507 508 /** 509 * Starts the camera preview. 510 */ 511 public void startPreview() { 512 getDispatchThread().runJob(new Runnable() { 513 @Override 514 public void run() { 515 getCameraHandler() 516 .obtainMessage(CameraActions.START_PREVIEW_ASYNC, null).sendToTarget(); 517 }}); 518 } 519 520 /** 521 * Starts the camera preview and executes a callback on a handler once 522 * the preview starts. 523 */ 524 public void startPreviewWithCallback(final Handler h, final CameraStartPreviewCallback cb) { 525 getDispatchThread().runJob(new Runnable() { 526 @Override 527 public void run() { 528 getCameraHandler().obtainMessage(CameraActions.START_PREVIEW_ASYNC, 529 CameraStartPreviewCallbackForward.getNewInstance(h, cb)) 530 .sendToTarget(); 531 }}); 532 } 533 534 /** 535 * Stops the camera preview synchronously. 536 * {@code stopPreview()} must be synchronous to ensure that the caller can 537 * continues to release resources related to camera preview. 538 */ 539 public void stopPreview() { 540 final WaitDoneBundle bundle = new WaitDoneBundle(); 541 getDispatchThread().runJobSync(new Runnable() { 542 @Override 543 public void run() { 544 getCameraHandler().sendEmptyMessage(CameraActions.STOP_PREVIEW); 545 getCameraHandler().post(bundle.mUnlockRunnable); 546 }}, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "stop preview"); 547 } 548 549 /** 550 * Sets the callback for preview data. 551 * 552 * @param handler The {@link android.os.Handler} in which the callback was handled. 553 * @param cb The callback to be invoked when the preview data is available. 554 * @see android.hardware.Camera#setPreviewCallback(android.hardware.Camera.PreviewCallback) 555 */ 556 public abstract void setPreviewDataCallback(Handler handler, CameraPreviewDataCallback cb); 557 558 /** 559 * Sets the one-time callback for preview data. 560 * 561 * @param handler The {@link android.os.Handler} in which the callback was handled. 562 * @param cb The callback to be invoked when the preview data for 563 * next frame is available. 564 * @see android.hardware.Camera#setPreviewCallback(android.hardware.Camera.PreviewCallback) 565 */ 566 public abstract void setOneShotPreviewCallback(Handler handler, 567 CameraPreviewDataCallback cb); 568 569 /** 570 * Sets the callback for preview data. 571 * 572 * @param handler The handler in which the callback will be invoked. 573 * @param cb The callback to be invoked when the preview data is available. 574 * @see android.hardware.Camera#setPreviewCallbackWithBuffer(android.hardware.Camera.PreviewCallback) 575 */ 576 public abstract void setPreviewDataCallbackWithBuffer(Handler handler, 577 CameraPreviewDataCallback cb); 578 579 /** 580 * Adds buffer for the preview callback. 581 * 582 * @param callbackBuffer The buffer allocated for the preview data. 583 */ 584 public void addCallbackBuffer(final byte[] callbackBuffer) { 585 getDispatchThread().runJob(new Runnable() { 586 @Override 587 public void run() { 588 getCameraHandler() 589 .obtainMessage(CameraActions.ADD_CALLBACK_BUFFER, callbackBuffer) 590 .sendToTarget(); 591 } 592 }); 593 } 594 595 /** 596 * Starts the auto-focus process. The result will be returned through the callback. 597 * 598 * @param handler The handler in which the callback will be invoked. 599 * @param cb The auto-focus callback. 600 */ 601 public abstract void autoFocus(Handler handler, CameraAFCallback cb); 602 603 /** 604 * Cancels the auto-focus process. 605 */ 606 public void cancelAutoFocus() { 607 getDispatchThread().runJob(new Runnable() { 608 @Override 609 public void run() { 610 getCameraHandler().removeMessages(CameraActions.AUTO_FOCUS); 611 getCameraHandler().sendEmptyMessage(CameraActions.CANCEL_AUTO_FOCUS); 612 }}); 613 } 614 615 /** 616 * Sets the auto-focus callback 617 * 618 * @param handler The handler in which the callback will be invoked. 619 * @param cb The callback to be invoked when the preview data is available. 620 */ 621 @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 622 public abstract void setAutoFocusMoveCallback(Handler handler, CameraAFMoveCallback cb); 623 624 /** 625 * Instrument the camera to take a picture. 626 * 627 * @param handler The handler in which the callback will be invoked. 628 * @param shutter The callback for shutter action, may be null. 629 * @param raw The callback for uncompressed data, may be null. 630 * @param postview The callback for postview image data, may be null. 631 * @param jpeg The callback for jpeg image data, may be null. 632 * @see android.hardware.Camera#takePicture( 633 * android.hardware.Camera.ShutterCallback, 634 * android.hardware.Camera.PictureCallback, 635 * android.hardware.Camera.PictureCallback) 636 */ 637 public abstract void takePicture( 638 Handler handler, 639 CameraShutterCallback shutter, 640 CameraPictureCallback raw, 641 CameraPictureCallback postview, 642 CameraPictureCallback jpeg); 643 644 /** 645 * Sets the display orientation for camera to adjust the preview and JPEG orientation. 646 * 647 * @param degrees The counterclockwise rotation in degrees, relative to the device's natural 648 * orientation. Should be 0, 90, 180 or 270. 649 */ 650 public void setDisplayOrientation(final int degrees) { 651 setDisplayOrientation(degrees, true); 652 } 653 654 /** 655 * Sets the display orientation for camera to adjust the preview—and, optionally, 656 * JPEG—orientations. 657 * <p>If capture rotation is not requested, future captures will be returned in the sensor's 658 * physical rotation, which does not necessarily match the device's natural orientation.</p> 659 * 660 * @param degrees The counterclockwise rotation in degrees, relative to the device's natural 661 * orientation. Should be 0, 90, 180 or 270. 662 * @param capture Whether to adjust the JPEG capture orientation as well as the preview one. 663 */ 664 public void setDisplayOrientation(final int degrees, final boolean capture) { 665 getDispatchThread().runJob(new Runnable() { 666 @Override 667 public void run() { 668 getCameraHandler() 669 .obtainMessage(CameraActions.SET_DISPLAY_ORIENTATION, degrees, 670 capture ? 1 : 0) 671 .sendToTarget(); 672 }}); 673 } 674 675 public void setJpegOrientation(final int degrees) { 676 getDispatchThread().runJob(new Runnable() { 677 @Override 678 public void run() { 679 getCameraHandler() 680 .obtainMessage(CameraActions.SET_JPEG_ORIENTATION, degrees, 0) 681 .sendToTarget(); 682 }}); 683 } 684 685 /** 686 * Sets the listener for zoom change. 687 * 688 * @param listener The listener. 689 */ 690 public abstract void setZoomChangeListener(OnZoomChangeListener listener); 691 692 /** 693 * Sets the face detection listener. 694 * 695 * @param handler The handler in which the callback will be invoked. 696 * @param callback The callback for face detection results. 697 */ 698 public abstract void setFaceDetectionCallback(Handler handler, 699 CameraFaceDetectionCallback callback); 700 701 /** 702 * Starts the face detection. 703 */ 704 public void startFaceDetection() { 705 getDispatchThread().runJob(new Runnable() { 706 @Override 707 public void run() { 708 getCameraHandler().sendEmptyMessage(CameraActions.START_FACE_DETECTION); 709 }}); 710 } 711 712 /** 713 * Stops the face detection. 714 */ 715 public void stopFaceDetection() { 716 getDispatchThread().runJob(new Runnable() { 717 @Override 718 public void run() { 719 getCameraHandler().sendEmptyMessage(CameraActions.STOP_FACE_DETECTION); 720 }}); 721 } 722 723 /** 724 * Registers an error callback. 725 * 726 * @param handler The handler on which the callback will be invoked. 727 * @param cb The error callback. 728 * @see android.hardware.Camera#setErrorCallback(android.hardware.Camera.ErrorCallback) 729 */ 730 public abstract void setErrorCallback(Handler handler, CameraErrorCallback cb); 731 732 /** 733 * Sets the camera parameters. 734 * 735 * @param params The camera parameters to use. 736 */ 737 @Deprecated 738 public abstract void setParameters(Camera.Parameters params); 739 740 /** 741 * Gets the current camera parameters synchronously. This method is 742 * synchronous since the caller has to wait for the camera to return 743 * the parameters. If the parameters are already cached, it returns 744 * immediately. 745 */ 746 @Deprecated 747 public abstract Camera.Parameters getParameters(); 748 749 /** 750 * Gets the current camera settings synchronously. 751 * <p>This method is synchronous since the caller has to wait for the 752 * camera to return the parameters. If the parameters are already 753 * cached, it returns immediately.</p> 754 */ 755 public abstract CameraSettings getSettings(); 756 757 /** 758 * Default implementation of {@link #applySettings(CameraSettings)} 759 * that is only missing the set of states it needs to wait for 760 * before applying the settings. 761 * 762 * @param settings The settings to use on the device. 763 * @param statesToAwait Bitwise OR of the required camera states. 764 * @return Whether the settings can be applied. 765 */ 766 protected boolean applySettingsHelper(CameraSettings settings, 767 final int statesToAwait) { 768 if (settings == null) { 769 Log.v(TAG, "null argument in applySettings()"); 770 return false; 771 } 772 if (!getCapabilities().supports(settings)) { 773 Log.w(TAG, "Unsupported settings in applySettings()"); 774 return false; 775 } 776 777 final CameraSettings copyOfSettings = settings.copy(); 778 getDispatchThread().runJob(new Runnable() { 779 @Override 780 public void run() { 781 getCameraState().waitForStates(statesToAwait); 782 getCameraHandler().obtainMessage(CameraActions.APPLY_SETTINGS, copyOfSettings) 783 .sendToTarget(); 784 }}); 785 return true; 786 } 787 788 /** 789 * Applies the settings to the camera device. 790 * 791 * @param settings The settings to use on the device. 792 * @return Whether the settings can be applied. 793 */ 794 public abstract boolean applySettings(CameraSettings settings); 795 796 /** 797 * Forces {@code CameraProxy} to update the cached version of the camera 798 * settings regardless of the dirty bit. 799 */ 800 public void refreshSettings() { 801 getDispatchThread().runJob(new Runnable() { 802 @Override 803 public void run() { 804 getCameraHandler().sendEmptyMessage(CameraActions.REFRESH_PARAMETERS); 805 }}); 806 } 807 808 /** 809 * Enables/Disables the camera shutter sound. 810 * 811 * @param enable {@code true} to enable the shutter sound, 812 * {@code false} to disable it. 813 */ 814 public void enableShutterSound(final boolean enable) { 815 getDispatchThread().runJob(new Runnable() { 816 @Override 817 public void run() { 818 getCameraHandler() 819 .obtainMessage(CameraActions.ENABLE_SHUTTER_SOUND, (enable ? 1 : 0), 0) 820 .sendToTarget(); 821 }}); 822 } 823 824 /** 825 * Dumps the current settings of the camera device. 826 * 827 * <p>The content varies based on the underlying camera API settings 828 * implementation.</p> 829 * 830 * @return The content of the device settings represented by a string. 831 */ 832 public abstract String dumpDeviceSettings(); 833 834 /** 835 * @return The handler to which camera tasks should be posted. 836 */ 837 public abstract Handler getCameraHandler(); 838 839 /** 840 * @return The thread used on which client callbacks are served. 841 */ 842 public abstract DispatchThread getDispatchThread(); 843 844 /** 845 * @return The state machine tracking the camera API's current mode. 846 */ 847 public abstract CameraStateHolder getCameraState(); 848 } 849 850 public static class WaitDoneBundle { 851 public final Runnable mUnlockRunnable; 852 public final Object mWaitLock; 853 854 WaitDoneBundle() { 855 mWaitLock = new Object(); 856 mUnlockRunnable = new Runnable() { 857 @Override 858 public void run() { 859 synchronized (mWaitLock) { 860 mWaitLock.notifyAll(); 861 } 862 }}; 863 } 864 } 865} 866