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 17 package android.hardware.cts; 18 19 import android.graphics.BitmapFactory; 20 import android.graphics.ImageFormat; 21 import android.graphics.Rect; 22 import android.hardware.Camera; 23 import android.hardware.Camera.Area; 24 import android.hardware.Camera.CameraInfo; 25 import android.hardware.Camera.ErrorCallback; 26 import android.hardware.Camera.Face; 27 import android.hardware.Camera.FaceDetectionListener; 28 import android.hardware.Camera.Parameters; 29 import android.hardware.Camera.PictureCallback; 30 import android.hardware.Camera.ShutterCallback; 31 import android.hardware.Camera.Size; 32 import android.media.CamcorderProfile; 33 import android.media.ExifInterface; 34 import android.media.MediaRecorder; 35 import android.os.ConditionVariable; 36 import android.os.Environment; 37 import android.os.Looper; 38 import android.test.ActivityInstrumentationTestCase2; 39 import android.test.MoreAsserts; 40 import android.test.UiThreadTest; 41 import android.test.suitebuilder.annotation.LargeTest; 42 import android.util.Log; 43 import android.view.SurfaceHolder; 44 45 import dalvik.annotation.TestLevel; 46 import dalvik.annotation.TestTargetClass; 47 import dalvik.annotation.TestTargetNew; 48 import dalvik.annotation.TestTargets; 49 50 import java.io.File; 51 import java.io.FileOutputStream; 52 import java.io.IOException; 53 import java.util.ArrayList; 54 import java.util.Arrays; 55 import java.util.Iterator; 56 import java.util.List; 57 58 /** 59 * This test case must run with hardware. It can't be tested in emulator 60 */ 61 @LargeTest 62 @TestTargetClass(Camera.class) 63 public class CameraTest extends ActivityInstrumentationTestCase2<CameraStubActivity> { 64 private String TAG = "CameraTest"; 65 private static final String PACKAGE = "com.android.cts.stub"; 66 private static final boolean LOGV = false; 67 private final String JPEG_PATH = Environment.getExternalStorageDirectory().getPath() + 68 "/test.jpg"; 69 private byte[] mJpegData; 70 71 private static final int PREVIEW_CALLBACK_NOT_RECEIVED = 0; 72 private static final int PREVIEW_CALLBACK_RECEIVED = 1; 73 private static final int PREVIEW_CALLBACK_DATA_NULL = 2; 74 private static final int PREVIEW_CALLBACK_INVALID_FRAME_SIZE = 3; 75 private int mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED; 76 77 private boolean mShutterCallbackResult = false; 78 private boolean mRawPictureCallbackResult = false; 79 private boolean mJpegPictureCallbackResult = false; 80 private static final int NO_ERROR = -1; 81 private int mCameraErrorCode = NO_ERROR; 82 private boolean mAutoFocusSucceeded = false; 83 84 private static final int WAIT_FOR_COMMAND_TO_COMPLETE = 1500; // Milliseconds. 85 private static final int WAIT_FOR_FOCUS_TO_COMPLETE = 3000; 86 private static final int WAIT_FOR_SNAPSHOT_TO_COMPLETE = 5000; 87 88 private static final int FOCUS_AREA = 0; 89 private static final int METERING_AREA = 1; 90 91 private static final int AUTOEXPOSURE_LOCK = 0; 92 private static final int AUTOWHITEBALANCE_LOCK = 1; 93 94 private PreviewCallback mPreviewCallback = new PreviewCallback(); 95 private TestShutterCallback mShutterCallback = new TestShutterCallback(); 96 private RawPictureCallback mRawPictureCallback = new RawPictureCallback(); 97 private JpegPictureCallback mJpegPictureCallback = new JpegPictureCallback(); 98 private TestErrorCallback mErrorCallback = new TestErrorCallback(); 99 private AutoFocusCallback mAutoFocusCallback = new AutoFocusCallback(); 100 101 private Looper mLooper = null; 102 private final ConditionVariable mPreviewDone = new ConditionVariable(); 103 private final ConditionVariable mFocusDone = new ConditionVariable(); 104 private final ConditionVariable mSnapshotDone = new ConditionVariable(); 105 106 Camera mCamera; 107 108 public CameraTest() { 109 super(PACKAGE, CameraStubActivity.class); 110 if (LOGV) Log.v(TAG, "Camera Constructor"); 111 } 112 113 @Override 114 protected void setUp() throws Exception { 115 super.setUp(); 116 // to start CameraStubActivity. 117 getActivity(); 118 } 119 120 @Override 121 protected void tearDown() throws Exception { 122 if (mCamera != null) { 123 mCamera.release(); 124 mCamera = null; 125 } 126 super.tearDown(); 127 } 128 129 /* 130 * Initializes the message looper so that the Camera object can 131 * receive the callback messages. 132 */ 133 private void initializeMessageLooper(final int cameraId) throws IOException { 134 final ConditionVariable startDone = new ConditionVariable(); 135 new Thread() { 136 @Override 137 public void run() { 138 Log.v(TAG, "start loopRun"); 139 // Set up a looper to be used by camera. 140 Looper.prepare(); 141 // Save the looper so that we can terminate this thread 142 // after we are done with it. 143 mLooper = Looper.myLooper(); 144 try { 145 mCamera = Camera.open(cameraId); 146 mCamera.setErrorCallback(mErrorCallback); 147 } catch (RuntimeException e) { 148 Log.e(TAG, "Fail to open camera." + e); 149 } 150 Log.v(TAG, "camera is opened"); 151 startDone.open(); 152 Looper.loop(); // Blocks forever until Looper.quit() is called. 153 if (LOGV) Log.v(TAG, "initializeMessageLooper: quit."); 154 } 155 }.start(); 156 157 Log.v(TAG, "start waiting for looper"); 158 if (!startDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) { 159 Log.v(TAG, "initializeMessageLooper: start timeout"); 160 fail("initializeMessageLooper: start timeout"); 161 } 162 assertNotNull("Fail to open camera.", mCamera); 163 mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder()); 164 } 165 166 /* 167 * Terminates the message looper thread. 168 */ 169 private void terminateMessageLooper() throws Exception { 170 mLooper.quit(); 171 // Looper.quit() is asynchronous. The looper may still has some 172 // preview callbacks in the queue after quit is called. The preview 173 // callback still uses the camera object (setHasPreviewCallback). 174 // After camera is released, RuntimeException will be thrown from 175 // the method. So we need to join the looper thread here. 176 mLooper.getThread().join(); 177 mCamera.release(); 178 mCamera = null; 179 assertEquals("Got camera error callback.", NO_ERROR, mCameraErrorCode); 180 } 181 182 //Implement the previewCallback 183 private final class PreviewCallback 184 implements android.hardware.Camera.PreviewCallback { 185 public void onPreviewFrame(byte [] data, Camera camera) { 186 if (data == null) { 187 mPreviewCallbackResult = PREVIEW_CALLBACK_DATA_NULL; 188 mPreviewDone.open(); 189 return; 190 } 191 Size size = camera.getParameters().getPreviewSize(); 192 int format = camera.getParameters().getPreviewFormat(); 193 int bitsPerPixel = ImageFormat.getBitsPerPixel(format); 194 if (size.width * size.height * bitsPerPixel / 8 != data.length) { 195 Log.e(TAG, "Invalid frame size " + data.length + ". width=" + size.width 196 + ". height=" + size.height + ". bitsPerPixel=" + bitsPerPixel); 197 mPreviewCallbackResult = PREVIEW_CALLBACK_INVALID_FRAME_SIZE; 198 mPreviewDone.open(); 199 return; 200 } 201 mPreviewCallbackResult = PREVIEW_CALLBACK_RECEIVED; 202 mCamera.stopPreview(); 203 if (LOGV) Log.v(TAG, "notify the preview callback"); 204 mPreviewDone.open(); 205 if (LOGV) Log.v(TAG, "Preview callback stop"); 206 } 207 } 208 209 //Implement the shutterCallback 210 private final class TestShutterCallback implements ShutterCallback { 211 public void onShutter() { 212 mShutterCallbackResult = true; 213 if (LOGV) Log.v(TAG, "onShutter called"); 214 } 215 } 216 217 //Implement the RawPictureCallback 218 private final class RawPictureCallback implements PictureCallback { 219 public void onPictureTaken(byte [] rawData, Camera camera) { 220 mRawPictureCallbackResult = true; 221 if (LOGV) Log.v(TAG, "RawPictureCallback callback"); 222 } 223 } 224 225 // Implement the JpegPictureCallback 226 private final class JpegPictureCallback implements PictureCallback { 227 public void onPictureTaken(byte[] rawData, Camera camera) { 228 try { 229 mJpegData = rawData; 230 if (rawData != null) { 231 // try to store the picture on the SD card 232 File rawoutput = new File(JPEG_PATH); 233 FileOutputStream outStream = new FileOutputStream(rawoutput); 234 outStream.write(rawData); 235 outStream.close(); 236 mJpegPictureCallbackResult = true; 237 238 if (LOGV) { 239 Log.v(TAG, "JpegPictureCallback rawDataLength = " + rawData.length); 240 } 241 } else { 242 mJpegPictureCallbackResult = false; 243 } 244 mSnapshotDone.open(); 245 if (LOGV) Log.v(TAG, "Jpeg Picture callback"); 246 } catch (IOException e) { 247 // no need to fail here; callback worked fine 248 Log.w(TAG, "Error writing picture to sd card."); 249 } 250 } 251 } 252 253 // Implement the ErrorCallback 254 private final class TestErrorCallback implements ErrorCallback { 255 public void onError(int error, Camera camera) { 256 Log.e(TAG, "Got camera error=" + error); 257 mCameraErrorCode = error; 258 } 259 } 260 261 private final class AutoFocusCallback 262 implements android.hardware.Camera.AutoFocusCallback { 263 public void onAutoFocus(boolean success, Camera camera) { 264 mAutoFocusSucceeded = success; 265 Log.v(TAG, "AutoFocusCallback success=" + success); 266 mFocusDone.open(); 267 } 268 } 269 270 private void waitForPreviewDone() { 271 if (LOGV) Log.v(TAG, "Wait for preview callback"); 272 if (!mPreviewDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) { 273 // timeout could be expected or unexpected. The caller will decide. 274 Log.v(TAG, "waitForPreviewDone: timeout"); 275 } 276 mPreviewDone.close(); 277 } 278 279 private boolean waitForFocusDone() { 280 boolean result = mFocusDone.block(WAIT_FOR_FOCUS_TO_COMPLETE); 281 if (!result) { 282 // timeout could be expected or unexpected. The caller will decide. 283 Log.v(TAG, "waitForFocusDone: timeout"); 284 } 285 mFocusDone.close(); 286 return result; 287 } 288 289 private void waitForSnapshotDone() { 290 if (!mSnapshotDone.block(WAIT_FOR_SNAPSHOT_TO_COMPLETE)) { 291 // timeout could be expected or unexpected. The caller will decide. 292 Log.v(TAG, "waitForSnapshotDone: timeout"); 293 } 294 mSnapshotDone.close(); 295 } 296 297 private void checkPreviewCallback() throws Exception { 298 if (LOGV) Log.v(TAG, "check preview callback"); 299 mCamera.startPreview(); 300 waitForPreviewDone(); 301 mCamera.setPreviewCallback(null); 302 } 303 304 /* 305 * Test case 1: Take a picture and verify all the callback 306 * functions are called properly. 307 */ 308 @TestTargets({ 309 @TestTargetNew( 310 level = TestLevel.COMPLETE, 311 method = "startPreview", 312 args = {} 313 ), 314 @TestTargetNew( 315 level = TestLevel.COMPLETE, 316 method = "setPreviewDisplay", 317 args = {android.view.SurfaceHolder.class} 318 ), 319 @TestTargetNew( 320 level = TestLevel.COMPLETE, 321 method = "open", 322 args = {} 323 ), 324 @TestTargetNew( 325 level = TestLevel.COMPLETE, 326 method = "release", 327 args = {} 328 ), 329 @TestTargetNew( 330 level = TestLevel.COMPLETE, 331 method = "takePicture", 332 args = {android.hardware.Camera.ShutterCallback.class, 333 android.hardware.Camera.PictureCallback.class, 334 android.hardware.Camera.PictureCallback.class} 335 ), 336 @TestTargetNew( 337 level = TestLevel.COMPLETE, 338 method = "autoFocus", 339 args = {android.hardware.Camera.AutoFocusCallback.class} 340 ) 341 }) 342 @UiThreadTest 343 public void testTakePicture() throws Exception { 344 int nCameras = Camera.getNumberOfCameras(); 345 for (int id = 0; id < nCameras; id++) { 346 Log.v(TAG, "Camera id=" + id); 347 initializeMessageLooper(id); 348 mCamera.startPreview(); 349 testTakePictureByCamera(); 350 terminateMessageLooper(); 351 } 352 } 353 354 private void testTakePictureByCamera() throws Exception { 355 Size pictureSize = mCamera.getParameters().getPictureSize(); 356 mCamera.autoFocus(mAutoFocusCallback); 357 assertTrue(waitForFocusDone()); 358 mJpegData = null; 359 mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback); 360 waitForSnapshotDone(); 361 assertTrue("Shutter callback not received", mShutterCallbackResult); 362 assertTrue("Raw picture callback not received", mRawPictureCallbackResult); 363 assertTrue("Jpeg picture callback not recieved", mJpegPictureCallbackResult); 364 assertNotNull(mJpegData); 365 BitmapFactory.Options bmpOptions = new BitmapFactory.Options(); 366 bmpOptions.inJustDecodeBounds = true; 367 BitmapFactory.decodeByteArray(mJpegData, 0, mJpegData.length, bmpOptions); 368 assertEquals(pictureSize.width, bmpOptions.outWidth); 369 assertEquals(pictureSize.height, bmpOptions.outHeight); 370 } 371 372 @TestTargets({ 373 @TestTargetNew( 374 level = TestLevel.COMPLETE, 375 method = "stopPreview", 376 args = {} 377 ), 378 @TestTargetNew( 379 level = TestLevel.COMPLETE, 380 method = "setPreviewCallback", 381 args = {android.hardware.Camera.PreviewCallback.class} 382 ), 383 @TestTargetNew( 384 level = TestLevel.COMPLETE, 385 method = "open", 386 args = {} 387 ), 388 @TestTargetNew( 389 level = TestLevel.COMPLETE, 390 method = "release", 391 args = {} 392 ), 393 @TestTargetNew( 394 level = TestLevel.COMPLETE, 395 method = "startPreview", 396 args = {} 397 ), 398 @TestTargetNew( 399 level = TestLevel.COMPLETE, 400 method = "setPreviewDisplay", 401 args = {android.view.SurfaceHolder.class} 402 ), 403 @TestTargetNew( 404 level = TestLevel.COMPLETE, 405 method = "setErrorCallback", 406 args = {android.hardware.Camera.ErrorCallback.class} 407 ) 408 }) 409 @UiThreadTest 410 public void testPreviewCallback() throws Exception { 411 int nCameras = Camera.getNumberOfCameras(); 412 for (int id = 0; id < nCameras; id++) { 413 Log.v(TAG, "Camera id=" + id); 414 testPreviewCallbackByCamera(id); 415 } 416 } 417 418 private void testPreviewCallbackByCamera(int cameraId) throws Exception { 419 initializeMessageLooper(cameraId); 420 mCamera.setPreviewCallback(mPreviewCallback); 421 checkPreviewCallback(); 422 terminateMessageLooper(); 423 assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult); 424 425 mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED; 426 initializeMessageLooper(cameraId); 427 checkPreviewCallback(); 428 terminateMessageLooper(); 429 assertEquals(PREVIEW_CALLBACK_NOT_RECEIVED, mPreviewCallbackResult); 430 431 // Test all preview sizes. 432 initializeMessageLooper(cameraId); 433 Parameters parameters = mCamera.getParameters(); 434 for (Size size: parameters.getSupportedPreviewSizes()) { 435 mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED; 436 mCamera.setPreviewCallback(mPreviewCallback); 437 parameters.setPreviewSize(size.width, size.height); 438 mCamera.setParameters(parameters); 439 assertEquals(size, mCamera.getParameters().getPreviewSize()); 440 checkPreviewCallback(); 441 assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult); 442 try { 443 // Wait for a while to throw away the remaining preview frames. 444 Thread.sleep(1000); 445 } catch(Exception e) { 446 // ignore 447 } 448 mPreviewDone.close(); 449 } 450 terminateMessageLooper(); 451 } 452 453 @TestTargetNew( 454 level = TestLevel.COMPLETE, 455 method = "setOneShotPreviewCallback", 456 args = {PreviewCallback.class} 457 ) 458 @UiThreadTest 459 public void testSetOneShotPreviewCallback() throws Exception { 460 int nCameras = Camera.getNumberOfCameras(); 461 for (int id = 0; id < nCameras; id++) { 462 Log.v(TAG, "Camera id=" + id); 463 testSetOneShotPreviewCallbackByCamera(id); 464 } 465 } 466 467 private void testSetOneShotPreviewCallbackByCamera(int cameraId) throws Exception { 468 initializeMessageLooper(cameraId); 469 mCamera.setOneShotPreviewCallback(mPreviewCallback); 470 checkPreviewCallback(); 471 terminateMessageLooper(); 472 assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult); 473 474 mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED; 475 initializeMessageLooper(cameraId); 476 checkPreviewCallback(); 477 terminateMessageLooper(); 478 assertEquals(PREVIEW_CALLBACK_NOT_RECEIVED, mPreviewCallbackResult); 479 } 480 481 @TestTargetNew( 482 level = TestLevel.COMPLETE, 483 method = "setPreviewDisplay", 484 args = {SurfaceHolder.class} 485 ) 486 @UiThreadTest 487 public void testSetPreviewDisplay() throws Exception { 488 int nCameras = Camera.getNumberOfCameras(); 489 for (int id = 0; id < nCameras; id++) { 490 Log.v(TAG, "Camera id=" + id); 491 testSetPreviewDisplayByCamera(id); 492 } 493 } 494 495 private void testSetPreviewDisplayByCamera(int cameraId) throws Exception { 496 SurfaceHolder holder = getActivity().getSurfaceView().getHolder(); 497 initializeMessageLooper(cameraId); 498 499 // Check the order: startPreview->setPreviewDisplay. 500 mCamera.setOneShotPreviewCallback(mPreviewCallback); 501 mCamera.startPreview(); 502 mCamera.setPreviewDisplay(holder); 503 waitForPreviewDone(); 504 terminateMessageLooper(); 505 assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult); 506 507 // Check the order: setPreviewDisplay->startPreview. 508 initializeMessageLooper(cameraId); 509 mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED; 510 mCamera.setOneShotPreviewCallback(mPreviewCallback); 511 mCamera.setPreviewDisplay(holder); 512 mCamera.startPreview(); 513 waitForPreviewDone(); 514 mCamera.stopPreview(); 515 assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult); 516 517 // Check the order: setting preview display to null->startPreview-> 518 // setPreviewDisplay. 519 mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED; 520 mCamera.setOneShotPreviewCallback(mPreviewCallback); 521 mCamera.setPreviewDisplay(null); 522 mCamera.startPreview(); 523 mCamera.setPreviewDisplay(holder); 524 waitForPreviewDone(); 525 terminateMessageLooper(); 526 assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult); 527 } 528 529 @TestTargetNew( 530 level = TestLevel.COMPLETE, 531 method = "setDisplayOrientation", 532 args = {int.class} 533 ) 534 @UiThreadTest 535 public void testDisplayOrientation() throws Exception { 536 int nCameras = Camera.getNumberOfCameras(); 537 for (int id = 0; id < nCameras; id++) { 538 Log.v(TAG, "Camera id=" + id); 539 testDisplayOrientationByCamera(id); 540 } 541 } 542 543 private void testDisplayOrientationByCamera(int cameraId) throws Exception { 544 initializeMessageLooper(cameraId); 545 546 // Check valid arguments. 547 mCamera.setDisplayOrientation(0); 548 mCamera.setDisplayOrientation(90); 549 mCamera.setDisplayOrientation(180); 550 mCamera.setDisplayOrientation(270); 551 552 // Check invalid arguments. 553 try { 554 mCamera.setDisplayOrientation(45); 555 fail("Should throw exception for invalid arguments"); 556 } catch (RuntimeException ex) { 557 // expected 558 } 559 560 // Start preview. 561 mCamera.startPreview(); 562 563 // Check setting orientation during preview is allowed. 564 mCamera.setDisplayOrientation(90); 565 mCamera.setDisplayOrientation(180); 566 mCamera.setDisplayOrientation(270); 567 mCamera.setDisplayOrientation(00); 568 569 terminateMessageLooper(); 570 } 571 572 @TestTargets({ 573 @TestTargetNew( 574 level = TestLevel.COMPLETE, 575 method = "getParameters", 576 args = {} 577 ), 578 @TestTargetNew( 579 level = TestLevel.COMPLETE, 580 method = "setParameters", 581 args = {android.hardware.Camera.Parameters.class} 582 ) 583 }) 584 @UiThreadTest 585 public void testParameters() throws Exception { 586 int nCameras = Camera.getNumberOfCameras(); 587 for (int id = 0; id < nCameras; id++) { 588 Log.v(TAG, "Camera id=" + id); 589 testParametersByCamera(id); 590 } 591 } 592 593 private void testParametersByCamera(int cameraId) throws Exception { 594 initializeMessageLooper(cameraId); 595 // we can get parameters just by getxxx method due to the private constructor 596 Parameters pSet = mCamera.getParameters(); 597 assertParameters(pSet); 598 terminateMessageLooper(); 599 } 600 601 // Also test Camera.Parameters 602 private void assertParameters(Parameters parameters) { 603 // Parameters constants 604 final int PICTURE_FORMAT = ImageFormat.JPEG; 605 final int PREVIEW_FORMAT = ImageFormat.NV21; 606 607 // Before setting Parameters 608 final int origPictureFormat = parameters.getPictureFormat(); 609 final int origPictureWidth = parameters.getPictureSize().width; 610 final int origPictureHeight = parameters.getPictureSize().height; 611 final int origPreviewFormat = parameters.getPreviewFormat(); 612 final int origPreviewWidth = parameters.getPreviewSize().width; 613 final int origPreviewHeight = parameters.getPreviewSize().height; 614 final int origPreviewFrameRate = parameters.getPreviewFrameRate(); 615 616 assertTrue(origPictureWidth > 0); 617 assertTrue(origPictureHeight > 0); 618 assertTrue(origPreviewWidth > 0); 619 assertTrue(origPreviewHeight > 0); 620 assertTrue(origPreviewFrameRate > 0); 621 622 // The default preview format must be yuv420 (NV21). 623 assertEquals(ImageFormat.NV21, origPreviewFormat); 624 625 // The default picture format must be Jpeg. 626 assertEquals(ImageFormat.JPEG, origPictureFormat); 627 628 // If camera supports flash, the default flash mode must be off. 629 String flashMode = parameters.getFlashMode(); 630 assertTrue(flashMode == null || flashMode.equals(parameters.FLASH_MODE_OFF)); 631 String wb = parameters.getWhiteBalance(); 632 assertTrue(wb == null || wb.equals(parameters.WHITE_BALANCE_AUTO)); 633 String effect = parameters.getColorEffect(); 634 assertTrue(effect == null || effect.equals(parameters.EFFECT_NONE)); 635 636 // Some parameters must be supported. 637 List<Size> previewSizes = parameters.getSupportedPreviewSizes(); 638 List<Size> pictureSizes = parameters.getSupportedPictureSizes(); 639 List<Integer> previewFormats = parameters.getSupportedPreviewFormats(); 640 List<Integer> pictureFormats = parameters.getSupportedPictureFormats(); 641 List<Integer> frameRates = parameters.getSupportedPreviewFrameRates(); 642 List<String> focusModes = parameters.getSupportedFocusModes(); 643 String focusMode = parameters.getFocusMode(); 644 float focalLength = parameters.getFocalLength(); 645 float horizontalViewAngle = parameters.getHorizontalViewAngle(); 646 float verticalViewAngle = parameters.getVerticalViewAngle(); 647 int jpegQuality = parameters.getJpegQuality(); 648 int jpegThumnailQuality = parameters.getJpegThumbnailQuality(); 649 assertTrue(previewSizes != null && previewSizes.size() != 0); 650 assertTrue(pictureSizes != null && pictureSizes.size() != 0); 651 assertTrue(previewFormats != null && previewFormats.size() >= 2); 652 assertTrue(previewFormats.contains(ImageFormat.NV21)); 653 assertTrue(previewFormats.contains(ImageFormat.YV12)); 654 assertTrue(pictureFormats != null && pictureFormats.size() != 0); 655 assertTrue(frameRates != null && frameRates.size() != 0); 656 assertTrue(focusModes != null && focusModes.size() != 0); 657 assertNotNull(focusMode); 658 assertTrue(focalLength > 0); 659 assertTrue(horizontalViewAngle > 0 && horizontalViewAngle <= 360); 660 assertTrue(verticalViewAngle > 0 && verticalViewAngle <= 360); 661 Size previewSize = previewSizes.get(0); 662 Size pictureSize = pictureSizes.get(0); 663 assertTrue(jpegQuality >= 1 && jpegQuality <= 100); 664 assertTrue(jpegThumnailQuality >= 1 && jpegThumnailQuality <= 100); 665 666 // If a parameter is supported, both getXXX and getSupportedXXX have to 667 // be non null. 668 if (parameters.getWhiteBalance() != null) { 669 assertNotNull(parameters.getSupportedWhiteBalance()); 670 } 671 if (parameters.getSupportedWhiteBalance() != null) { 672 assertNotNull(parameters.getWhiteBalance()); 673 } 674 if (parameters.getColorEffect() != null) { 675 assertNotNull(parameters.getSupportedColorEffects()); 676 } 677 if (parameters.getSupportedColorEffects() != null) { 678 assertNotNull(parameters.getColorEffect()); 679 } 680 if (parameters.getAntibanding() != null) { 681 assertNotNull(parameters.getSupportedAntibanding()); 682 } 683 if (parameters.getSupportedAntibanding() != null) { 684 assertNotNull(parameters.getAntibanding()); 685 } 686 if (parameters.getSceneMode() != null) { 687 assertNotNull(parameters.getSupportedSceneModes()); 688 } 689 if (parameters.getSupportedSceneModes() != null) { 690 assertNotNull(parameters.getSceneMode()); 691 } 692 if (parameters.getFlashMode() != null) { 693 assertNotNull(parameters.getSupportedFlashModes()); 694 } 695 if (parameters.getSupportedFlashModes() != null) { 696 assertNotNull(parameters.getFlashMode()); 697 } 698 699 // Check if the sizes value contain invalid characters. 700 assertNoLetters(parameters.get("preview-size-values"), "preview-size-values"); 701 assertNoLetters(parameters.get("picture-size-values"), "picture-size-values"); 702 assertNoLetters(parameters.get("jpeg-thumbnail-size-values"), 703 "jpeg-thumbnail-size-values"); 704 705 // Set the parameters. 706 parameters.setPictureFormat(PICTURE_FORMAT); 707 assertEquals(PICTURE_FORMAT, parameters.getPictureFormat()); 708 parameters.setPictureSize(pictureSize.width, pictureSize.height); 709 assertEquals(pictureSize.width, parameters.getPictureSize().width); 710 assertEquals(pictureSize.height, parameters.getPictureSize().height); 711 parameters.setPreviewFormat(PREVIEW_FORMAT); 712 assertEquals(PREVIEW_FORMAT, parameters.getPreviewFormat()); 713 parameters.setPreviewFrameRate(frameRates.get(0)); 714 assertEquals(frameRates.get(0).intValue(), parameters.getPreviewFrameRate()); 715 parameters.setPreviewSize(previewSize.width, previewSize.height); 716 assertEquals(previewSize.width, parameters.getPreviewSize().width); 717 assertEquals(previewSize.height, parameters.getPreviewSize().height); 718 719 mCamera.setParameters(parameters); 720 Parameters paramActual = mCamera.getParameters(); 721 722 assertTrue(isValidPixelFormat(paramActual.getPictureFormat())); 723 assertEquals(pictureSize.width, paramActual.getPictureSize().width); 724 assertEquals(pictureSize.height, paramActual.getPictureSize().height); 725 assertTrue(isValidPixelFormat(paramActual.getPreviewFormat())); 726 assertEquals(previewSize.width, paramActual.getPreviewSize().width); 727 assertEquals(previewSize.height, paramActual.getPreviewSize().height); 728 assertTrue(paramActual.getPreviewFrameRate() > 0); 729 730 checkExposureCompensation(parameters); 731 checkPreferredPreviewSizeForVideo(parameters); 732 } 733 734 private void checkPreferredPreviewSizeForVideo(Parameters parameters) { 735 List<Size> videoSizes = parameters.getSupportedVideoSizes(); 736 Size preferredPreviewSize = parameters.getPreferredPreviewSizeForVideo(); 737 738 // If getSupportedVideoSizes() returns null, 739 // getPreferredPreviewSizeForVideo() will return null; 740 // otherwise, if getSupportedVideoSizes() does not return null, 741 // getPreferredPreviewSizeForVideo() will not return null. 742 if (videoSizes == null) { 743 assertNull(preferredPreviewSize); 744 } else { 745 assertNotNull(preferredPreviewSize); 746 } 747 748 // If getPreferredPreviewSizeForVideo() returns null, 749 // getSupportedVideoSizes() will return null; 750 // otherwise, if getPreferredPreviewSizeForVideo() does not return null, 751 // getSupportedVideoSizes() will not return null. 752 if (preferredPreviewSize == null) { 753 assertNull(videoSizes); 754 } else { 755 assertNotNull(videoSizes); 756 } 757 758 if (videoSizes != null) { // implies: preferredPreviewSize != null 759 // If getSupportedVideoSizes() does not return null, 760 // the returned list will contain at least one size. 761 assertTrue(videoSizes.size() > 0); 762 763 // In addition, getPreferredPreviewSizeForVideo() returns a size 764 // that is among the supported preview sizes. 765 List<Size> previewSizes = parameters.getSupportedPreviewSizes(); 766 assertNotNull(previewSizes); 767 assertTrue(previewSizes.size() > 0); 768 assertTrue(previewSizes.contains(preferredPreviewSize)); 769 } 770 } 771 772 private void checkExposureCompensation(Parameters parameters) { 773 assertEquals(0, parameters.getExposureCompensation()); 774 int max = parameters.getMaxExposureCompensation(); 775 int min = parameters.getMinExposureCompensation(); 776 float step = parameters.getExposureCompensationStep(); 777 if (max == 0 && min == 0) { 778 assertEquals(0f, step, 0.000001f); 779 return; 780 } 781 assertTrue(step > 0); 782 assertTrue(max >= 0); 783 assertTrue(min <= 0); 784 } 785 786 private boolean isValidPixelFormat(int format) { 787 return (format == ImageFormat.RGB_565) || (format == ImageFormat.NV21) 788 || (format == ImageFormat.JPEG) || (format == ImageFormat.YUY2); 789 } 790 791 @TestTargets({ 792 @TestTargetNew( 793 level = TestLevel.COMPLETE, 794 method = "setJpegThumbnailSize", 795 args = {android.hardware.Camera.Size.class} 796 ), 797 @TestTargetNew( 798 level = TestLevel.COMPLETE, 799 method = "getJpegThumbnailSize", 800 args = {} 801 ), 802 @TestTargetNew( 803 level = TestLevel.COMPLETE, 804 method = "getJpegSupportedThumbnailSizes", 805 args = {} 806 ) 807 }) 808 @UiThreadTest 809 public void testJpegThumbnailSize() throws Exception { 810 int nCameras = Camera.getNumberOfCameras(); 811 for (int id = 0; id < nCameras; id++) { 812 Log.v(TAG, "Camera id=" + id); 813 initializeMessageLooper(id); 814 testJpegThumbnailSizeByCamera(false); 815 terminateMessageLooper(); 816 } 817 } 818 819 private void testJpegThumbnailSizeByCamera(boolean recording) throws Exception { 820 // Thumbnail size parameters should have valid values. 821 Parameters p = mCamera.getParameters(); 822 Size size = p.getJpegThumbnailSize(); 823 assertTrue(size.width > 0 && size.height > 0); 824 List<Size> sizes = p.getSupportedJpegThumbnailSizes(); 825 assertTrue(sizes.size() >= 2); 826 assertTrue(sizes.contains(size)); 827 assertTrue(sizes.contains(mCamera.new Size(0, 0))); 828 829 // Test if the thumbnail size matches the setting. 830 if (!recording) mCamera.startPreview(); 831 mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback); 832 waitForSnapshotDone(); 833 assertTrue(mJpegPictureCallbackResult); 834 ExifInterface exif = new ExifInterface(JPEG_PATH); 835 assertTrue(exif.hasThumbnail()); 836 byte[] thumb = exif.getThumbnail(); 837 BitmapFactory.Options bmpOptions = new BitmapFactory.Options(); 838 bmpOptions.inJustDecodeBounds = true; 839 BitmapFactory.decodeByteArray(thumb, 0, thumb.length, bmpOptions); 840 assertEquals(size.width, bmpOptions.outWidth); 841 assertEquals(size.height, bmpOptions.outHeight); 842 843 // Test no thumbnail case. 844 p.setJpegThumbnailSize(0, 0); 845 mCamera.setParameters(p); 846 Size actual = mCamera.getParameters().getJpegThumbnailSize(); 847 assertEquals(0, actual.width); 848 assertEquals(0, actual.height); 849 if (!recording) mCamera.startPreview(); 850 mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback); 851 waitForSnapshotDone(); 852 assertTrue(mJpegPictureCallbackResult); 853 exif = new ExifInterface(JPEG_PATH); 854 assertFalse(exif.hasThumbnail()); 855 } 856 857 @UiThreadTest 858 public void testJpegExif() throws Exception { 859 int nCameras = Camera.getNumberOfCameras(); 860 for (int id = 0; id < nCameras; id++) { 861 Log.v(TAG, "Camera id=" + id); 862 initializeMessageLooper(id); 863 testJpegExifByCamera(false); 864 terminateMessageLooper(); 865 } 866 } 867 868 private void testJpegExifByCamera(boolean recording) throws Exception { 869 Camera.Parameters parameters = mCamera.getParameters(); 870 if (!recording) mCamera.startPreview(); 871 double focalLength = parameters.getFocalLength(); 872 mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback); 873 waitForSnapshotDone(); 874 ExifInterface exif = new ExifInterface(JPEG_PATH); 875 assertNotNull(exif.getAttribute(ExifInterface.TAG_MAKE)); 876 assertNotNull(exif.getAttribute(ExifInterface.TAG_MODEL)); 877 assertNotNull(exif.getAttribute(ExifInterface.TAG_DATETIME)); 878 assertTrue(exif.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, 0) != 0); 879 assertTrue(exif.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, 0) != 0); 880 checkGpsDataNull(exif); 881 double exifFocalLength = exif.getAttributeDouble(ExifInterface.TAG_FOCAL_LENGTH, -1); 882 assertEquals(focalLength, exifFocalLength, 0.001); 883 884 // Test gps exif tags. 885 testGpsExifValues(parameters, 37.736071, -122.441983, 21, 1199145600, 886 "GPS NETWORK HYBRID ARE ALL FINE."); 887 testGpsExifValues(parameters, 0.736071, 0.441983, 1, 1199145601, "GPS"); 888 testGpsExifValues(parameters, -89.736071, -179.441983, 100000, 1199145602, "NETWORK"); 889 890 // Test gps tags do not exist after calling removeGpsData. 891 if (!recording) mCamera.startPreview(); 892 parameters.removeGpsData(); 893 mCamera.setParameters(parameters); 894 mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback); 895 waitForSnapshotDone(); 896 exif = new ExifInterface(JPEG_PATH); 897 checkGpsDataNull(exif); 898 } 899 900 private void testGpsExifValues(Parameters parameters, double latitude, 901 double longitude, double altitude, long timestamp, String method) 902 throws IOException { 903 mCamera.startPreview(); 904 parameters.setGpsLatitude(latitude); 905 parameters.setGpsLongitude(longitude); 906 parameters.setGpsAltitude(altitude); 907 parameters.setGpsTimestamp(timestamp); 908 parameters.setGpsProcessingMethod(method); 909 mCamera.setParameters(parameters); 910 mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback); 911 waitForSnapshotDone(); 912 ExifInterface exif = new ExifInterface(JPEG_PATH); 913 assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE)); 914 assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE)); 915 assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF)); 916 assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF)); 917 assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP)); 918 assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_DATESTAMP)); 919 assertEquals(method, exif.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD)); 920 float[] latLong = new float[2]; 921 assertTrue(exif.getLatLong(latLong)); 922 assertEquals((float)latitude, latLong[0], 0.0001f); 923 assertEquals((float)longitude, latLong[1], 0.0001f); 924 assertEquals(altitude, exif.getAltitude(-1), 1); 925 assertEquals(timestamp, exif.getGpsDateTime() / 1000); 926 } 927 928 private void checkGpsDataNull(ExifInterface exif) { 929 assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE)); 930 assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE)); 931 assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF)); 932 assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF)); 933 assertNull(exif.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP)); 934 assertNull(exif.getAttribute(ExifInterface.TAG_GPS_DATESTAMP)); 935 assertNull(exif.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD)); 936 } 937 938 @TestTargets({ 939 @TestTargetNew( 940 level = TestLevel.COMPLETE, 941 method = "lock", 942 args = {} 943 ), 944 @TestTargetNew( 945 level = TestLevel.COMPLETE, 946 method = "unlock", 947 args = {} 948 ) 949 }) 950 @UiThreadTest 951 public void testLockUnlock() throws Exception { 952 int nCameras = Camera.getNumberOfCameras(); 953 for (int id = 0; id < nCameras; id++) { 954 Log.v(TAG, "Camera id=" + id); 955 testLockUnlockByCamera(id); 956 } 957 } 958 959 private void testLockUnlockByCamera(int cameraId) throws Exception { 960 initializeMessageLooper(cameraId); 961 Camera.Parameters parameters = mCamera.getParameters(); 962 SurfaceHolder surfaceHolder; 963 surfaceHolder = getActivity().getSurfaceView().getHolder(); 964 CamcorderProfile profile = CamcorderProfile.get(cameraId, 965 CamcorderProfile.QUALITY_LOW); 966 967 // Set the preview size. 968 setPreviewSizeByProfile(parameters, profile); 969 970 mCamera.setParameters(parameters); 971 mCamera.setPreviewDisplay(surfaceHolder); 972 mCamera.startPreview(); 973 mCamera.lock(); // Locking again from the same process has no effect. 974 try { 975 recordVideo(profile, surfaceHolder); 976 fail("Recording should not succeed because camera is locked."); 977 } catch (Exception e) { 978 // expected 979 } 980 981 mCamera.unlock(); // Unlock the camera so media recorder can use it. 982 try { 983 mCamera.setParameters(parameters); 984 fail("setParameters should not succeed because camera is unlocked."); 985 } catch (RuntimeException e) { 986 // expected 987 } 988 989 recordVideo(profile, surfaceHolder); // should not throw exception 990 // Media recorder already releases the camera so the test application 991 // can lock and use the camera now. 992 mCamera.lock(); // should not fail 993 mCamera.setParameters(parameters); // should not fail 994 terminateMessageLooper(); 995 } 996 997 private void setPreviewSizeByProfile(Parameters parameters, CamcorderProfile profile) { 998 if (parameters.getSupportedVideoSizes() == null) { 999 parameters.setPreviewSize(profile.videoFrameWidth, 1000 profile.videoFrameHeight); 1001 } else { // Driver supports separates outputs for preview and video. 1002 List<Size> sizes = parameters.getSupportedPreviewSizes(); 1003 Size preferred = parameters.getPreferredPreviewSizeForVideo(); 1004 int product = preferred.width * preferred.height; 1005 for (Size size: sizes) { 1006 if (size.width * size.height <= product) { 1007 parameters.setPreviewSize(size.width, size.height); 1008 break; 1009 } 1010 } 1011 } 1012 } 1013 1014 private void recordVideo(CamcorderProfile profile, 1015 SurfaceHolder holder) throws Exception { 1016 MediaRecorder recorder = new MediaRecorder(); 1017 try { 1018 // Pass the camera from the test application to media recorder. 1019 recorder.setCamera(mCamera); 1020 recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 1021 recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 1022 recorder.setProfile(profile); 1023 recorder.setOutputFile("/dev/null"); 1024 recorder.setPreviewDisplay(holder.getSurface()); 1025 recorder.prepare(); 1026 recorder.start(); 1027 1028 // Apps can use the camera after start since API level 13. 1029 Parameters parameters = mCamera.getParameters(); 1030 if (parameters.isZoomSupported()) { 1031 if (parameters.getMaxZoom() > 0) { 1032 parameters.setZoom(1); 1033 mCamera.setParameters(parameters); 1034 parameters.setZoom(0); 1035 mCamera.setParameters(parameters); 1036 } 1037 } 1038 if (parameters.isSmoothZoomSupported()) { 1039 if (parameters.getMaxZoom() > 0) { 1040 ZoomListener zoomListener = new ZoomListener(); 1041 mCamera.setZoomChangeListener(zoomListener); 1042 mCamera.startSmoothZoom(1); 1043 assertTrue(zoomListener.mZoomDone.block(1000)); 1044 } 1045 } 1046 1047 try { 1048 mCamera.unlock(); 1049 fail("unlock should not succeed during recording."); 1050 } catch(RuntimeException e) { 1051 // expected 1052 } 1053 1054 Thread.sleep(2000); 1055 recorder.stop(); 1056 } finally { 1057 recorder.release(); 1058 } 1059 } 1060 1061 @TestTargets({ 1062 @TestTargetNew( 1063 level = TestLevel.COMPLETE, 1064 method = "addCallbackBuffer", 1065 args = {byte[].class} 1066 ), 1067 @TestTargetNew( 1068 level = TestLevel.COMPLETE, 1069 method = "setPreviewCallbackWithBuffer", 1070 args = {android.hardware.Camera.PreviewCallback.class} 1071 ) 1072 }) 1073 @UiThreadTest 1074 public void testPreviewCallbackWithBuffer() throws Exception { 1075 int nCameras = Camera.getNumberOfCameras(); 1076 for (int id = 0; id < nCameras; id++) { 1077 Log.v(TAG, "Camera id=" + id); 1078 testPreviewCallbackWithBufferByCamera(id); 1079 } 1080 } 1081 1082 private void testPreviewCallbackWithBufferByCamera(int cameraId) throws Exception { 1083 initializeMessageLooper(cameraId); 1084 SurfaceHolder surfaceHolder; 1085 surfaceHolder = getActivity().getSurfaceView().getHolder(); 1086 mCamera.setPreviewDisplay(surfaceHolder); 1087 Parameters parameters = mCamera.getParameters(); 1088 PreviewCallbackWithBuffer callback = new PreviewCallbackWithBuffer(); 1089 // Test all preview sizes. 1090 for (Size size: parameters.getSupportedPreviewSizes()) { 1091 parameters.setPreviewSize(size.width, size.height); 1092 mCamera.setParameters(parameters); 1093 assertEquals(size, mCamera.getParameters().getPreviewSize()); 1094 callback.mNumCbWithBuffer1 = 0; 1095 callback.mNumCbWithBuffer2 = 0; 1096 callback.mNumCbWithBuffer3 = 0; 1097 int format = mCamera.getParameters().getPreviewFormat(); 1098 int bitsPerPixel = ImageFormat.getBitsPerPixel(format); 1099 callback.mBuffer1 = new byte[size.width * size.height * bitsPerPixel / 8]; 1100 callback.mBuffer2 = new byte[size.width * size.height * bitsPerPixel / 8]; 1101 callback.mBuffer3 = new byte[size.width * size.height * bitsPerPixel / 8]; 1102 1103 // Test if we can get the preview callbacks with specified buffers. 1104 mCamera.addCallbackBuffer(callback.mBuffer1); 1105 mCamera.addCallbackBuffer(callback.mBuffer2); 1106 mCamera.setPreviewCallbackWithBuffer(callback); 1107 mCamera.startPreview(); 1108 waitForPreviewDone(); 1109 assertFalse(callback.mPreviewDataNull); 1110 assertFalse(callback.mInvalidData); 1111 assertEquals(1, callback.mNumCbWithBuffer1); 1112 assertEquals(1, callback.mNumCbWithBuffer2); 1113 assertEquals(0, callback.mNumCbWithBuffer3); 1114 1115 // Test if preview callback with buffer still works during preview. 1116 mCamera.addCallbackBuffer(callback.mBuffer3); 1117 waitForPreviewDone(); 1118 assertFalse(callback.mPreviewDataNull); 1119 assertFalse(callback.mInvalidData); 1120 assertEquals(1, callback.mNumCbWithBuffer1); 1121 assertEquals(1, callback.mNumCbWithBuffer2); 1122 assertEquals(1, callback.mNumCbWithBuffer3); 1123 mCamera.setPreviewCallbackWithBuffer(null); 1124 mCamera.stopPreview(); 1125 } 1126 terminateMessageLooper(); 1127 } 1128 1129 private final class PreviewCallbackWithBuffer 1130 implements android.hardware.Camera.PreviewCallback { 1131 public int mNumCbWithBuffer1, mNumCbWithBuffer2, mNumCbWithBuffer3; 1132 public byte[] mBuffer1, mBuffer2, mBuffer3; 1133 public boolean mPreviewDataNull, mInvalidData; 1134 public void onPreviewFrame(byte[] data, Camera camera) { 1135 if (data == null) { 1136 Log.e(TAG, "Preview data is null!"); 1137 mPreviewDataNull = true; 1138 mPreviewDone.open(); 1139 return; 1140 } 1141 if (data == mBuffer1) { 1142 mNumCbWithBuffer1++; 1143 } else if (data == mBuffer2) { 1144 mNumCbWithBuffer2++; 1145 } else if (data == mBuffer3) { 1146 mNumCbWithBuffer3++; 1147 } else { 1148 Log.e(TAG, "Invalid byte array."); 1149 mInvalidData = true; 1150 mPreviewDone.open(); 1151 return; 1152 } 1153 1154 if ((mNumCbWithBuffer1 == 1 && mNumCbWithBuffer2 == 1) 1155 || mNumCbWithBuffer3 == 1) { 1156 mPreviewDone.open(); 1157 } 1158 } 1159 } 1160 1161 @UiThreadTest 1162 public void testImmediateZoom() throws Exception { 1163 int nCameras = Camera.getNumberOfCameras(); 1164 for (int id = 0; id < nCameras; id++) { 1165 Log.v(TAG, "Camera id=" + id); 1166 testImmediateZoomByCamera(id); 1167 } 1168 } 1169 1170 private void testImmediateZoomByCamera(int id) throws Exception { 1171 initializeMessageLooper(id); 1172 1173 Parameters parameters = mCamera.getParameters(); 1174 if (!parameters.isZoomSupported()) { 1175 terminateMessageLooper(); 1176 return; 1177 } 1178 1179 // Test the zoom parameters. 1180 assertEquals(0, parameters.getZoom()); // default zoom should be 0. 1181 for (Size size: parameters.getSupportedPreviewSizes()) { 1182 parameters = mCamera.getParameters(); 1183 parameters.setPreviewSize(size.width, size.height); 1184 mCamera.setParameters(parameters); 1185 parameters = mCamera.getParameters(); 1186 int maxZoom = parameters.getMaxZoom(); 1187 assertTrue(maxZoom >= 0); 1188 1189 // Zoom ratios should be sorted from small to large. 1190 List<Integer> ratios = parameters.getZoomRatios(); 1191 assertEquals(maxZoom + 1, ratios.size()); 1192 assertEquals(100, ratios.get(0).intValue()); 1193 for (int i = 0; i < ratios.size() - 1; i++) { 1194 assertTrue(ratios.get(i) < ratios.get(i + 1)); 1195 } 1196 mCamera.startPreview(); 1197 waitForPreviewDone(); 1198 1199 // Test each zoom step. 1200 for (int i = 0; i <= maxZoom; i++) { 1201 parameters.setZoom(i); 1202 mCamera.setParameters(parameters); 1203 assertEquals(i, mCamera.getParameters().getZoom()); 1204 } 1205 1206 // It should throw exception if an invalid value is passed. 1207 try { 1208 parameters.setZoom(maxZoom + 1); 1209 mCamera.setParameters(parameters); 1210 fail("setZoom should throw exception."); 1211 } catch (RuntimeException e) { 1212 // expected 1213 } 1214 assertEquals(maxZoom, mCamera.getParameters().getZoom()); 1215 1216 mCamera.takePicture(mShutterCallback, mRawPictureCallback, 1217 mJpegPictureCallback); 1218 waitForSnapshotDone(); 1219 } 1220 1221 terminateMessageLooper(); 1222 } 1223 1224 @TestTargets({ 1225 @TestTargetNew( 1226 level = TestLevel.COMPLETE, 1227 method = "startSmoothZoom", 1228 args = {int.class} 1229 ), 1230 @TestTargetNew( 1231 level = TestLevel.COMPLETE, 1232 method = "stopSmoothZoom", 1233 args = {} 1234 ), 1235 @TestTargetNew( 1236 level = TestLevel.COMPLETE, 1237 method = "setZoomChangeListener", 1238 args = {android.hardware.Camera.OnZoomChangeListener.class} 1239 ) 1240 }) 1241 @UiThreadTest 1242 public void testSmoothZoom() throws Exception { 1243 int nCameras = Camera.getNumberOfCameras(); 1244 for (int id = 0; id < nCameras; id++) { 1245 Log.v(TAG, "Camera id=" + id); 1246 testSmoothZoomByCamera(id); 1247 } 1248 } 1249 1250 private void testSmoothZoomByCamera(int id) throws Exception { 1251 initializeMessageLooper(id); 1252 1253 Parameters parameters = mCamera.getParameters(); 1254 if (!parameters.isSmoothZoomSupported()) { 1255 terminateMessageLooper(); 1256 return; 1257 } 1258 assertTrue(parameters.isZoomSupported()); 1259 1260 ZoomListener zoomListener = new ZoomListener(); 1261 mCamera.setZoomChangeListener(zoomListener); 1262 mCamera.startPreview(); 1263 waitForPreviewDone(); 1264 1265 // Immediate zoom should not generate callbacks. 1266 int maxZoom = parameters.getMaxZoom(); 1267 parameters.setZoom(maxZoom); 1268 mCamera.setParameters(parameters); 1269 assertEquals(maxZoom, mCamera.getParameters().getZoom()); 1270 parameters.setZoom(0); 1271 mCamera.setParameters(parameters); 1272 assertEquals(0, mCamera.getParameters().getZoom()); 1273 assertFalse(zoomListener.mZoomDone.block(500)); 1274 1275 // Nothing will happen if zoom is not moving. 1276 mCamera.stopSmoothZoom(); 1277 1278 // It should not generate callbacks if zoom value is not changed. 1279 mCamera.startSmoothZoom(0); 1280 assertFalse(zoomListener.mZoomDone.block(500)); 1281 assertEquals(0, mCamera.getParameters().getZoom()); 1282 1283 // Test startSmoothZoom. 1284 mCamera.startSmoothZoom(maxZoom); 1285 assertEquals(true, zoomListener.mZoomDone.block(5000)); 1286 assertEquals(maxZoom, mCamera.getParameters().getZoom()); 1287 assertEquals(maxZoom, zoomListener.mValues.size()); 1288 for(int i = 0; i < maxZoom; i++) { 1289 int value = zoomListener.mValues.get(i); 1290 boolean stopped = zoomListener.mStopped.get(i); 1291 // Make sure we get all the zoom values in order. 1292 assertEquals(i + 1, value); 1293 // All "stopped" except the last should be false. 1294 assertEquals(i == maxZoom - 1, stopped); 1295 } 1296 1297 // Test startSmoothZoom. Make sure we get all the callbacks. 1298 if (maxZoom > 1) { 1299 zoomListener.mValues.clear(); 1300 zoomListener.mStopped.clear(); 1301 Log.e(TAG, "zoomListener.mStopped = " + zoomListener.mStopped); 1302 zoomListener.mZoomDone.close(); 1303 mCamera.startSmoothZoom(maxZoom / 2); 1304 assertTrue(zoomListener.mZoomDone.block(5000)); 1305 assertEquals(maxZoom / 2, mCamera.getParameters().getZoom()); 1306 assertEquals(maxZoom - (maxZoom / 2), zoomListener.mValues.size()); 1307 for(int i = 0; i < zoomListener.mValues.size(); i++) { 1308 int value = zoomListener.mValues.get(i); 1309 boolean stopped = zoomListener.mStopped.get(i); 1310 // Make sure we get all the zoom values in order. 1311 assertEquals(maxZoom - 1 - i, value); 1312 // All "stopped" except the last should be false. 1313 assertEquals(i == zoomListener.mValues.size() - 1, stopped); 1314 } 1315 } 1316 1317 // It should throw exception if an invalid value is passed. 1318 try { 1319 mCamera.startSmoothZoom(maxZoom + 1); 1320 fail("startSmoothZoom should throw exception."); 1321 } catch (IllegalArgumentException e) { 1322 // expected 1323 } 1324 1325 // Test stopSmoothZoom. 1326 zoomListener.mValues.clear(); 1327 zoomListener.mStopped.clear(); 1328 zoomListener.mZoomDone.close(); 1329 parameters.setZoom(0); 1330 mCamera.setParameters(parameters); 1331 assertEquals(0, mCamera.getParameters().getZoom()); 1332 mCamera.startSmoothZoom(maxZoom); 1333 mCamera.stopSmoothZoom(); 1334 assertTrue(zoomListener.mZoomDone.block(5000)); 1335 assertEquals(zoomListener.mValues.size(), mCamera.getParameters().getZoom()); 1336 for(int i = 0; i < zoomListener.mValues.size() - 1; i++) { 1337 int value = zoomListener.mValues.get(i); 1338 boolean stopped = zoomListener.mStopped.get(i); 1339 // Make sure we get all the callbacks in order (except the last). 1340 assertEquals(i + 1, value); 1341 // All "stopped" except the last should be false. stopSmoothZoom has been called. So the 1342 // last "stopped" can be true or false. 1343 if (i != zoomListener.mValues.size() - 1) { 1344 assertFalse(stopped); 1345 } 1346 } 1347 1348 terminateMessageLooper(); 1349 } 1350 1351 private final class ZoomListener 1352 implements android.hardware.Camera.OnZoomChangeListener { 1353 public ArrayList<Integer> mValues = new ArrayList<Integer>(); 1354 public ArrayList<Boolean> mStopped = new ArrayList<Boolean>(); 1355 public final ConditionVariable mZoomDone = new ConditionVariable(); 1356 1357 public void onZoomChange(int value, boolean stopped, Camera camera) { 1358 mValues.add(value); 1359 mStopped.add(stopped); 1360 if (stopped) { 1361 mZoomDone.open(); 1362 } 1363 } 1364 } 1365 1366 @UiThreadTest 1367 public void testFocusDistances() throws Exception { 1368 int nCameras = Camera.getNumberOfCameras(); 1369 for (int id = 0; id < nCameras; id++) { 1370 Log.v(TAG, "Camera id=" + id); 1371 testFocusDistancesByCamera(id); 1372 } 1373 } 1374 1375 private void testFocusDistancesByCamera(int cameraId) throws Exception { 1376 initializeMessageLooper(cameraId); 1377 mCamera.startPreview(); 1378 waitForPreviewDone(); 1379 Parameters parameters = mCamera.getParameters(); 1380 1381 // Test every supported focus mode. 1382 for (String focusMode: parameters.getSupportedFocusModes()) { 1383 parameters.setFocusMode(focusMode); 1384 mCamera.setParameters(parameters); 1385 parameters = mCamera.getParameters(); 1386 assertEquals(focusMode, parameters.getFocusMode()); 1387 checkFocusDistances(parameters); 1388 if (Parameters.FOCUS_MODE_AUTO.equals(focusMode) 1389 || Parameters.FOCUS_MODE_MACRO.equals(focusMode) 1390 || Parameters.FOCUS_MODE_CONTINUOUS_VIDEO.equals(focusMode) 1391 || Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(focusMode)) { 1392 Log.v(TAG, "Focus mode=" + focusMode); 1393 mCamera.autoFocus(mAutoFocusCallback); 1394 assertTrue(waitForFocusDone()); 1395 parameters = mCamera.getParameters(); 1396 checkFocusDistances(parameters); 1397 float[] initialFocusDistances = new float[3]; 1398 parameters.getFocusDistances(initialFocusDistances); 1399 1400 // Focus position should not change after autoFocus call. 1401 // Continuous autofocus should have stopped. Sleep some time and 1402 // check. Make sure continuous autofocus is not working. If the 1403 // focus mode is auto or macro, it is no harm to do the extra 1404 // test. 1405 Thread.sleep(500); 1406 parameters = mCamera.getParameters(); 1407 float[] currentFocusDistances = new float[3]; 1408 parameters.getFocusDistances(currentFocusDistances); 1409 assertEquals(initialFocusDistances, currentFocusDistances); 1410 1411 // Focus position should not change after stopping preview. 1412 mCamera.stopPreview(); 1413 parameters = mCamera.getParameters(); 1414 parameters.getFocusDistances(currentFocusDistances); 1415 assertEquals(initialFocusDistances, currentFocusDistances); 1416 1417 // Focus position should not change after taking a picture. 1418 mCamera.startPreview(); 1419 mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback); 1420 waitForSnapshotDone(); 1421 parameters = mCamera.getParameters(); 1422 parameters.getFocusDistances(currentFocusDistances); 1423 assertEquals(initialFocusDistances, currentFocusDistances); 1424 mCamera.startPreview(); 1425 } 1426 } 1427 1428 // Test if the method throws exception if the argument is invalid. 1429 try { 1430 parameters.getFocusDistances(null); 1431 fail("getFocusDistances should not accept null."); 1432 } catch (IllegalArgumentException e) { 1433 // expected 1434 } 1435 1436 try { 1437 parameters.getFocusDistances(new float[2]); 1438 fail("getFocusDistances should not accept a float array with two elements."); 1439 } catch (IllegalArgumentException e) { 1440 // expected 1441 } 1442 1443 try { 1444 parameters.getFocusDistances(new float[4]); 1445 fail("getFocusDistances should not accept a float array with four elements."); 1446 } catch (IllegalArgumentException e) { 1447 // expected 1448 } 1449 terminateMessageLooper(); 1450 } 1451 1452 private void checkFocusDistances(Parameters parameters) { 1453 float[] distances = new float[3]; 1454 parameters.getFocusDistances(distances); 1455 1456 // Focus distances should be greater than 0. 1457 assertTrue(distances[Parameters.FOCUS_DISTANCE_NEAR_INDEX] > 0); 1458 assertTrue(distances[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX] > 0); 1459 assertTrue(distances[Parameters.FOCUS_DISTANCE_FAR_INDEX] > 0); 1460 1461 // Make sure far focus distance >= optimal focus distance >= near focus distance. 1462 assertTrue(distances[Parameters.FOCUS_DISTANCE_FAR_INDEX] >= 1463 distances[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX]); 1464 assertTrue(distances[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX] >= 1465 distances[Parameters.FOCUS_DISTANCE_NEAR_INDEX]); 1466 1467 // Far focus distance should be infinity in infinity focus mode. 1468 if (Parameters.FOCUS_MODE_INFINITY.equals(parameters.getFocusMode())) { 1469 assertEquals(Float.POSITIVE_INFINITY, 1470 distances[Parameters.FOCUS_DISTANCE_FAR_INDEX]); 1471 } 1472 } 1473 1474 @TestTargets({ 1475 @TestTargetNew( 1476 level = TestLevel.COMPLETE, 1477 method = "cancelAutofocus", 1478 args = {} 1479 ) 1480 }) 1481 @UiThreadTest 1482 public void testCancelAutofocus() throws Exception { 1483 int nCameras = Camera.getNumberOfCameras(); 1484 for (int id = 0; id < nCameras; id++) { 1485 Log.v(TAG, "Camera id=" + id); 1486 testCancelAutofocusByCamera(id); 1487 } 1488 } 1489 1490 private void testCancelAutofocusByCamera(int cameraId) throws Exception { 1491 initializeMessageLooper(cameraId); 1492 Parameters parameters = mCamera.getParameters(); 1493 List<String> focusModes = parameters.getSupportedFocusModes(); 1494 1495 if (focusModes.contains(Parameters.FOCUS_MODE_AUTO)) { 1496 parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO); 1497 } else if (focusModes.contains(Parameters.FOCUS_MODE_MACRO)) { 1498 parameters.setFocusMode(Parameters.FOCUS_MODE_MACRO); 1499 } else { 1500 terminateMessageLooper(); 1501 return; 1502 } 1503 1504 mCamera.setParameters(parameters); 1505 1506 mCamera.startPreview(); 1507 1508 // No op if autofocus is not in progress. 1509 mCamera.cancelAutoFocus(); 1510 1511 // Try to cancel autofocus immediately. 1512 mCamera.autoFocus(mAutoFocusCallback); 1513 mCamera.cancelAutoFocus(); 1514 checkFocusDistanceNotChanging(); 1515 1516 // Try to cancel autofocus after it starts for some time. 1517 mCamera.autoFocus(mAutoFocusCallback); 1518 Thread.sleep(500); 1519 mCamera.cancelAutoFocus(); 1520 checkFocusDistanceNotChanging(); 1521 1522 // Try to cancel autofocus after it completes. It should be no op. 1523 mCamera.autoFocus(mAutoFocusCallback); 1524 assertTrue(waitForFocusDone()); 1525 mCamera.cancelAutoFocus(); 1526 1527 // Test the case calling cancelAutoFocus and release in a row. 1528 mCamera.autoFocus(mAutoFocusCallback); 1529 mCamera.cancelAutoFocus(); 1530 mCamera.release(); 1531 1532 // Ensure the camera can be opened if release is called right after AF. 1533 mCamera = Camera.open(cameraId); 1534 mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder()); 1535 mCamera.startPreview(); 1536 mCamera.autoFocus(mAutoFocusCallback); 1537 mCamera.release(); 1538 1539 terminateMessageLooper(); 1540 } 1541 1542 private void checkFocusDistanceNotChanging() throws Exception { 1543 float[] distances1 = new float[3]; 1544 float[] distances2 = new float[3]; 1545 Parameters parameters = mCamera.getParameters(); 1546 parameters.getFocusDistances(distances1); 1547 Thread.sleep(100); 1548 parameters = mCamera.getParameters(); 1549 parameters.getFocusDistances(distances2); 1550 assertEquals(distances1[Parameters.FOCUS_DISTANCE_NEAR_INDEX], 1551 distances2[Parameters.FOCUS_DISTANCE_NEAR_INDEX]); 1552 assertEquals(distances1[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX], 1553 distances2[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX]); 1554 assertEquals(distances1[Parameters.FOCUS_DISTANCE_FAR_INDEX], 1555 distances2[Parameters.FOCUS_DISTANCE_FAR_INDEX]); 1556 } 1557 1558 @TestTargets({ 1559 @TestTargetNew( 1560 level = TestLevel.COMPLETE, 1561 method = "getNumberOfCameras", 1562 args = {int.class} 1563 ), 1564 @TestTargetNew( 1565 level = TestLevel.COMPLETE, 1566 method = "getCameraInfo", 1567 args = {int.class, CameraInfo.class} 1568 ), 1569 @TestTargetNew( 1570 level = TestLevel.COMPLETE, 1571 method = "open", 1572 args = {int.class} 1573 ) 1574 }) 1575 @UiThreadTest 1576 public void testMultipleCameras() throws Exception { 1577 int nCameras = Camera.getNumberOfCameras(); 1578 Log.v(TAG, "total " + nCameras + " cameras"); 1579 assertTrue(nCameras >= 0); 1580 1581 boolean backCameraExist = false; 1582 CameraInfo info = new CameraInfo(); 1583 for (int i = 0; i < nCameras; i++) { 1584 Camera.getCameraInfo(i, info); 1585 if (info.facing == CameraInfo.CAMERA_FACING_BACK) { 1586 backCameraExist = true; 1587 break; 1588 } 1589 } 1590 // Make sure original open still works. It must return a back-facing 1591 // camera. 1592 mCamera = Camera.open(); 1593 if (mCamera != null) { 1594 mCamera.release(); 1595 assertTrue(backCameraExist); 1596 } else { 1597 assertFalse(backCameraExist); 1598 } 1599 1600 for (int id = -1; id <= nCameras; id++) { 1601 Log.v(TAG, "testing camera #" + id); 1602 1603 boolean isBadId = (id < 0 || id >= nCameras); 1604 1605 try { 1606 Camera.getCameraInfo(id, info); 1607 if (isBadId) { 1608 fail("getCameraInfo should not accept bad cameraId (" + id + ")"); 1609 } 1610 } catch (RuntimeException e) { 1611 if (!isBadId) throw e; 1612 } 1613 1614 int facing = info.facing; 1615 int orientation = info.orientation; 1616 assertTrue(facing == CameraInfo.CAMERA_FACING_BACK || 1617 facing == CameraInfo.CAMERA_FACING_FRONT); 1618 assertTrue(orientation == 0 || orientation == 90 || 1619 orientation == 180 || orientation == 270); 1620 1621 Camera camera = null; 1622 try { 1623 camera = Camera.open(id); 1624 if (isBadId) { 1625 fail("open() should not accept bad cameraId (" + id + ")"); 1626 } 1627 } catch (RuntimeException e) { 1628 if (!isBadId) throw e; 1629 } finally { 1630 if (camera != null) { 1631 camera.release(); 1632 } 1633 } 1634 } 1635 } 1636 1637 @UiThreadTest 1638 public void testPreviewPictureSizesCombination() throws Exception { 1639 int nCameras = Camera.getNumberOfCameras(); 1640 for (int id = 0; id < nCameras; id++) { 1641 Log.v(TAG, "Camera id=" + id); 1642 testPreviewPictureSizesCombinationByCamera(id); 1643 } 1644 } 1645 1646 private void testPreviewPictureSizesCombinationByCamera(int cameraId) throws Exception { 1647 initializeMessageLooper(cameraId); 1648 Parameters parameters = mCamera.getParameters(); 1649 PreviewCbForPreviewPictureSizesCombination callback = 1650 new PreviewCbForPreviewPictureSizesCombination(); 1651 1652 // Test combination of preview sizes and picture sizes. Pick four of each to test. 1653 // Do not test all combinations because it will timeout. Four is just a small number 1654 // and the test will not timeout. 1655 List<Size> previewSizes = parameters.getSupportedPreviewSizes(); 1656 List<Size> pictureSizes = parameters.getSupportedPictureSizes(); 1657 int previewSizeTestCount = Math.min(previewSizes.size(), 4); 1658 int pictureSizeTestCount = Math.min(pictureSizes.size(), 4); 1659 // Calculate the step so that the first one and the last one are always tested. 1660 float previewSizeIndexStep = (float) (previewSizes.size() - 1) / (previewSizeTestCount - 1); 1661 float pictureSizeIndexStep = (float) (pictureSizes.size() - 1) / (pictureSizeTestCount - 1); 1662 for (int i = 0; i < previewSizeTestCount; i++) { 1663 for (int j = 0; j < pictureSizeTestCount; j++) { 1664 Size previewSize = previewSizes.get(Math.round(previewSizeIndexStep * i)); 1665 Size pictureSize = pictureSizes.get(Math.round(pictureSizeIndexStep * j)); 1666 Log.v(TAG, "Test previewSize=(" + previewSize.width + "," + 1667 previewSize.height + ") pictureSize=(" + 1668 pictureSize.width + "," + pictureSize.height + ")"); 1669 mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED; 1670 mCamera.setPreviewCallback(callback); 1671 callback.expectedPreviewSize = previewSize; 1672 parameters.setPreviewSize(previewSize.width, previewSize.height); 1673 parameters.setPictureSize(pictureSize.width, pictureSize.height); 1674 mCamera.setParameters(parameters); 1675 assertEquals(previewSize, mCamera.getParameters().getPreviewSize()); 1676 assertEquals(pictureSize, mCamera.getParameters().getPictureSize()); 1677 1678 // Check if the preview size is the same as requested. 1679 mCamera.startPreview(); 1680 waitForPreviewDone(); 1681 assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult); 1682 1683 // Check if the picture size is the same as requested. 1684 mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback); 1685 waitForSnapshotDone(); 1686 assertTrue(mJpegPictureCallbackResult); 1687 assertNotNull(mJpegData); 1688 BitmapFactory.Options bmpOptions = new BitmapFactory.Options(); 1689 bmpOptions.inJustDecodeBounds = true; 1690 BitmapFactory.decodeByteArray(mJpegData, 0, mJpegData.length, bmpOptions); 1691 assertEquals(pictureSize.width, bmpOptions.outWidth); 1692 assertEquals(pictureSize.height, bmpOptions.outHeight); 1693 } 1694 } 1695 terminateMessageLooper(); 1696 } 1697 1698 private final class PreviewCbForPreviewPictureSizesCombination 1699 implements android.hardware.Camera.PreviewCallback { 1700 public Size expectedPreviewSize; 1701 public void onPreviewFrame(byte[] data, Camera camera) { 1702 if (data == null) { 1703 mPreviewCallbackResult = PREVIEW_CALLBACK_DATA_NULL; 1704 mPreviewDone.open(); 1705 return; 1706 } 1707 Size size = camera.getParameters().getPreviewSize(); 1708 int format = camera.getParameters().getPreviewFormat(); 1709 int bitsPerPixel = ImageFormat.getBitsPerPixel(format); 1710 if (!expectedPreviewSize.equals(size) || 1711 size.width * size.height * bitsPerPixel / 8 != data.length) { 1712 Log.e(TAG, "Expected preview width=" + expectedPreviewSize.width + ", height=" 1713 + expectedPreviewSize.height + ". Actual width=" + size.width + ", height=" 1714 + size.height); 1715 Log.e(TAG, "Frame data length=" + data.length + ". bitsPerPixel=" + bitsPerPixel); 1716 mPreviewCallbackResult = PREVIEW_CALLBACK_INVALID_FRAME_SIZE; 1717 mPreviewDone.open(); 1718 return; 1719 } 1720 camera.setPreviewCallback(null); 1721 mPreviewCallbackResult = PREVIEW_CALLBACK_RECEIVED; 1722 mPreviewDone.open(); 1723 } 1724 } 1725 1726 @UiThreadTest 1727 public void testPreviewFpsRange() throws Exception { 1728 int nCameras = Camera.getNumberOfCameras(); 1729 for (int id = 0; id < nCameras; id++) { 1730 Log.v(TAG, "Camera id=" + id); 1731 testPreviewFpsRangeByCamera(id); 1732 } 1733 } 1734 1735 private void testPreviewFpsRangeByCamera(int cameraId) throws Exception { 1736 initializeMessageLooper(cameraId); 1737 1738 // Test if the parameters exists and minimum fps <= maximum fps. 1739 int[] defaultFps = new int[2]; 1740 Parameters parameters = mCamera.getParameters(); 1741 parameters.getPreviewFpsRange(defaultFps); 1742 List<int[]> fpsList = parameters.getSupportedPreviewFpsRange(); 1743 assertTrue(fpsList.size() > 0); 1744 boolean found = false; 1745 for(int[] fps: fpsList) { 1746 assertTrue(fps[Parameters.PREVIEW_FPS_MIN_INDEX] > 0); 1747 assertTrue(fps[Parameters.PREVIEW_FPS_MIN_INDEX] <= 1748 fps[Parameters.PREVIEW_FPS_MAX_INDEX]); 1749 if (!found && Arrays.equals(defaultFps, fps)) { 1750 found = true; 1751 } 1752 } 1753 assertTrue("Preview fps range must be in the supported list.", found); 1754 1755 // Test if the list is properly sorted. 1756 for (int i = 0; i < fpsList.size() - 1; i++) { 1757 int minFps1 = fpsList.get(i)[Parameters.PREVIEW_FPS_MIN_INDEX]; 1758 int maxFps1 = fpsList.get(i)[Parameters.PREVIEW_FPS_MAX_INDEX]; 1759 int minFps2 = fpsList.get(i + 1)[Parameters.PREVIEW_FPS_MIN_INDEX]; 1760 int maxFps2 = fpsList.get(i + 1)[Parameters.PREVIEW_FPS_MAX_INDEX]; 1761 assertTrue(maxFps1 < maxFps2 1762 || (maxFps1 == maxFps2 && minFps1 < minFps2)); 1763 } 1764 1765 // Test if the actual fps is within fps range. 1766 Size size = parameters.getPreviewSize(); 1767 int format = mCamera.getParameters().getPreviewFormat(); 1768 int bitsPerPixel = ImageFormat.getBitsPerPixel(format); 1769 byte[] buffer1 = new byte[size.width * size.height * bitsPerPixel / 8]; 1770 byte[] buffer2 = new byte[size.width * size.height * bitsPerPixel / 8]; 1771 byte[] buffer3 = new byte[size.width * size.height * bitsPerPixel / 8]; 1772 FpsRangePreviewCb callback = new FpsRangePreviewCb(); 1773 int[] readBackFps = new int[2]; 1774 for (int[] fps: fpsList) { 1775 parameters = mCamera.getParameters(); 1776 parameters.setPreviewFpsRange(fps[Parameters.PREVIEW_FPS_MIN_INDEX], 1777 fps[Parameters.PREVIEW_FPS_MAX_INDEX]); 1778 callback.reset(fps[Parameters.PREVIEW_FPS_MIN_INDEX] / 1000.0, 1779 fps[Parameters.PREVIEW_FPS_MAX_INDEX] / 1000.0); 1780 mCamera.setParameters(parameters); 1781 parameters = mCamera.getParameters(); 1782 parameters.getPreviewFpsRange(readBackFps); 1783 MoreAsserts.assertEquals(fps, readBackFps); 1784 mCamera.addCallbackBuffer(buffer1); 1785 mCamera.addCallbackBuffer(buffer2); 1786 mCamera.addCallbackBuffer(buffer3); 1787 mCamera.setPreviewCallbackWithBuffer(callback); 1788 mCamera.startPreview(); 1789 try { 1790 // Test the frame rate for a while. 1791 Thread.sleep(3000); 1792 } catch(Exception e) { 1793 // ignore 1794 } 1795 mCamera.stopPreview(); 1796 } 1797 1798 // Test the invalid fps cases. 1799 parameters = mCamera.getParameters(); 1800 parameters.setPreviewFpsRange(-1, -1); 1801 try { 1802 mCamera.setParameters(parameters); 1803 fail("Should throw an exception if fps range is negative."); 1804 } catch (RuntimeException e) { 1805 // expected 1806 } 1807 parameters.setPreviewFpsRange(10, 5); 1808 try { 1809 mCamera.setParameters(parameters); 1810 fail("Should throw an exception if fps range is invalid."); 1811 } catch (RuntimeException e) { 1812 // expected 1813 } 1814 1815 terminateMessageLooper(); 1816 } 1817 1818 private final class FpsRangePreviewCb 1819 implements android.hardware.Camera.PreviewCallback { 1820 private double mMinFps, mMaxFps, mMaxFrameInterval, mMinFrameInterval; 1821 // An array storing the arrival time of the frames in the last second. 1822 private ArrayList<Long> mFrames = new ArrayList<Long>(); 1823 private long firstFrameArrivalTime; 1824 1825 public void reset(double minFps, double maxFps) { 1826 this.mMinFps = minFps; 1827 this.mMaxFps = maxFps; 1828 mMaxFrameInterval = 1000.0 / mMinFps; 1829 mMinFrameInterval = 1000.0 / mMaxFps; 1830 Log.v(TAG, "Min fps=" + mMinFps + ". Max fps=" + mMaxFps 1831 + ". Min frame interval=" + mMinFrameInterval 1832 + ". Max frame interval=" + mMaxFrameInterval); 1833 mFrames.clear(); 1834 firstFrameArrivalTime = 0; 1835 } 1836 1837 // This method tests if the actual fps is between minimum and maximum. 1838 // It also tests if the frame interval is too long. 1839 public void onPreviewFrame(byte[] data, android.hardware.Camera camera) { 1840 long arrivalTime = System.currentTimeMillis(); 1841 camera.addCallbackBuffer(data); 1842 if (firstFrameArrivalTime == 0) firstFrameArrivalTime = arrivalTime; 1843 1844 // Remove the frames that arrived before the last second. 1845 Iterator<Long> it = mFrames.iterator(); 1846 while(it.hasNext()) { 1847 long time = it.next(); 1848 if (arrivalTime - time > 1000 && mFrames.size() > 2) { 1849 it.remove(); 1850 } else { 1851 break; 1852 } 1853 } 1854 1855 // Start the test after one second. 1856 if (arrivalTime - firstFrameArrivalTime > 1000) { 1857 assertTrue(mFrames.size() >= 2); 1858 1859 // Check the frame interval and fps. The interval check 1860 // considers the time variance passing frames from the camera 1861 // hardware to the callback. It should be a constant time, not a 1862 // ratio. The fps check is more strict because individual 1863 // variance is averaged out. 1864 1865 // Check if the frame interval is too large or too small. 1866 double intervalMargin = 30; // ms 1867 long lastArrivalTime = mFrames.get(mFrames.size() - 1); 1868 double interval = arrivalTime - lastArrivalTime; 1869 if (LOGV) Log.v(TAG, "Frame interval=" + interval); 1870 assertTrue("Frame interval (" + interval + "ms) is too large." + 1871 " mMaxFrameInterval=" + mMaxFrameInterval + "ms", 1872 interval < mMaxFrameInterval + intervalMargin); 1873 assertTrue("Frame interval (" + interval + "ms) is too small." + 1874 " mMinFrameInterval=" + mMinFrameInterval + "ms", 1875 interval > mMinFrameInterval - intervalMargin); 1876 1877 // Check if the fps is within range. 1878 double fpsMargin = 0.05; 1879 double avgInterval = (double)(arrivalTime - mFrames.get(0)) 1880 / mFrames.size(); 1881 double fps = 1000.0 / avgInterval; 1882 assertTrue("Actual fps (" + fps + ") should be larger than " + 1883 "min fps (" + mMinFps + ")", 1884 fps >= mMinFps * (1 - fpsMargin)); 1885 assertTrue("Actual fps (" + fps + ") should be smaller than " + 1886 "max fps (" + mMaxFps + ")", 1887 fps <= mMaxFps * (1 + fpsMargin)); 1888 } 1889 // Add the arrival time of this frame to the list. 1890 mFrames.add(arrivalTime); 1891 } 1892 } 1893 1894 private void assertEquals(Size expected, Size actual) { 1895 assertEquals(expected.width, actual.width); 1896 assertEquals(expected.height, actual.height); 1897 } 1898 1899 private void assertEquals(float[] expected, float[] actual) { 1900 assertEquals(expected.length, actual.length); 1901 for (int i = 0; i < expected.length; i++) { 1902 assertEquals(expected[i], actual[i], 0.000001f); 1903 } 1904 } 1905 1906 private void assertNoLetters(String value, String key) { 1907 for (int i = 0; i < value.length(); i++) { 1908 char c = value.charAt(i); 1909 assertFalse("Parameter contains invalid characters. key,value=(" 1910 + key + "," + value + ")", 1911 Character.isLetter(c) && c != 'x'); 1912 } 1913 } 1914 1915 @UiThreadTest 1916 public void testSceneMode() throws Exception { 1917 int nCameras = Camera.getNumberOfCameras(); 1918 for (int id = 0; id < nCameras; id++) { 1919 Log.v(TAG, "Camera id=" + id); 1920 testSceneModeByCamera(id); 1921 } 1922 } 1923 1924 private class SceneModeSettings { 1925 public String mScene, mFlash, mFocus, mWhiteBalance; 1926 public List<String> mSupportedFlash, mSupportedFocus, mSupportedWhiteBalance; 1927 1928 public SceneModeSettings(Parameters parameters) { 1929 mScene = parameters.getSceneMode(); 1930 mFlash = parameters.getFlashMode(); 1931 mFocus = parameters.getFocusMode(); 1932 mWhiteBalance = parameters.getWhiteBalance(); 1933 mSupportedFlash = parameters.getSupportedFlashModes(); 1934 mSupportedFocus = parameters.getSupportedFocusModes(); 1935 mSupportedWhiteBalance = parameters.getSupportedWhiteBalance(); 1936 } 1937 } 1938 1939 private void testSceneModeByCamera(int cameraId) throws Exception { 1940 initializeMessageLooper(cameraId); 1941 Parameters parameters = mCamera.getParameters(); 1942 List<String> supportedSceneModes = parameters.getSupportedSceneModes(); 1943 if (supportedSceneModes != null) { 1944 assertEquals(Parameters.SCENE_MODE_AUTO, parameters.getSceneMode()); 1945 SceneModeSettings autoSceneMode = new SceneModeSettings(parameters); 1946 1947 // Store all scene mode affected settings. 1948 SceneModeSettings[] settings = new SceneModeSettings[supportedSceneModes.size()]; 1949 for (int i = 0; i < supportedSceneModes.size(); i++) { 1950 parameters.setSceneMode(supportedSceneModes.get(i)); 1951 mCamera.setParameters(parameters); 1952 parameters = mCamera.getParameters(); 1953 settings[i] = new SceneModeSettings(parameters); 1954 } 1955 1956 // Make sure scene mode settings are consistent before preview and 1957 // after preview. 1958 mCamera.startPreview(); 1959 waitForPreviewDone(); 1960 for (int i = 0; i < supportedSceneModes.size(); i++) { 1961 String sceneMode = supportedSceneModes.get(i); 1962 parameters.setSceneMode(sceneMode); 1963 mCamera.setParameters(parameters); 1964 parameters = mCamera.getParameters(); 1965 1966 // In auto scene mode, camera HAL will not remember the previous 1967 // flash, focus, and white-balance. It will just take values set 1968 // by parameters. But the supported flash, focus, and 1969 // white-balance should still be restored in auto scene mode. 1970 if (!Parameters.SCENE_MODE_AUTO.equals(sceneMode)) { 1971 assertEquals("Flash is inconsistent in scene mode " + sceneMode, 1972 settings[i].mFlash, parameters.getFlashMode()); 1973 assertEquals("Focus is inconsistent in scene mode " + sceneMode, 1974 settings[i].mFocus, parameters.getFocusMode()); 1975 assertEquals("White balance is inconsistent in scene mode " + sceneMode, 1976 settings[i].mWhiteBalance, parameters.getWhiteBalance()); 1977 } 1978 assertEquals("Suppported flash modes are inconsistent in scene mode " + sceneMode, 1979 settings[i].mSupportedFlash, parameters.getSupportedFlashModes()); 1980 assertEquals("Suppported focus modes are inconsistent in scene mode " + sceneMode, 1981 settings[i].mSupportedFocus, parameters.getSupportedFocusModes()); 1982 assertEquals("Suppported white balance are inconsistent in scene mode " + sceneMode, 1983 settings[i].mSupportedWhiteBalance, parameters.getSupportedWhiteBalance()); 1984 } 1985 1986 for (int i = 0; i < settings.length; i++) { 1987 if (Parameters.SCENE_MODE_AUTO.equals(settings[i].mScene)) continue; 1988 1989 // Both the setting and the supported settings may change. It is 1990 // allowed to have more than one supported settings in scene 1991 // modes. For example, in night scene mode, supported flash 1992 // modes can have on and off. 1993 if (autoSceneMode.mSupportedFlash != null) { 1994 assertTrue(settings[i].mSupportedFlash.contains(settings[i].mFlash)); 1995 for (String mode: settings[i].mSupportedFlash) { 1996 assertTrue(autoSceneMode.mSupportedFlash.contains(mode)); 1997 } 1998 } 1999 if (autoSceneMode.mSupportedFocus != null) { 2000 assertTrue(settings[i].mSupportedFocus.contains(settings[i].mFocus)); 2001 for (String mode: settings[i].mSupportedFocus) { 2002 assertTrue(autoSceneMode.mSupportedFocus.contains(mode)); 2003 } 2004 } 2005 if (autoSceneMode.mSupportedWhiteBalance != null) { 2006 assertTrue(settings[i].mSupportedWhiteBalance.contains(settings[i].mWhiteBalance)); 2007 for (String mode: settings[i].mSupportedWhiteBalance) { 2008 assertTrue(autoSceneMode.mSupportedWhiteBalance.contains(mode)); 2009 } 2010 } 2011 } 2012 } 2013 terminateMessageLooper(); 2014 } 2015 2016 @UiThreadTest 2017 public void testInvalidParameters() throws Exception { 2018 int nCameras = Camera.getNumberOfCameras(); 2019 for (int id = 0; id < nCameras; id++) { 2020 Log.v(TAG, "Camera id=" + id); 2021 testInvalidParametersByCamera(id); 2022 } 2023 } 2024 2025 private void testInvalidParametersByCamera(int cameraId) throws Exception { 2026 initializeMessageLooper(cameraId); 2027 // Test flash mode. 2028 Parameters parameters = mCamera.getParameters(); 2029 List<String> list = parameters.getSupportedFlashModes(); 2030 if (list != null && list.size() > 0) { 2031 String original = parameters.getFlashMode(); 2032 parameters.setFlashMode("invalid"); 2033 try { 2034 mCamera.setParameters(parameters); 2035 fail("Should throw exception for invalid parameters"); 2036 } catch (RuntimeException e) { 2037 // expected 2038 } 2039 parameters = mCamera.getParameters(); 2040 assertEquals(original, parameters.getFlashMode()); 2041 } 2042 2043 // Test focus mode. 2044 String originalFocus = parameters.getFocusMode(); 2045 parameters.setFocusMode("invalid"); 2046 try { 2047 mCamera.setParameters(parameters); 2048 fail("Should throw exception for invalid parameters"); 2049 } catch (RuntimeException e) { 2050 // expected 2051 } 2052 parameters = mCamera.getParameters(); 2053 assertEquals(originalFocus, parameters.getFocusMode()); 2054 2055 // Test preview size. 2056 Size originalSize = parameters.getPreviewSize(); 2057 parameters.setPreviewSize(-1, -1); 2058 try { 2059 mCamera.setParameters(parameters); 2060 fail("Should throw exception for invalid parameters"); 2061 } catch (RuntimeException e) { 2062 // expected 2063 } 2064 parameters = mCamera.getParameters(); 2065 assertEquals(originalSize, parameters.getPreviewSize()); 2066 2067 terminateMessageLooper(); 2068 } 2069 2070 @UiThreadTest 2071 public void testGetParameterDuringFocus() throws Exception { 2072 int nCameras = Camera.getNumberOfCameras(); 2073 for (int id = 0; id < nCameras; id++) { 2074 Log.v(TAG, "Camera id=" + id); 2075 testGetParameterDuringFocusByCamera(id); 2076 } 2077 } 2078 2079 private void testGetParameterDuringFocusByCamera(int cameraId) throws Exception { 2080 initializeMessageLooper(cameraId); 2081 mCamera.startPreview(); 2082 Parameters parameters = mCamera.getParameters(); 2083 for (String focusMode: parameters.getSupportedFocusModes()) { 2084 if (focusMode.equals(parameters.FOCUS_MODE_AUTO) 2085 || focusMode.equals(parameters.FOCUS_MODE_MACRO)) { 2086 parameters.setFocusMode(focusMode); 2087 mCamera.setParameters(parameters); 2088 mCamera.autoFocus(mAutoFocusCallback); 2089 // This should not crash or throw exception. 2090 mCamera.getParameters(); 2091 waitForFocusDone(); 2092 2093 2094 mCamera.autoFocus(mAutoFocusCallback); 2095 // Add a small delay to make sure focus has started. 2096 Thread.sleep(100); 2097 // This should not crash or throw exception. 2098 mCamera.getParameters(); 2099 waitForFocusDone(); 2100 } 2101 } 2102 terminateMessageLooper(); 2103 } 2104 2105 @UiThreadTest 2106 public void testPreviewFormats() throws Exception { 2107 int nCameras = Camera.getNumberOfCameras(); 2108 for (int id = 0; id < nCameras; id++) { 2109 Log.v(TAG, "Camera id=" + id); 2110 testPreviewFormatsByCamera(id); 2111 } 2112 } 2113 2114 private void testPreviewFormatsByCamera(int cameraId) throws Exception { 2115 initializeMessageLooper(cameraId); 2116 Parameters parameters = mCamera.getParameters(); 2117 for (int format: parameters.getSupportedPreviewFormats()) { 2118 Log.v(TAG, "Test preview format " + format); 2119 parameters.setPreviewFormat(format); 2120 mCamera.setParameters(parameters); 2121 mCamera.setOneShotPreviewCallback(mPreviewCallback); 2122 mCamera.startPreview(); 2123 waitForPreviewDone(); 2124 assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult); 2125 } 2126 terminateMessageLooper(); 2127 } 2128 2129 @UiThreadTest 2130 public void testMultiCameraRelease() throws Exception { 2131 // Verify that multiple cameras exist, and that they can be opened at the same time 2132 if (LOGV) Log.v(TAG, "testMultiCameraRelease: Checking pre-conditions."); 2133 int nCameras = Camera.getNumberOfCameras(); 2134 if (nCameras < 2) { 2135 Log.i(TAG, "Test multi-camera release: Skipping test because only 1 camera available"); 2136 return; 2137 } 2138 2139 Camera testCamera0 = Camera.open(0); 2140 Camera testCamera1 = null; 2141 try { 2142 testCamera1 = Camera.open(1); 2143 } catch (RuntimeException e) { 2144 // Can't open two cameras at once 2145 Log.i(TAG, "testMultiCameraRelease: Skipping test because only 1 camera "+ 2146 "could be opened at once. Second open threw: " + e); 2147 testCamera0.release(); 2148 return; 2149 } 2150 testCamera0.release(); 2151 testCamera1.release(); 2152 2153 // Start first camera 2154 if (LOGV) Log.v(TAG, "testMultiCameraRelease: Opening camera 0"); 2155 initializeMessageLooper(0); 2156 SimplePreviewStreamCb callback0 = new SimplePreviewStreamCb(0); 2157 mCamera.setPreviewCallback(callback0); 2158 if (LOGV) Log.v(TAG, "testMultiCameraRelease: Starting preview on camera 0"); 2159 mCamera.startPreview(); 2160 // Run preview for a bit 2161 for (int f = 0; f < 100; f++) { 2162 mPreviewDone.close(); 2163 assertTrue("testMultiCameraRelease: First camera preview timed out on frame " + f + "!", 2164 mPreviewDone.block( WAIT_FOR_COMMAND_TO_COMPLETE)); 2165 } 2166 if (LOGV) Log.v(TAG, "testMultiCameraRelease: Stopping preview on camera 0"); 2167 mCamera.stopPreview(); 2168 // Save message looper and camera to deterministically release them, instead 2169 // of letting GC do it at some point. 2170 Camera firstCamera = mCamera; 2171 Looper firstLooper = mLooper; 2172 //terminateMessageLooper(); // Intentionally not calling this 2173 // Preview surface should be released though! 2174 mCamera.setPreviewDisplay(null); 2175 2176 // Start second camera without releasing the first one (will 2177 // set mCamera and mLooper to new objects) 2178 if (LOGV) Log.v(TAG, "testMultiCameraRelease: Opening camera 1"); 2179 initializeMessageLooper(1); 2180 SimplePreviewStreamCb callback1 = new SimplePreviewStreamCb(1); 2181 mCamera.setPreviewCallback(callback1); 2182 if (LOGV) Log.v(TAG, "testMultiCameraRelease: Starting preview on camera 1"); 2183 mCamera.startPreview(); 2184 // Run preview for a bit - GC of first camera instance should not impact the second's 2185 // operation. 2186 for (int f = 0; f < 100; f++) { 2187 mPreviewDone.close(); 2188 assertTrue("testMultiCameraRelease: Second camera preview timed out on frame " + f + "!", 2189 mPreviewDone.block( WAIT_FOR_COMMAND_TO_COMPLETE)); 2190 if (f == 50) { 2191 // Release first camera mid-preview, should cause no problems 2192 if (LOGV) Log.v(TAG, "testMultiCameraRelease: Releasing camera 0"); 2193 firstCamera.release(); 2194 } 2195 } 2196 if (LOGV) Log.v(TAG, "testMultiCameraRelease: Stopping preview on camera 0"); 2197 mCamera.stopPreview(); 2198 2199 firstLooper.quit(); 2200 terminateMessageLooper(); 2201 } 2202 2203 // This callback just signals on the condition variable, making it useful for checking that 2204 // preview callbacks don't stop unexpectedly 2205 private final class SimplePreviewStreamCb 2206 implements android.hardware.Camera.PreviewCallback { 2207 private int mId; 2208 public SimplePreviewStreamCb(int id) { 2209 mId = id; 2210 } 2211 public void onPreviewFrame(byte[] data, android.hardware.Camera camera) { 2212 if (LOGV) Log.v(TAG, "Preview frame callback, id " + mId + "."); 2213 mPreviewDone.open(); 2214 } 2215 } 2216 2217 @UiThreadTest 2218 public void testFocusAreas() throws Exception { 2219 int nCameras = Camera.getNumberOfCameras(); 2220 for (int id = 0; id < nCameras; id++) { 2221 Log.v(TAG, "Camera id=" + id); 2222 2223 initializeMessageLooper(id); 2224 Parameters parameters = mCamera.getParameters(); 2225 int maxNumFocusAreas = parameters.getMaxNumFocusAreas(); 2226 assertTrue(maxNumFocusAreas >= 0); 2227 if (maxNumFocusAreas > 0) { 2228 List<String> focusModes = parameters.getSupportedFocusModes(); 2229 assertTrue(focusModes.contains(Parameters.FOCUS_MODE_AUTO)); 2230 testAreas(FOCUS_AREA, maxNumFocusAreas); 2231 } 2232 terminateMessageLooper(); 2233 } 2234 } 2235 2236 @UiThreadTest 2237 public void testMeteringAreas() throws Exception { 2238 int nCameras = Camera.getNumberOfCameras(); 2239 for (int id = 0; id < nCameras; id++) { 2240 Log.v(TAG, "Camera id=" + id); 2241 initializeMessageLooper(id); 2242 Parameters parameters = mCamera.getParameters(); 2243 int maxNumMeteringAreas = parameters.getMaxNumMeteringAreas(); 2244 assertTrue(maxNumMeteringAreas >= 0); 2245 if (maxNumMeteringAreas > 0) { 2246 testAreas(METERING_AREA, maxNumMeteringAreas); 2247 } 2248 terminateMessageLooper(); 2249 } 2250 } 2251 2252 private void testAreas(int type, int maxNumAreas) throws Exception { 2253 mCamera.startPreview(); 2254 2255 // Test various valid cases. 2256 testValidAreas(type, null); // the default area 2257 testValidAreas(type, makeAreas(-1000, -1000, 1000, 1000, 1)); // biggest area 2258 testValidAreas(type, makeAreas(-500, -500, 500, 500, 1000)); // medium area & biggest weight 2259 testValidAreas(type, makeAreas(0, 0, 1, 1, 1)); // smallest area 2260 2261 ArrayList<Area> areas = new ArrayList(); 2262 if (maxNumAreas > 1) { 2263 // Test overlapped areas. 2264 testValidAreas(type, makeAreas(-250, -250, 250, 250, 1, 0, 0, 500, 500, 2)); 2265 // Test completely disjoint areas. 2266 testValidAreas(type, makeAreas(-250, -250, 0, 0, 1, 900, 900, 1000, 1000, 1)); 2267 // Test the maximum number of areas. 2268 testValidAreas(type, makeAreas(-1000, -1000, 1000, 1000, 1000, maxNumAreas)); 2269 } 2270 2271 // Test various invalid cases. 2272 testInvalidAreas(type, makeAreas(-1001, -1000, 1000, 1000, 1)); // left should >= -1000 2273 testInvalidAreas(type, makeAreas(-1000, -1001, 1000, 1000, 1)); // top should >= -1000 2274 testInvalidAreas(type, makeAreas(-1000, -1000, 1001, 1000, 1)); // right should <= 1000 2275 testInvalidAreas(type, makeAreas(-1000, -1000, 1000, 1001, 1)); // bottom should <= 1000 2276 testInvalidAreas(type, makeAreas(-1000, -1000, 1000, 1000, 0)); // weight should >= 1 2277 testInvalidAreas(type, makeAreas(-1000, -1000, 1000, 1001, 1001)); // weight should <= 1000 2278 testInvalidAreas(type, makeAreas(500, -1000, 500, 1000, 1)); // left should < right 2279 testInvalidAreas(type, makeAreas(-1000, 500, 1000, 500, 1)); // top should < bottom 2280 testInvalidAreas(type, makeAreas(500, -1000, 499, 1000, 1)); // left should < right 2281 testInvalidAreas(type, makeAreas(-1000, 500, 100, 499, 1)); // top should < bottom 2282 testInvalidAreas(type, makeAreas(-250, -250, 250, 250, -1)); // weight should >= 1 2283 // Test when the number of areas exceeds maximum. 2284 testInvalidAreas(type, makeAreas(-1000, -1000, 1000, 1000, 1000, maxNumAreas + 1)); 2285 } 2286 2287 private static ArrayList<Area> makeAreas(int left, int top, int right, int bottom, int weight) { 2288 ArrayList<Area> areas = new ArrayList<Area>(); 2289 areas.add(new Area(new Rect(left, top, right, bottom), weight)); 2290 return areas; 2291 } 2292 2293 private static ArrayList<Area> makeAreas(int left, int top, int right, int bottom, 2294 int weight, int number) { 2295 ArrayList<Area> areas = new ArrayList<Area>(); 2296 for (int i = 0; i < number; i++) { 2297 areas.add(new Area(new Rect(left, top, right, bottom), weight)); 2298 } 2299 return areas; 2300 } 2301 2302 private static ArrayList<Area> makeAreas(int left1, int top1, int right1, 2303 int bottom1, int weight1, int left2, int top2, int right2, 2304 int bottom2, int weight2) { 2305 ArrayList<Area> areas = new ArrayList<Area>(); 2306 areas.add(new Area(new Rect(left1, top1, right1, bottom1), weight1)); 2307 areas.add(new Area(new Rect(left2, top2, right2, bottom2), weight2)); 2308 return areas; 2309 } 2310 2311 private void testValidAreas(int areaType, ArrayList<Area> areas) { 2312 if (areaType == FOCUS_AREA) { 2313 testValidFocusAreas(areas); 2314 } else { 2315 testValidMeteringAreas(areas); 2316 } 2317 } 2318 2319 private void testInvalidAreas(int areaType, ArrayList<Area> areas) { 2320 if (areaType == FOCUS_AREA) { 2321 testInvalidFocusAreas(areas); 2322 } else { 2323 testInvalidMeteringAreas(areas); 2324 } 2325 } 2326 2327 private void testValidFocusAreas(ArrayList<Area> areas) { 2328 Parameters parameters = mCamera.getParameters(); 2329 parameters.setFocusAreas(areas); 2330 mCamera.setParameters(parameters); 2331 parameters = mCamera.getParameters(); 2332 assertEquals(areas, parameters.getFocusAreas()); 2333 mCamera.autoFocus(mAutoFocusCallback); 2334 waitForFocusDone(); 2335 } 2336 2337 private void testInvalidFocusAreas(ArrayList<Area> areas) { 2338 Parameters parameters = mCamera.getParameters(); 2339 List<Area> originalAreas = parameters.getFocusAreas(); 2340 try { 2341 parameters.setFocusAreas(areas); 2342 mCamera.setParameters(parameters); 2343 fail("Should throw exception when focus area is invalid."); 2344 } catch (RuntimeException e) { 2345 parameters = mCamera.getParameters(); 2346 assertEquals(originalAreas, parameters.getFocusAreas()); 2347 } 2348 } 2349 2350 private void testValidMeteringAreas(ArrayList<Area> areas) { 2351 Parameters parameters = mCamera.getParameters(); 2352 parameters.setMeteringAreas(areas); 2353 mCamera.setParameters(parameters); 2354 parameters = mCamera.getParameters(); 2355 assertEquals(areas, parameters.getMeteringAreas()); 2356 } 2357 2358 private void testInvalidMeteringAreas(ArrayList<Area> areas) { 2359 Parameters parameters = mCamera.getParameters(); 2360 List<Area> originalAreas = parameters.getMeteringAreas(); 2361 try { 2362 parameters.setMeteringAreas(areas); 2363 mCamera.setParameters(parameters); 2364 fail("Should throw exception when metering area is invalid."); 2365 } catch (RuntimeException e) { 2366 parameters = mCamera.getParameters(); 2367 assertEquals(originalAreas, parameters.getMeteringAreas()); 2368 } 2369 } 2370 2371 // Apps should be able to call startPreview in jpeg callback. 2372 @UiThreadTest 2373 public void testJpegCallbackStartPreview() throws Exception { 2374 int nCameras = Camera.getNumberOfCameras(); 2375 for (int id = 0; id < nCameras; id++) { 2376 Log.v(TAG, "Camera id=" + id); 2377 testJpegCallbackStartPreviewByCamera(id); 2378 } 2379 } 2380 2381 private void testJpegCallbackStartPreviewByCamera(int cameraId) throws Exception { 2382 initializeMessageLooper(cameraId); 2383 mCamera.startPreview(); 2384 mCamera.takePicture(mShutterCallback, mRawPictureCallback, new JpegStartPreviewCallback()); 2385 waitForSnapshotDone(); 2386 terminateMessageLooper(); 2387 assertTrue(mJpegPictureCallbackResult); 2388 } 2389 2390 private final class JpegStartPreviewCallback implements PictureCallback { 2391 public void onPictureTaken(byte[] rawData, Camera camera) { 2392 try { 2393 camera.startPreview(); 2394 mJpegPictureCallbackResult = true; 2395 } catch (Exception e) { 2396 } 2397 mSnapshotDone.open(); 2398 } 2399 } 2400 2401 @UiThreadTest 2402 public void testRecordingHint() throws Exception { 2403 int nCameras = Camera.getNumberOfCameras(); 2404 for (int id = 0; id < nCameras; id++) { 2405 Log.v(TAG, "Camera id=" + id); 2406 testRecordingHintByCamera(id); 2407 } 2408 } 2409 2410 private void testRecordingHintByCamera(int cameraId) throws Exception { 2411 initializeMessageLooper(cameraId); 2412 Parameters parameters = mCamera.getParameters(); 2413 2414 SurfaceHolder holder = getActivity().getSurfaceView().getHolder(); 2415 CamcorderProfile profile = CamcorderProfile.get(cameraId, 2416 CamcorderProfile.QUALITY_LOW); 2417 2418 setPreviewSizeByProfile(parameters, profile); 2419 2420 // Test recording videos and taking pictures when the hint is off and on. 2421 for (int i = 0; i < 2; i++) { 2422 parameters.setRecordingHint(i == 0 ? false : true); 2423 mCamera.setParameters(parameters); 2424 mCamera.startPreview(); 2425 recordVideoSimple(profile, holder); 2426 mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback); 2427 waitForSnapshotDone(); 2428 assertTrue(mJpegPictureCallbackResult); 2429 } 2430 2431 // Can change recording hint when the preview is active. 2432 mCamera.startPreview(); 2433 parameters.setRecordingHint(false); 2434 mCamera.setParameters(parameters); 2435 parameters.setRecordingHint(true); 2436 mCamera.setParameters(parameters); 2437 terminateMessageLooper(); 2438 } 2439 2440 private void recordVideoSimple(CamcorderProfile profile, 2441 SurfaceHolder holder) throws Exception { 2442 mCamera.unlock(); 2443 MediaRecorder recorder = new MediaRecorder(); 2444 try { 2445 recorder.setCamera(mCamera); 2446 recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 2447 recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 2448 recorder.setProfile(profile); 2449 recorder.setOutputFile("/dev/null"); 2450 recorder.setPreviewDisplay(holder.getSurface()); 2451 recorder.prepare(); 2452 recorder.start(); 2453 Thread.sleep(2000); 2454 recorder.stop(); 2455 } finally { 2456 recorder.release(); 2457 mCamera.lock(); 2458 } 2459 } 2460 2461 @UiThreadTest 2462 public void testAutoExposureLock() throws Exception { 2463 int nCameras = Camera.getNumberOfCameras(); 2464 for (int id = 0; id < nCameras; id++) { 2465 Log.v(TAG, "Camera id=" + id); 2466 initializeMessageLooper(id); 2467 Parameters parameters = mCamera.getParameters(); 2468 boolean aeLockSupported = parameters.isAutoExposureLockSupported(); 2469 if (aeLockSupported) { 2470 testLockCommon(AUTOEXPOSURE_LOCK); 2471 testLockAdditionalAE(); 2472 } 2473 terminateMessageLooper(); 2474 } 2475 } 2476 2477 @UiThreadTest 2478 public void testAutoWhiteBalanceLock() throws Exception { 2479 int nCameras = Camera.getNumberOfCameras(); 2480 for (int id = 0; id < nCameras; id++) { 2481 Log.v(TAG, "Camera id=" + id); 2482 initializeMessageLooper(id); 2483 Parameters parameters = mCamera.getParameters(); 2484 boolean awbLockSupported = parameters.isAutoWhiteBalanceLockSupported(); 2485 if (awbLockSupported) { 2486 testLockCommon(AUTOWHITEBALANCE_LOCK); 2487 testLockAdditionalAWB(); 2488 } 2489 terminateMessageLooper(); 2490 } 2491 } 2492 2493 @UiThreadTest 2494 public void test3ALockInteraction() throws Exception { 2495 int nCameras = Camera.getNumberOfCameras(); 2496 for (int id = 0; id < nCameras; id++) { 2497 Log.v(TAG, "Camera id=" + id); 2498 initializeMessageLooper(id); 2499 Parameters parameters = mCamera.getParameters(); 2500 boolean locksSupported = 2501 parameters.isAutoWhiteBalanceLockSupported() && 2502 parameters.isAutoExposureLockSupported(); 2503 if (locksSupported) { 2504 testLockInteractions(); 2505 } 2506 terminateMessageLooper(); 2507 } 2508 } 2509 2510 private void testLockCommon(int type) { 2511 // Verify lock is not set on open() 2512 assert3ALockState("Lock not released after open()", type, false); 2513 2514 // Verify lock can be set, unset before preview 2515 set3ALockState(true, type); 2516 assert3ALockState("Lock could not be set before 1st preview!", 2517 type, true); 2518 2519 set3ALockState(false, type); 2520 assert3ALockState("Lock could not be unset before 1st preview!", 2521 type, false); 2522 2523 // Verify preview start does not set lock 2524 mCamera.startPreview(); 2525 assert3ALockState("Lock state changed by preview start!", type, false); 2526 2527 // Verify lock can be set, unset during preview 2528 set3ALockState(true, type); 2529 assert3ALockState("Lock could not be set during preview!", type, true); 2530 2531 set3ALockState(false, type); 2532 assert3ALockState("Lock could not be unset during preview!", 2533 type, false); 2534 2535 // Verify lock is not cleared by stop preview 2536 set3ALockState(true, type); 2537 mCamera.stopPreview(); 2538 assert3ALockState("Lock was cleared by stopPreview!", type, true); 2539 2540 // Verify that preview start does not clear lock 2541 set3ALockState(true, type); 2542 mCamera.startPreview(); 2543 assert3ALockState("Lock state changed by preview start!", type, true); 2544 2545 // Verify that taking a picture does not clear the lock 2546 set3ALockState(true, type); 2547 mCamera.takePicture(mShutterCallback, mRawPictureCallback, 2548 mJpegPictureCallback); 2549 waitForSnapshotDone(); 2550 assert3ALockState("Lock state was cleared by takePicture!", type, true); 2551 2552 mCamera.startPreview(); 2553 Parameters parameters = mCamera.getParameters(); 2554 for (String focusMode: parameters.getSupportedFocusModes()) { 2555 // TODO: Test this for other focus modes as well, once agreement is 2556 // reached on which ones it should apply to 2557 if (!Parameters.FOCUS_MODE_AUTO.equals(focusMode) ) { 2558 continue; 2559 } 2560 2561 parameters.setFocusMode(focusMode); 2562 mCamera.setParameters(parameters); 2563 2564 // Verify that autoFocus does not change the lock 2565 set3ALockState(false, type); 2566 mCamera.autoFocus(mAutoFocusCallback); 2567 assert3ALockState("Lock was set by autoFocus in mode: " + focusMode, type, false); 2568 assertTrue(waitForFocusDone()); 2569 assert3ALockState("Lock was set by autoFocus in mode: " + focusMode, type, false); 2570 2571 // Verify that cancelAutoFocus does not change the lock 2572 mCamera.cancelAutoFocus(); 2573 assert3ALockState("Lock was set by cancelAutoFocus!", type, false); 2574 2575 // Verify that autoFocus does not change the lock 2576 set3ALockState(true, type); 2577 mCamera.autoFocus(mAutoFocusCallback); 2578 assert3ALockState("Lock was cleared by autoFocus in mode: " + focusMode, type, true); 2579 assertTrue(waitForFocusDone()); 2580 assert3ALockState("Lock was cleared by autoFocus in mode: " + focusMode, type, true); 2581 2582 // Verify that cancelAutoFocus does not change the lock 2583 mCamera.cancelAutoFocus(); 2584 assert3ALockState("Lock was cleared by cancelAutoFocus!", type, true); 2585 } 2586 mCamera.stopPreview(); 2587 } 2588 2589 private void testLockAdditionalAE() { 2590 // Verify that exposure compensation can be used while 2591 // AE lock is active 2592 mCamera.startPreview(); 2593 Parameters parameters = mCamera.getParameters(); 2594 parameters.setAutoExposureLock(true); 2595 mCamera.setParameters(parameters); 2596 parameters.setExposureCompensation(parameters.getMaxExposureCompensation()); 2597 mCamera.setParameters(parameters); 2598 parameters = mCamera.getParameters(); 2599 assertTrue("Could not adjust exposure compensation with AE locked!", 2600 parameters.getExposureCompensation() == 2601 parameters.getMaxExposureCompensation() ); 2602 2603 parameters.setExposureCompensation(parameters.getMinExposureCompensation()); 2604 mCamera.setParameters(parameters); 2605 parameters = mCamera.getParameters(); 2606 assertTrue("Could not adjust exposure compensation with AE locked!", 2607 parameters.getExposureCompensation() == 2608 parameters.getMinExposureCompensation() ); 2609 mCamera.stopPreview(); 2610 } 2611 2612 private void testLockAdditionalAWB() { 2613 // Verify that switching AWB modes clears AWB lock 2614 mCamera.startPreview(); 2615 Parameters parameters = mCamera.getParameters(); 2616 String firstWb = null; 2617 for ( String wbMode: parameters.getSupportedWhiteBalance() ) { 2618 if (firstWb == null) { 2619 firstWb = wbMode; 2620 } 2621 parameters.setWhiteBalance(firstWb); 2622 mCamera.setParameters(parameters); 2623 parameters.setAutoWhiteBalanceLock(true); 2624 mCamera.setParameters(parameters); 2625 2626 parameters.setWhiteBalance(wbMode); 2627 mCamera.setParameters(parameters); 2628 2629 if (firstWb == wbMode) { 2630 assert3ALockState("AWB lock was cleared when WB mode was unchanged!", 2631 AUTOWHITEBALANCE_LOCK, true); 2632 } else { 2633 assert3ALockState("Changing WB mode did not clear AWB lock!", 2634 AUTOWHITEBALANCE_LOCK, false); 2635 } 2636 } 2637 mCamera.stopPreview(); 2638 } 2639 2640 private void testLockInteractions() { 2641 // Verify that toggling AE does not change AWB lock state 2642 set3ALockState(false, AUTOWHITEBALANCE_LOCK); 2643 set3ALockState(false, AUTOEXPOSURE_LOCK); 2644 2645 set3ALockState(true, AUTOEXPOSURE_LOCK); 2646 assert3ALockState("Changing AE lock affected AWB lock!", 2647 AUTOWHITEBALANCE_LOCK, false); 2648 2649 set3ALockState(false, AUTOEXPOSURE_LOCK); 2650 assert3ALockState("Changing AE lock affected AWB lock!", 2651 AUTOWHITEBALANCE_LOCK, false); 2652 2653 set3ALockState(true, AUTOWHITEBALANCE_LOCK); 2654 2655 set3ALockState(true, AUTOEXPOSURE_LOCK); 2656 assert3ALockState("Changing AE lock affected AWB lock!", 2657 AUTOWHITEBALANCE_LOCK, true); 2658 2659 set3ALockState(false, AUTOEXPOSURE_LOCK); 2660 assert3ALockState("Changing AE lock affected AWB lock!", 2661 AUTOWHITEBALANCE_LOCK, true); 2662 2663 // Verify that toggling AWB does not change AE lock state 2664 set3ALockState(false, AUTOWHITEBALANCE_LOCK); 2665 set3ALockState(false, AUTOEXPOSURE_LOCK); 2666 2667 set3ALockState(true, AUTOWHITEBALANCE_LOCK); 2668 assert3ALockState("Changing AWB lock affected AE lock!", 2669 AUTOEXPOSURE_LOCK, false); 2670 2671 set3ALockState(false, AUTOWHITEBALANCE_LOCK); 2672 assert3ALockState("Changing AWB lock affected AE lock!", 2673 AUTOEXPOSURE_LOCK, false); 2674 2675 set3ALockState(true, AUTOEXPOSURE_LOCK); 2676 2677 set3ALockState(true, AUTOWHITEBALANCE_LOCK); 2678 assert3ALockState("Changing AWB lock affected AE lock!", 2679 AUTOEXPOSURE_LOCK, true); 2680 2681 set3ALockState(false, AUTOWHITEBALANCE_LOCK); 2682 assert3ALockState("Changing AWB lock affected AE lock!", 2683 AUTOEXPOSURE_LOCK, true); 2684 } 2685 2686 private void assert3ALockState(String msg, int type, boolean state) { 2687 Parameters parameters = mCamera.getParameters(); 2688 switch (type) { 2689 case AUTOEXPOSURE_LOCK: 2690 assertTrue(msg, state == parameters.getAutoExposureLock()); 2691 break; 2692 case AUTOWHITEBALANCE_LOCK: 2693 assertTrue(msg, state == parameters.getAutoWhiteBalanceLock()); 2694 break; 2695 default: 2696 assertTrue("Unknown lock type " + type, false); 2697 break; 2698 } 2699 } 2700 2701 private void set3ALockState(boolean state, int type) { 2702 Parameters parameters = mCamera.getParameters(); 2703 switch (type) { 2704 case AUTOEXPOSURE_LOCK: 2705 parameters.setAutoExposureLock(state); 2706 break; 2707 case AUTOWHITEBALANCE_LOCK: 2708 parameters.setAutoWhiteBalanceLock(state); 2709 break; 2710 default: 2711 assertTrue("Unknown lock type "+type, false); 2712 break; 2713 } 2714 mCamera.setParameters(parameters); 2715 } 2716 2717 @UiThreadTest 2718 public void testFaceDetection() throws Exception { 2719 int nCameras = Camera.getNumberOfCameras(); 2720 for (int id = 0; id < nCameras; id++) { 2721 Log.v(TAG, "Camera id=" + id); 2722 testFaceDetectionByCamera(id); 2723 } 2724 } 2725 2726 private void testFaceDetectionByCamera(int cameraId) throws Exception { 2727 final int FACE_DETECTION_TEST_DURATION = 3000; 2728 initializeMessageLooper(cameraId); 2729 mCamera.startPreview(); 2730 Parameters parameters = mCamera.getParameters(); 2731 int maxNumOfFaces = parameters.getMaxNumDetectedFaces(); 2732 assertTrue(maxNumOfFaces >= 0); 2733 if (maxNumOfFaces == 0) { 2734 try { 2735 mCamera.startFaceDetection(); 2736 fail("Should throw an exception if face detection is not supported."); 2737 } catch (IllegalArgumentException e) { 2738 // expected 2739 } 2740 terminateMessageLooper(); 2741 return; 2742 } 2743 2744 mCamera.startFaceDetection(); 2745 try { 2746 mCamera.startFaceDetection(); 2747 fail("Starting face detection twice should throw an exception"); 2748 } catch (RuntimeException e) { 2749 // expected 2750 } 2751 FaceListener listener = new FaceListener(); 2752 mCamera.setFaceDetectionListener(listener); 2753 // Sleep some time so the camera has chances to detect faces. 2754 Thread.sleep(FACE_DETECTION_TEST_DURATION); 2755 // The face callback runs in another thread. Release the camera and stop 2756 // the looper. So we do not access the face array from two threads at 2757 // the same time. 2758 terminateMessageLooper(); 2759 2760 // Check if the optional fields are supported. 2761 boolean optionalFieldSupported = false; 2762 Face firstFace = null; 2763 for (Face[] faces: listener.mFacesArray) { 2764 for (Face face: faces) { 2765 if (face != null) firstFace = face; 2766 } 2767 } 2768 if (firstFace != null) { 2769 if (firstFace.id != -1 || firstFace.leftEye != null 2770 || firstFace.rightEye != null || firstFace.mouth != null) { 2771 optionalFieldSupported = true; 2772 } 2773 } 2774 2775 // Verify the faces array. 2776 for (Face[] faces: listener.mFacesArray) { 2777 testFaces(faces, maxNumOfFaces, optionalFieldSupported); 2778 } 2779 } 2780 2781 private class FaceListener implements FaceDetectionListener { 2782 public ArrayList<Face[]> mFacesArray = new ArrayList<Face[]>(); 2783 2784 @Override 2785 public void onFaceDetection(Face[] faces, Camera camera) { 2786 mFacesArray.add(faces); 2787 } 2788 } 2789 2790 private void testFaces(Face[] faces, int maxNumOfFaces, 2791 boolean optionalFieldSupported) { 2792 Rect bounds = new Rect(-1000, -1000, 1000, 1000); 2793 assertNotNull(faces); 2794 assertTrue(faces.length <= maxNumOfFaces); 2795 for (int i = 0; i < faces.length; i++) { 2796 Face face = faces[i]; 2797 Rect rect = face.rect; 2798 // Check the bounds. 2799 assertNotNull(rect); 2800 assertTrue(rect.width() > 0); 2801 assertTrue(rect.height() > 0); 2802 assertTrue("Coordinates out of bounds. rect=" + rect, 2803 bounds.contains(rect) || Rect.intersects(bounds, rect)); 2804 2805 // Check the score. 2806 assertTrue(face.score >= 1 && face.score <= 100); 2807 2808 // Check id, left eye, right eye, and the mouth. 2809 // Optional fields should be all valid or none of them. 2810 if (!optionalFieldSupported) { 2811 assertEquals(-1, face.id); 2812 assertNull(face.leftEye); 2813 assertNull(face.rightEye); 2814 assertNull(face.mouth); 2815 } else { 2816 assertTrue(face.id != -1); 2817 assertNotNull(face.leftEye); 2818 assertNotNull(face.rightEye); 2819 assertNotNull(face.mouth); 2820 assertTrue(bounds.contains(face.leftEye.x, face.leftEye.y)); 2821 assertTrue(bounds.contains(face.rightEye.x, face.rightEye.y)); 2822 assertTrue(bounds.contains(face.mouth.x, face.mouth.y)); 2823 // ID should be unique. 2824 if (i != faces.length - 1) { 2825 assertTrue(face.id != faces[i + 1].id); 2826 } 2827 } 2828 } 2829 } 2830 2831 @UiThreadTest 2832 public void testVideoSnapshot() throws Exception { 2833 int nCameras = Camera.getNumberOfCameras(); 2834 for (int id = 0; id < nCameras; id++) { 2835 Log.v(TAG, "Camera id=" + id); 2836 testVideoSnapshotByCamera(id); 2837 } 2838 } 2839 2840 private void testVideoSnapshotByCamera(int cameraId) throws Exception { 2841 initializeMessageLooper(cameraId); 2842 Camera.Parameters parameters = mCamera.getParameters(); 2843 if (!parameters.isVideoSnapshotSupported()) { 2844 terminateMessageLooper(); 2845 return; 2846 } 2847 2848 SurfaceHolder holder = getActivity().getSurfaceView().getHolder(); 2849 2850 // Set the preview size. 2851 CamcorderProfile profile = CamcorderProfile.get(cameraId, 2852 CamcorderProfile.QUALITY_LOW); 2853 setPreviewSizeByProfile(parameters, profile); 2854 2855 // Set the biggest picture size. 2856 Size biggestSize = mCamera.new Size(-1, -1); 2857 for (Size size: parameters.getSupportedPictureSizes()) { 2858 if (biggestSize.width < size.width) { 2859 biggestSize = size; 2860 } 2861 } 2862 parameters.setPictureSize(biggestSize.width, biggestSize.height); 2863 2864 mCamera.setParameters(parameters); 2865 mCamera.startPreview(); 2866 mCamera.unlock(); 2867 MediaRecorder recorder = new MediaRecorder(); 2868 try { 2869 recorder.setCamera(mCamera); 2870 recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 2871 recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 2872 recorder.setProfile(profile); 2873 recorder.setOutputFile("/dev/null"); 2874 recorder.setPreviewDisplay(holder.getSurface()); 2875 recorder.prepare(); 2876 recorder.start(); 2877 testTakePictureByCamera(); 2878 testJpegExifByCamera(true); 2879 testJpegThumbnailSizeByCamera(true); 2880 recorder.stop(); 2881 } finally { 2882 recorder.release(); 2883 mCamera.lock(); 2884 } 2885 terminateMessageLooper(); 2886 } 2887 } 2888