CameraAgent.java revision de48004068f8c16f9a56c60b0ed2485a67687b4b
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 * @param surfaceTexture The {@link SurfaceTexture} for preview. 440 */ 441 public void setPreviewTexture(final SurfaceTexture surfaceTexture) { 442 getDispatchThread().runJob(new Runnable() { 443 @Override 444 public void run() { 445 getCameraHandler() 446 .obtainMessage(CameraActions.SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture) 447 .sendToTarget(); 448 }}); 449 } 450 451 /** 452 * Blocks until a {@link android.graphics.SurfaceTexture} has been set 453 * for preview. 454 * 455 * @param surfaceTexture The {@link SurfaceTexture} for preview. 456 */ 457 public void setPreviewTextureSync(final SurfaceTexture surfaceTexture) { 458 final WaitDoneBundle bundle = new WaitDoneBundle(); 459 getDispatchThread().runJobSync(new Runnable() { 460 @Override 461 public void run() { 462 getCameraHandler() 463 .obtainMessage(CameraActions.SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture) 464 .sendToTarget(); 465 getCameraHandler().post(bundle.mUnlockRunnable); 466 }}, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "set preview texture"); 467 } 468 469 /** 470 * Sets the {@link android.view.SurfaceHolder} for preview. 471 * 472 * @param surfaceHolder The {@link SurfaceHolder} for preview. 473 */ 474 public void setPreviewDisplay(final SurfaceHolder surfaceHolder) { 475 getDispatchThread().runJob(new Runnable() { 476 @Override 477 public void run() { 478 getCameraHandler() 479 .obtainMessage(CameraActions.SET_PREVIEW_DISPLAY_ASYNC, surfaceHolder) 480 .sendToTarget(); 481 }}); 482 } 483 484 /** 485 * Starts the camera preview. 486 */ 487 public void startPreview() { 488 getDispatchThread().runJob(new Runnable() { 489 @Override 490 public void run() { 491 getCameraHandler() 492 .obtainMessage(CameraActions.START_PREVIEW_ASYNC, null).sendToTarget(); 493 }}); 494 } 495 496 /** 497 * Starts the camera preview and executes a callback on a handler once 498 * the preview starts. 499 */ 500 public void startPreviewWithCallback(final Handler h, final CameraStartPreviewCallback cb) { 501 getDispatchThread().runJob(new Runnable() { 502 @Override 503 public void run() { 504 getCameraHandler().obtainMessage(CameraActions.START_PREVIEW_ASYNC, 505 CameraStartPreviewCallbackForward.getNewInstance(h, cb)) 506 .sendToTarget(); 507 }}); 508 } 509 510 /** 511 * Stops the camera preview synchronously. 512 * {@code stopPreview()} must be synchronous to ensure that the caller can 513 * continues to release resources related to camera preview. 514 */ 515 public void stopPreview() { 516 final WaitDoneBundle bundle = new WaitDoneBundle(); 517 getDispatchThread().runJobSync(new Runnable() { 518 @Override 519 public void run() { 520 getCameraHandler().sendEmptyMessage(CameraActions.STOP_PREVIEW); 521 getCameraHandler().post(bundle.mUnlockRunnable); 522 }}, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "stop preview"); 523 } 524 525 /** 526 * Sets the callback for preview data. 527 * 528 * @param handler The {@link android.os.Handler} in which the callback was handled. 529 * @param cb The callback to be invoked when the preview data is available. 530 * @see android.hardware.Camera#setPreviewCallback(android.hardware.Camera.PreviewCallback) 531 */ 532 public abstract void setPreviewDataCallback(Handler handler, CameraPreviewDataCallback cb); 533 534 /** 535 * Sets the one-time callback for preview data. 536 * 537 * @param handler The {@link android.os.Handler} in which the callback was handled. 538 * @param cb The callback to be invoked when the preview data for 539 * next frame is available. 540 * @see android.hardware.Camera#setPreviewCallback(android.hardware.Camera.PreviewCallback) 541 */ 542 public abstract void setOneShotPreviewCallback(Handler handler, 543 CameraPreviewDataCallback cb); 544 545 /** 546 * Sets the callback for preview data. 547 * 548 * @param handler The handler in which the callback will be invoked. 549 * @param cb The callback to be invoked when the preview data is available. 550 * @see android.hardware.Camera#setPreviewCallbackWithBuffer(android.hardware.Camera.PreviewCallback) 551 */ 552 public abstract void setPreviewDataCallbackWithBuffer(Handler handler, 553 CameraPreviewDataCallback cb); 554 555 /** 556 * Adds buffer for the preview callback. 557 * 558 * @param callbackBuffer The buffer allocated for the preview data. 559 */ 560 public void addCallbackBuffer(final byte[] callbackBuffer) { 561 getDispatchThread().runJob(new Runnable() { 562 @Override 563 public void run() { 564 getCameraHandler() 565 .obtainMessage(CameraActions.ADD_CALLBACK_BUFFER, callbackBuffer) 566 .sendToTarget(); 567 } 568 }); 569 } 570 571 /** 572 * Starts the auto-focus process. The result will be returned through the callback. 573 * 574 * @param handler The handler in which the callback will be invoked. 575 * @param cb The auto-focus callback. 576 */ 577 public abstract void autoFocus(Handler handler, CameraAFCallback cb); 578 579 /** 580 * Cancels the auto-focus process. 581 */ 582 public void cancelAutoFocus() { 583 getDispatchThread().runJob(new Runnable() { 584 @Override 585 public void run() { 586 getCameraHandler().removeMessages(CameraActions.AUTO_FOCUS); 587 getCameraHandler().sendEmptyMessage(CameraActions.CANCEL_AUTO_FOCUS); 588 }}); 589 } 590 591 /** 592 * Sets the auto-focus callback 593 * 594 * @param handler The handler in which the callback will be invoked. 595 * @param cb The callback to be invoked when the preview data is available. 596 */ 597 @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 598 public abstract void setAutoFocusMoveCallback(Handler handler, CameraAFMoveCallback cb); 599 600 /** 601 * Instrument the camera to take a picture. 602 * 603 * @param handler The handler in which the callback will be invoked. 604 * @param shutter The callback for shutter action, may be null. 605 * @param raw The callback for uncompressed data, may be null. 606 * @param postview The callback for postview image data, may be null. 607 * @param jpeg The callback for jpeg image data, may be null. 608 * @see android.hardware.Camera#takePicture( 609 * android.hardware.Camera.ShutterCallback, 610 * android.hardware.Camera.PictureCallback, 611 * android.hardware.Camera.PictureCallback) 612 */ 613 public abstract void takePicture( 614 Handler handler, 615 CameraShutterCallback shutter, 616 CameraPictureCallback raw, 617 CameraPictureCallback postview, 618 CameraPictureCallback jpeg); 619 620 /** 621 * Sets the display orientation for camera to adjust the preview and JPEG orientation. 622 * 623 * @param degrees The counterclockwise rotation in degrees, relative to the device's natural 624 * orientation. Should be 0, 90, 180 or 270. 625 */ 626 public void setDisplayOrientation(final int degrees) { 627 setDisplayOrientation(degrees, true); 628 } 629 630 /** 631 * Sets the display orientation for camera to adjust the preview—and, optionally, 632 * JPEG—orientations. 633 * <p>If capture rotation is not requested, future captures will be returned in the sensor's 634 * physical rotation, which does not necessarily match the device's natural orientation.</p> 635 * 636 * @param degrees The counterclockwise rotation in degrees, relative to the device's natural 637 * orientation. Should be 0, 90, 180 or 270. 638 * @param capture Whether to adjust the JPEG capture orientation as well as the preview one. 639 */ 640 public void setDisplayOrientation(final int degrees, final boolean capture) { 641 getDispatchThread().runJob(new Runnable() { 642 @Override 643 public void run() { 644 getCameraHandler() 645 .obtainMessage(CameraActions.SET_DISPLAY_ORIENTATION, degrees, 646 capture ? 1 : 0) 647 .sendToTarget(); 648 }}); 649 } 650 651 /** 652 * Sets the listener for zoom change. 653 * 654 * @param listener The listener. 655 */ 656 public abstract void setZoomChangeListener(OnZoomChangeListener listener); 657 658 /** 659 * Sets the face detection listener. 660 * 661 * @param handler The handler in which the callback will be invoked. 662 * @param callback The callback for face detection results. 663 */ 664 public abstract void setFaceDetectionCallback(Handler handler, 665 CameraFaceDetectionCallback callback); 666 667 /** 668 * Starts the face detection. 669 */ 670 public void startFaceDetection() { 671 getDispatchThread().runJob(new Runnable() { 672 @Override 673 public void run() { 674 getCameraHandler().sendEmptyMessage(CameraActions.START_FACE_DETECTION); 675 }}); 676 } 677 678 /** 679 * Stops the face detection. 680 */ 681 public void stopFaceDetection() { 682 getDispatchThread().runJob(new Runnable() { 683 @Override 684 public void run() { 685 getCameraHandler().sendEmptyMessage(CameraActions.STOP_FACE_DETECTION); 686 }}); 687 } 688 689 /** 690 * Registers an error callback. 691 * 692 * @param handler The handler on which the callback will be invoked. 693 * @param cb The error callback. 694 * @see android.hardware.Camera#setErrorCallback(android.hardware.Camera.ErrorCallback) 695 */ 696 public abstract void setErrorCallback(Handler handler, CameraErrorCallback cb); 697 698 /** 699 * Sets the camera parameters. 700 * 701 * @param params The camera parameters to use. 702 */ 703 @Deprecated 704 public abstract void setParameters(Camera.Parameters params); 705 706 /** 707 * Gets the current camera parameters synchronously. This method is 708 * synchronous since the caller has to wait for the camera to return 709 * the parameters. If the parameters are already cached, it returns 710 * immediately. 711 */ 712 @Deprecated 713 public abstract Camera.Parameters getParameters(); 714 715 /** 716 * Gets the current camera settings synchronously. 717 * <p>This method is synchronous since the caller has to wait for the 718 * camera to return the parameters. If the parameters are already 719 * cached, it returns immediately.</p> 720 */ 721 public abstract CameraSettings getSettings(); 722 723 /** 724 * Default implementation of {@link #applySettings(CameraSettings)} 725 * that is only missing the set of states it needs to wait for 726 * before applying the settings. 727 * 728 * @param settings The settings to use on the device. 729 * @param statesToAwait Bitwise OR of the required camera states. 730 * @return Whether the settings can be applied. 731 */ 732 protected boolean applySettingsHelper(CameraSettings settings, 733 final int statesToAwait) { 734 if (settings == null) { 735 Log.v(TAG, "null parameters in applySettings()"); 736 return false; 737 } 738 if (!getCapabilities().supports(settings)) { 739 return false; 740 } 741 742 final CameraSettings copyOfSettings = settings.copy(); 743 getDispatchThread().runJob(new Runnable() { 744 @Override 745 public void run() { 746 getCameraState().waitForStates(statesToAwait); 747 getCameraHandler().obtainMessage(CameraActions.APPLY_SETTINGS, copyOfSettings) 748 .sendToTarget(); 749 }}); 750 return true; 751 } 752 753 /** 754 * Applies the settings to the camera device. 755 * 756 * @param settings The settings to use on the device. 757 * @return Whether the settings can be applied. 758 */ 759 public abstract boolean applySettings(CameraSettings settings); 760 761 /** 762 * Forces {@code CameraProxy} to update the cached version of the camera 763 * settings regardless of the dirty bit. 764 */ 765 public void refreshSettings() { 766 getDispatchThread().runJob(new Runnable() { 767 @Override 768 public void run() { 769 getCameraHandler().sendEmptyMessage(CameraActions.REFRESH_PARAMETERS); 770 }}); 771 } 772 773 /** 774 * Enables/Disables the camera shutter sound. 775 * 776 * @param enable {@code true} to enable the shutter sound, 777 * {@code false} to disable it. 778 */ 779 public void enableShutterSound(final boolean enable) { 780 getDispatchThread().runJob(new Runnable() { 781 @Override 782 public void run() { 783 getCameraHandler() 784 .obtainMessage(CameraActions.ENABLE_SHUTTER_SOUND, (enable ? 1 : 0), 0) 785 .sendToTarget(); 786 }}); 787 } 788 789 /** 790 * Dumps the current settings of the camera device. 791 * 792 * <p>The content varies based on the underlying camera API settings 793 * implementation.</p> 794 * 795 * @return The content of the device settings represented by a string. 796 */ 797 public abstract String dumpDeviceSettings(); 798 799 /** 800 * @return The handler to which camera tasks should be posted. 801 */ 802 public abstract Handler getCameraHandler(); 803 804 /** 805 * @return The thread used on which client callbacks are served. 806 */ 807 public abstract DispatchThread getDispatchThread(); 808 809 /** 810 * @return The state machine tracking the camera API's current mode. 811 */ 812 public abstract CameraStateHolder getCameraState(); 813 } 814 815 public static class WaitDoneBundle { 816 public final Runnable mUnlockRunnable; 817 public final Object mWaitLock; 818 819 WaitDoneBundle() { 820 mWaitLock = new Object(); 821 mUnlockRunnable = new Runnable() { 822 @Override 823 public void run() { 824 synchronized (mWaitLock) { 825 mWaitLock.notifyAll(); 826 } 827 }}; 828 } 829 } 830} 831