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