1 /* 2 * Copyright (C) 2014 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.camera2.cts; 18 19 import static android.hardware.camera2.cts.CameraTestUtils.*; 20 import static android.hardware.camera2.cts.helpers.AssertHelpers.assertArrayContains; 21 22 import android.graphics.Bitmap; 23 import android.graphics.Bitmap.Config; 24 import android.graphics.ImageFormat; 25 import android.graphics.Point; 26 import android.graphics.Rect; 27 import android.hardware.camera2.CameraCharacteristics; 28 import android.hardware.camera2.CameraDevice; 29 import android.hardware.camera2.CaptureRequest; 30 import android.hardware.camera2.CaptureResult; 31 import android.hardware.camera2.DngCreator; 32 import android.location.Location; 33 import android.location.LocationManager; 34 import android.media.ImageReader; 35 import android.util.Pair; 36 import android.util.Size; 37 import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback; 38 import android.hardware.camera2.cts.CameraTestUtils.SimpleImageReaderListener; 39 import android.hardware.camera2.cts.helpers.Camera2Focuser; 40 import android.hardware.camera2.cts.helpers.StaticMetadata; 41 import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase; 42 import android.hardware.camera2.params.MeteringRectangle; 43 import android.media.Image; 44 import android.os.ConditionVariable; 45 import android.util.Log; 46 import android.util.Range; 47 import android.util.Rational; 48 import android.view.Surface; 49 50 import com.android.ex.camera2.blocking.BlockingSessionCallback; 51 import com.android.ex.camera2.exceptions.TimeoutRuntimeException; 52 53 import java.io.ByteArrayOutputStream; 54 import java.util.ArrayList; 55 import java.util.Arrays; 56 import java.util.List; 57 58 import junit.framework.Assert; 59 60 import org.junit.runners.Parameterized; 61 import org.junit.runner.RunWith; 62 import org.junit.Test; 63 64 @RunWith(Parameterized.class) 65 public class StillCaptureTest extends Camera2SurfaceViewTestCase { 66 private static final String TAG = "StillCaptureTest"; 67 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 68 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 69 // 60 second to accommodate the possible long exposure time. 70 private static final int RELAXED_CAPTURE_IMAGE_TIMEOUT_MS = CAPTURE_IMAGE_TIMEOUT_MS + 1000; 71 private static final int MAX_REGIONS_AE_INDEX = 0; 72 private static final int MAX_REGIONS_AWB_INDEX = 1; 73 private static final int MAX_REGIONS_AF_INDEX = 2; 74 private static final int WAIT_FOR_FOCUS_DONE_TIMEOUT_MS = 6000; 75 private static final double AE_COMPENSATION_ERROR_TOLERANCE = 0.2; 76 private static final int NUM_FRAMES_WAITED = 30; 77 // 5 percent error margin for resulting metering regions 78 private static final float METERING_REGION_ERROR_PERCENT_DELTA = 0.05f; 79 // Android CDD (5.0 and newer) required number of simultenous bitmap allocations for camera 80 private static final int MAX_ALLOCATED_BITMAPS = 3; 81 82 @Override setUp()83 public void setUp() throws Exception { 84 super.setUp(); 85 } 86 87 @Override tearDown()88 public void tearDown() throws Exception { 89 super.tearDown(); 90 } 91 92 /** 93 * Test JPEG capture exif fields for each camera. 94 */ 95 @Test testJpegExif()96 public void testJpegExif() throws Exception { 97 for (int i = 0; i < mCameraIdsUnderTest.length; i++) { 98 try { 99 Log.i(TAG, "Testing JPEG exif for Camera " + mCameraIdsUnderTest[i]); 100 if (!mAllStaticInfo.get(mCameraIdsUnderTest[i]).isColorOutputSupported()) { 101 Log.i(TAG, "Camera " + mCameraIdsUnderTest[i] + 102 " does not support color outputs, skipping"); 103 continue; 104 } 105 openDevice(mCameraIdsUnderTest[i]); 106 Size maxJpegSize = mOrderedStillSizes.get(0); 107 stillExifTestByCamera(ImageFormat.JPEG, maxJpegSize); 108 } finally { 109 closeDevice(); 110 closeImageReader(); 111 } 112 } 113 } 114 115 /** 116 * Test HEIC capture exif fields for each camera. 117 */ 118 @Test testHeicExif()119 public void testHeicExif() throws Exception { 120 for (int i = 0; i < mCameraIdsUnderTest.length; i++) { 121 try { 122 Log.i(TAG, "Testing HEIC exif for Camera " + mCameraIdsUnderTest[i]); 123 if (!mAllStaticInfo.get(mCameraIdsUnderTest[i]).isColorOutputSupported()) { 124 Log.i(TAG, "Camera " + mCameraIdsUnderTest[i] + 125 " does not support color outputs, skipping"); 126 continue; 127 } 128 if (!mAllStaticInfo.get(mCameraIdsUnderTest[i]).isHeicSupported()) { 129 Log.i(TAG, "Camera " + mCameraIdsUnderTest[i] + 130 " does not support HEIC, skipping"); 131 continue; 132 } 133 134 openDevice(mCameraIdsUnderTest[i]); 135 136 // Test maximum Heic size capture 137 List<Size> orderedHeicSizes = CameraTestUtils.getSupportedHeicSizes( 138 mCameraIdsUnderTest[i], mCameraManager, null/*bound*/); 139 Size maxHeicSize = orderedHeicSizes.get(0); 140 stillExifTestByCamera(ImageFormat.HEIC, maxHeicSize); 141 142 // Test preview size Heic capture 143 Size previewSize = mOrderedPreviewSizes.get(0); 144 stillExifTestByCamera(ImageFormat.HEIC, previewSize); 145 146 } finally { 147 closeDevice(); 148 closeImageReader(); 149 } 150 } 151 } 152 153 /** 154 * Test dynamic depth capture along with preview for each camera. 155 */ 156 @Test testDynamicDepthCapture()157 public void testDynamicDepthCapture() throws Exception { 158 for (int i = 0; i < mCameraIdsUnderTest.length; i++) { 159 try { 160 Log.i(TAG, "Testing dynamic depth for Camera " + mCameraIdsUnderTest[i]); 161 if (!mAllStaticInfo.get(mCameraIdsUnderTest[i]).isColorOutputSupported()) { 162 Log.i(TAG, "Camera " + mCameraIdsUnderTest[i] + 163 " does not support color outputs, skipping"); 164 continue; 165 } 166 if (!mAllStaticInfo.get(mCameraIdsUnderTest[i]).isDepthJpegSupported()) { 167 Log.i(TAG, "Camera " + mCameraIdsUnderTest[i] + 168 " does not support dynamic depth, skipping"); 169 continue; 170 } 171 172 openDevice(mCameraIdsUnderTest[i]); 173 174 // Check the maximum supported size. 175 List<Size> orderedDepthJpegSizes = CameraTestUtils.getSortedSizesForFormat( 176 mCameraIdsUnderTest[i], mCameraManager, ImageFormat.DEPTH_JPEG, null/*bound*/); 177 Size maxDepthJpegSize = orderedDepthJpegSizes.get(0); 178 stillDynamicDepthTestByCamera(ImageFormat.DEPTH_JPEG, maxDepthJpegSize); 179 } finally { 180 closeDevice(); 181 closeImageReader(); 182 } 183 } 184 } 185 186 /** 187 * Test normal still capture sequence. 188 * <p> 189 * Preview and jpeg output streams are configured. Max still capture 190 * size is used for jpeg capture. The sequence of still capture being test 191 * is: start preview, auto focus, precapture metering (if AE is not 192 * converged), then capture jpeg. The AWB and AE are in auto modes. AF mode 193 * is CONTINUOUS_PICTURE. 194 * </p> 195 */ 196 @Test testTakePicture()197 public void testTakePicture() throws Exception{ 198 for (String id : mCameraIdsUnderTest) { 199 try { 200 Log.i(TAG, "Testing basic take picture for Camera " + id); 201 if (!mAllStaticInfo.get(id).isColorOutputSupported()) { 202 Log.i(TAG, "Camera " + id + " does not support color outputs, skipping"); 203 continue; 204 } 205 openDevice(id); 206 takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null, /*afRegions*/null); 207 } finally { 208 closeDevice(); 209 closeImageReader(); 210 } 211 } 212 } 213 214 /** 215 * Test ZSL still capture sequence. 216 * <p> 217 * Preview and jpeg output streams are configured. Max still capture 218 * size is used for jpeg capture. The sequence of still capture being test 219 * is: start preview, auto focus, precapture metering (if AE is not 220 * converged), then capture jpeg. The AWB and AE are in auto modes. AF mode 221 * is CONTINUOUS_PICTURE. Same as testTakePicture, but with enableZSL set. 222 * </p> 223 */ 224 @Test testTakePictureZsl()225 public void testTakePictureZsl() throws Exception{ 226 for (String id : mCameraIdsUnderTest) { 227 try { 228 Log.i(TAG, "Testing basic ZSL take picture for Camera " + id); 229 if (!mAllStaticInfo.get(id).isColorOutputSupported()) { 230 Log.i(TAG, "Camera " + id + " does not support color outputs, skipping"); 231 continue; 232 } 233 openDevice(id); 234 CaptureRequest.Builder stillRequest = 235 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 236 stillRequest.set(CaptureRequest.CONTROL_ENABLE_ZSL, true); 237 takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null, /*afRegions*/null, 238 /*addAeTriggerCancel*/false, /*allocateBitmap*/false, 239 /*previewRequest*/null, stillRequest); 240 } finally { 241 closeDevice(); 242 closeImageReader(); 243 } 244 } 245 } 246 247 /** 248 * Test basic Raw capture. Raw buffer avaiablility is checked, but raw buffer data is not. 249 */ 250 @Test testBasicRawCapture()251 public void testBasicRawCapture() throws Exception { 252 for (int i = 0; i < mCameraIdsUnderTest.length; i++) { 253 try { 254 Log.i(TAG, "Testing raw capture for Camera " + mCameraIdsUnderTest[i]); 255 256 if (!mAllStaticInfo.get(mCameraIdsUnderTest[i]).isCapabilitySupported( 257 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) { 258 Log.i(TAG, "RAW capability is not supported in camera " + mCameraIdsUnderTest[i] + 259 ". Skip the test."); 260 continue; 261 } 262 263 openDevice(mCameraIdsUnderTest[i]); 264 rawCaptureTestByCamera(/*stillRequest*/null); 265 } finally { 266 closeDevice(); 267 closeImageReader(); 268 } 269 } 270 } 271 272 /** 273 * Test basic Raw ZSL capture. Raw buffer avaiablility is checked, but raw buffer data is not. 274 */ 275 @Test testBasicRawZslCapture()276 public void testBasicRawZslCapture() throws Exception { 277 for (int i = 0; i < mCameraIdsUnderTest.length; i++) { 278 try { 279 Log.i(TAG, "Testing raw ZSL capture for Camera " + mCameraIdsUnderTest[i]); 280 281 if (!mAllStaticInfo.get(mCameraIdsUnderTest[i]).isCapabilitySupported( 282 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) { 283 Log.i(TAG, "RAW capability is not supported in camera " + mCameraIdsUnderTest[i] + 284 ". Skip the test."); 285 continue; 286 } 287 openDevice(mCameraIdsUnderTest[i]); 288 CaptureRequest.Builder stillRequest = 289 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 290 stillRequest.set(CaptureRequest.CONTROL_ENABLE_ZSL, true); 291 rawCaptureTestByCamera(stillRequest); 292 } finally { 293 closeDevice(); 294 closeImageReader(); 295 } 296 } 297 } 298 299 300 /** 301 * Test the full raw capture use case. 302 * 303 * This includes: 304 * - Configuring the camera with a preview, jpeg, and raw output stream. 305 * - Running preview until AE/AF can settle. 306 * - Capturing with a request targeting all three output streams. 307 */ 308 @Test testFullRawCapture()309 public void testFullRawCapture() throws Exception { 310 for (int i = 0; i < mCameraIdsUnderTest.length; i++) { 311 try { 312 Log.i(TAG, "Testing raw+JPEG capture for Camera " + mCameraIdsUnderTest[i]); 313 if (!mAllStaticInfo.get(mCameraIdsUnderTest[i]).isCapabilitySupported( 314 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) { 315 Log.i(TAG, "RAW capability is not supported in camera " + mCameraIdsUnderTest[i] + 316 ". Skip the test."); 317 continue; 318 } 319 320 openDevice(mCameraIdsUnderTest[i]); 321 fullRawCaptureTestByCamera(/*stillRequest*/null); 322 } finally { 323 closeDevice(); 324 closeImageReader(); 325 } 326 } 327 } 328 329 /** 330 * Test the full raw capture ZSL use case. 331 * 332 * This includes: 333 * - Configuring the camera with a preview, jpeg, and raw output stream. 334 * - Running preview until AE/AF can settle. 335 * - Capturing with a request targeting all three output streams. 336 */ 337 @Test testFullRawZSLCapture()338 public void testFullRawZSLCapture() throws Exception { 339 for (int i = 0; i < mCameraIdsUnderTest.length; i++) { 340 try { 341 Log.i(TAG, "Testing raw+JPEG ZSL capture for Camera " + mCameraIdsUnderTest[i]); 342 if (!mAllStaticInfo.get(mCameraIdsUnderTest[i]).isCapabilitySupported( 343 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) { 344 Log.i(TAG, "RAW capability is not supported in camera " + mCameraIdsUnderTest[i] + 345 ". Skip the test."); 346 continue; 347 } 348 openDevice(mCameraIdsUnderTest[i]); 349 CaptureRequest.Builder stillRequest = 350 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 351 stillRequest.set(CaptureRequest.CONTROL_ENABLE_ZSL, true); 352 fullRawCaptureTestByCamera(stillRequest); 353 } finally { 354 closeDevice(); 355 closeImageReader(); 356 } 357 } 358 } 359 360 /** 361 * Test touch for focus. 362 * <p> 363 * AF is in CAF mode when preview is started, test uses several pre-selected 364 * regions to simulate touches. Active scan is triggered to make sure the AF 365 * converges in reasonable time. 366 * </p> 367 */ 368 @Test testTouchForFocus()369 public void testTouchForFocus() throws Exception { 370 for (String id : mCameraIdsUnderTest) { 371 try { 372 Log.i(TAG, "Testing touch for focus for Camera " + id); 373 StaticMetadata staticInfo = mAllStaticInfo.get(id); 374 int maxAfRegions = staticInfo.getAfMaxRegionsChecked(); 375 if (!(staticInfo.hasFocuser() && maxAfRegions > 0)) { 376 continue; 377 } 378 // TODO: Relax test to use non-SurfaceView output for depth cases 379 if (!staticInfo.isColorOutputSupported()) { 380 Log.i(TAG, "Camera " + id + " does not support color outputs, skipping"); 381 continue; 382 } 383 openDevice(id); 384 touchForFocusTestByCamera(); 385 } finally { 386 closeDevice(); 387 closeImageReader(); 388 } 389 } 390 } 391 392 /** 393 * Test all combination of available preview sizes and still sizes. 394 * <p> 395 * For each still capture, Only the jpeg buffer is validated, capture 396 * result validation is covered by {@link #stillExifTestByCamera} test. 397 * </p> 398 */ 399 @Test(timeout=60*60*1000) // timeout = 60 mins for long running tests testStillPreviewCombination()400 public void testStillPreviewCombination() throws Exception { 401 for (String id : mCameraIdsUnderTest) { 402 try { 403 Log.i(TAG, "Testing Still preview capture combination for Camera " + id); 404 if (!mAllStaticInfo.get(id).isColorOutputSupported()) { 405 Log.i(TAG, "Camera " + id + " does not support color outputs, skipping"); 406 continue; 407 } 408 openDevice(id); 409 previewStillCombinationTestByCamera(); 410 } finally { 411 closeDevice(); 412 closeImageReader(); 413 } 414 } 415 } 416 417 /** 418 * Test AE compensation. 419 * <p> 420 * For each integer EV compensation setting: retrieve the exposure value (exposure time * 421 * sensitivity) with or without compensation, verify if the exposure value is legal (conformed 422 * to what static info has) and the ratio between two exposure values matches EV compensation 423 * setting. Also test for the behavior that exposure settings should be changed when AE 424 * compensation settings is changed, even when AE lock is ON. 425 * </p> 426 */ 427 @Test testAeCompensation()428 public void testAeCompensation() throws Exception { 429 for (String id : mCameraIdsUnderTest) { 430 try { 431 Log.i(TAG, "Testing AE compensation for Camera " + id); 432 433 StaticMetadata staticInfo = mAllStaticInfo.get(id); 434 if (staticInfo.isHardwareLevelLegacy()) { 435 Log.i(TAG, "Skipping test on legacy devices"); 436 continue; 437 } 438 if (!staticInfo.isColorOutputSupported()) { 439 Log.i(TAG, "Camera " + id + " does not support color outputs, skipping"); 440 continue; 441 } 442 openDevice(id); 443 aeCompensationTestByCamera(); 444 } finally { 445 closeDevice(); 446 closeImageReader(); 447 } 448 } 449 } 450 451 /** 452 * Test Ae region for still capture. 453 */ 454 @Test testAeRegions()455 public void testAeRegions() throws Exception { 456 for (String id : mCameraIdsUnderTest) { 457 try { 458 Log.i(TAG, "Testing AE regions for Camera " + id); 459 openDevice(id); 460 461 boolean aeRegionsSupported = isRegionsSupportedFor3A(MAX_REGIONS_AE_INDEX); 462 if (!aeRegionsSupported) { 463 continue; 464 } 465 466 ArrayList<MeteringRectangle[]> aeRegionTestCases = get3ARegionTestCasesForCamera(); 467 for (MeteringRectangle[] aeRegions : aeRegionTestCases) { 468 takePictureTestByCamera(aeRegions, /*awbRegions*/null, /*afRegions*/null); 469 } 470 } finally { 471 closeDevice(); 472 closeImageReader(); 473 } 474 } 475 } 476 477 /** 478 * Test AWB region for still capture. 479 */ 480 @Test testAwbRegions()481 public void testAwbRegions() throws Exception { 482 for (String id : mCameraIdsUnderTest) { 483 try { 484 Log.i(TAG, "Testing AE regions for Camera " + id); 485 openDevice(id); 486 487 boolean awbRegionsSupported = isRegionsSupportedFor3A(MAX_REGIONS_AWB_INDEX); 488 if (!awbRegionsSupported) { 489 continue; 490 } 491 492 ArrayList<MeteringRectangle[]> awbRegionTestCases = get3ARegionTestCasesForCamera(); 493 for (MeteringRectangle[] awbRegions : awbRegionTestCases) { 494 takePictureTestByCamera(/*aeRegions*/null, awbRegions, /*afRegions*/null); 495 } 496 } finally { 497 closeDevice(); 498 closeImageReader(); 499 } 500 } 501 } 502 503 /** 504 * Test Af region for still capture. 505 */ 506 @Test testAfRegions()507 public void testAfRegions() throws Exception { 508 for (String id : mCameraIdsUnderTest) { 509 try { 510 Log.i(TAG, "Testing AF regions for Camera " + id); 511 openDevice(id); 512 513 boolean afRegionsSupported = isRegionsSupportedFor3A(MAX_REGIONS_AF_INDEX); 514 if (!afRegionsSupported) { 515 continue; 516 } 517 518 ArrayList<MeteringRectangle[]> afRegionTestCases = get3ARegionTestCasesForCamera(); 519 for (MeteringRectangle[] afRegions : afRegionTestCases) { 520 takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null, afRegions); 521 } 522 } finally { 523 closeDevice(); 524 closeImageReader(); 525 } 526 } 527 } 528 529 /** 530 * Test preview is still running after a still request 531 */ 532 @Test testPreviewPersistence()533 public void testPreviewPersistence() throws Exception { 534 for (String id : mCameraIdsUnderTest) { 535 try { 536 Log.i(TAG, "Testing preview persistence for Camera " + id); 537 if (!mAllStaticInfo.get(id).isColorOutputSupported()) { 538 Log.i(TAG, "Camera " + id + " does not support color outputs, skipping"); 539 continue; 540 } 541 openDevice(id); 542 previewPersistenceTestByCamera(); 543 } finally { 544 closeDevice(); 545 closeImageReader(); 546 } 547 } 548 } 549 550 @Test testAePrecaptureTriggerCancelJpegCapture()551 public void testAePrecaptureTriggerCancelJpegCapture() throws Exception { 552 for (String id : mCameraIdsUnderTest) { 553 try { 554 Log.i(TAG, "Testing AE precapture cancel for jpeg capture for Camera " + id); 555 556 StaticMetadata staticInfo = mAllStaticInfo.get(id); 557 // Legacy device doesn't support AE precapture trigger 558 if (staticInfo.isHardwareLevelLegacy()) { 559 Log.i(TAG, "Skipping AE precapture trigger cancel test on legacy devices"); 560 continue; 561 } 562 if (!staticInfo.isColorOutputSupported()) { 563 Log.i(TAG, "Camera " + id + " does not support color outputs, skipping"); 564 continue; 565 } 566 openDevice(id); 567 takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null, /*afRegions*/null, 568 /*addAeTriggerCancel*/true, /*allocateBitmap*/false, 569 /*previewRequest*/null, /*stillRequest*/null); 570 } finally { 571 closeDevice(); 572 closeImageReader(); 573 } 574 } 575 } 576 577 /** 578 * Test allocate some bitmaps while taking picture. 579 * <p> 580 * Per android CDD (5.0 and newer), android devices should support allocation of at least 3 581 * bitmaps equal to the size of the images produced by the largest resolution camera sensor on 582 * the devices. 583 * </p> 584 */ 585 @Test testAllocateBitmap()586 public void testAllocateBitmap() throws Exception { 587 for (String id : mCameraIdsUnderTest) { 588 try { 589 Log.i(TAG, "Testing bitmap allocations for Camera " + id); 590 if (!mAllStaticInfo.get(id).isColorOutputSupported()) { 591 Log.i(TAG, "Camera " + id + " does not support color outputs, skipping"); 592 continue; 593 } 594 openDevice(id); 595 takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null, /*afRegions*/null, 596 /*addAeTriggerCancel*/false, /*allocateBitmap*/true, 597 /*previewRequest*/null, /*stillRequest*/null); 598 } finally { 599 closeDevice(); 600 closeImageReader(); 601 } 602 } 603 604 } 605 606 /** 607 * Test focal length controls. 608 */ 609 @Test testFocalLengths()610 public void testFocalLengths() throws Exception { 611 for (String id : mCameraIdsUnderTest) { 612 try { 613 StaticMetadata staticInfo = mAllStaticInfo.get(id); 614 if (staticInfo.isHardwareLevelLegacy()) { 615 Log.i(TAG, "Camera " + id + " is legacy, skipping"); 616 continue; 617 } 618 if (!staticInfo.isColorOutputSupported()) { 619 Log.i(TAG, "Camera " + id + " does not support color outputs, skipping"); 620 continue; 621 } 622 if (staticInfo.isExternalCamera()) { 623 Log.i(TAG, "Camera " + id + " is external, skipping"); 624 continue; 625 } 626 openDevice(id); 627 focalLengthTestByCamera(); 628 } finally { 629 closeDevice(); 630 closeImageReader(); 631 } 632 } 633 } 634 focalLengthTestByCamera()635 private void focalLengthTestByCamera() throws Exception { 636 float[] focalLengths = mStaticInfo.getAvailableFocalLengthsChecked(); 637 int numStillCaptures = focalLengths.length; 638 639 Size maxStillSz = mOrderedStillSizes.get(0); 640 Size maxPreviewSz = mOrderedPreviewSizes.get(0); 641 SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); 642 SimpleImageReaderListener imageListener = new SimpleImageReaderListener(); 643 CaptureRequest.Builder previewRequest = 644 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 645 CaptureRequest.Builder stillRequest = 646 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 647 Size thumbnailSize = new Size(0, 0); 648 Location sTestLocation = new Location(LocationManager.GPS_PROVIDER); 649 sTestLocation.setTime(1199145600000L); 650 sTestLocation.setLatitude(37.736071); 651 sTestLocation.setLongitude(-122.441983); 652 sTestLocation.setAltitude(21.0); 653 ExifTestData exifTestData = new ExifTestData( 654 /* gpsLocation */ sTestLocation, 655 /* orientation */ 0, 656 /* jpgQuality */ (byte) 80, 657 /* thumbnailQuality */ (byte) 75); 658 setJpegKeys(stillRequest, exifTestData, thumbnailSize, mCollector); 659 CaptureResult result; 660 661 // Set the max number of images to number of focal lengths supported 662 prepareStillCaptureAndStartPreview(previewRequest, stillRequest, maxPreviewSz, 663 maxStillSz, resultListener, focalLengths.length, imageListener, false /*isHeic*/); 664 665 for(float focalLength : focalLengths) { 666 667 previewRequest.set(CaptureRequest.LENS_FOCAL_LENGTH, focalLength); 668 mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler); 669 waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY); 670 waitForResultValue(resultListener, CaptureResult.LENS_STATE, 671 CaptureResult.LENS_STATE_STATIONARY, NUM_RESULTS_WAIT_TIMEOUT); 672 result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS); 673 mCollector.expectEquals("Focal length in preview result and request should be the same", 674 previewRequest.get(CaptureRequest.LENS_FOCAL_LENGTH), 675 result.get(CaptureResult.LENS_FOCAL_LENGTH)); 676 677 stillRequest.set(CaptureRequest.LENS_FOCAL_LENGTH, focalLength); 678 CaptureRequest request = stillRequest.build(); 679 resultListener = new SimpleCaptureCallback(); 680 mSession.capture(request, resultListener, mHandler); 681 result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS); 682 mCollector.expectEquals( 683 "Focal length in still capture result and request should be the same", 684 stillRequest.get(CaptureRequest.LENS_FOCAL_LENGTH), 685 result.get(CaptureResult.LENS_FOCAL_LENGTH)); 686 687 Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS); 688 689 validateJpegCapture(image, maxStillSz); 690 verifyJpegKeys(image, result, maxStillSz, thumbnailSize, exifTestData, 691 mStaticInfo, mCollector, mDebugFileNameBase, ImageFormat.JPEG); 692 } 693 } 694 695 696 /** 697 * Start preview,take a picture and test preview is still running after snapshot 698 */ previewPersistenceTestByCamera()699 private void previewPersistenceTestByCamera() throws Exception { 700 Size maxStillSz = mOrderedStillSizes.get(0); 701 Size maxPreviewSz = mOrderedPreviewSizes.get(0); 702 703 SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); 704 SimpleCaptureCallback stillResultListener = new SimpleCaptureCallback(); 705 SimpleImageReaderListener imageListener = new SimpleImageReaderListener(); 706 CaptureRequest.Builder previewRequest = 707 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 708 CaptureRequest.Builder stillRequest = 709 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 710 prepareStillCaptureAndStartPreview(previewRequest, stillRequest, maxPreviewSz, 711 maxStillSz, resultListener, imageListener, false /*isHeic*/); 712 713 // make sure preview is actually running 714 waitForNumResults(resultListener, NUM_FRAMES_WAITED); 715 716 // take a picture 717 CaptureRequest request = stillRequest.build(); 718 mSession.capture(request, stillResultListener, mHandler); 719 stillResultListener.getCaptureResultForRequest(request, 720 WAIT_FOR_RESULT_TIMEOUT_MS); 721 722 // validate image 723 Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS); 724 validateJpegCapture(image, maxStillSz); 725 726 // make sure preview is still running after still capture 727 waitForNumResults(resultListener, NUM_FRAMES_WAITED); 728 729 stopPreview(); 730 731 // Free image resources 732 image.close(); 733 closeImageReader(); 734 return; 735 } 736 737 /** 738 * Take a picture for a given set of 3A regions for a particular camera. 739 * <p> 740 * Before take a still capture, it triggers an auto focus and lock it first, 741 * then wait for AWB to converge and lock it, then trigger a precapture 742 * metering sequence and wait for AE converged. After capture is received, the 743 * capture result and image are validated. 744 * </p> 745 * 746 * @param aeRegions AE regions for this capture 747 * @param awbRegions AWB regions for this capture 748 * @param afRegions AF regions for this capture 749 */ takePictureTestByCamera( MeteringRectangle[] aeRegions, MeteringRectangle[] awbRegions, MeteringRectangle[] afRegions)750 private void takePictureTestByCamera( 751 MeteringRectangle[] aeRegions, MeteringRectangle[] awbRegions, 752 MeteringRectangle[] afRegions) throws Exception { 753 takePictureTestByCamera(aeRegions, awbRegions, afRegions, 754 /*addAeTriggerCancel*/false, /*allocateBitmap*/false, 755 /*previewRequest*/null, /*stillRequest*/null); 756 } 757 758 /** 759 * Take a picture for a given set of 3A regions for a particular camera. 760 * <p> 761 * Before take a still capture, it triggers an auto focus and lock it first, 762 * then wait for AWB to converge and lock it, then trigger a precapture 763 * metering sequence and wait for AE converged. After capture is received, the 764 * capture result and image are validated. If {@code addAeTriggerCancel} is true, 765 * a precapture trigger cancel will be inserted between two adjacent triggers, which 766 * should effective cancel the first trigger. 767 * </p> 768 * 769 * @param aeRegions AE regions for this capture 770 * @param awbRegions AWB regions for this capture 771 * @param afRegions AF regions for this capture 772 * @param addAeTriggerCancel If a AE precapture trigger cancel is sent after the trigger. 773 * @param allocateBitmap If a set of bitmaps are allocated during the test for memory test. 774 * @param previewRequest The preview request builder to use, or null to use the default 775 * @param stillRequest The still capture request to use, or null to use the default 776 */ takePictureTestByCamera( MeteringRectangle[] aeRegions, MeteringRectangle[] awbRegions, MeteringRectangle[] afRegions, boolean addAeTriggerCancel, boolean allocateBitmap, CaptureRequest.Builder previewRequest, CaptureRequest.Builder stillRequest)777 private void takePictureTestByCamera( 778 MeteringRectangle[] aeRegions, MeteringRectangle[] awbRegions, 779 MeteringRectangle[] afRegions, boolean addAeTriggerCancel, boolean allocateBitmap, 780 CaptureRequest.Builder previewRequest, CaptureRequest.Builder stillRequest) 781 throws Exception { 782 783 boolean hasFocuser = mStaticInfo.hasFocuser(); 784 785 Size maxStillSz = mOrderedStillSizes.get(0); 786 Size maxPreviewSz = mOrderedPreviewSizes.get(0); 787 CaptureResult result; 788 SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); 789 SimpleImageReaderListener imageListener = new SimpleImageReaderListener(); 790 if (previewRequest == null) { 791 previewRequest = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 792 } 793 if (stillRequest == null) { 794 stillRequest = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 795 } 796 prepareStillCaptureAndStartPreview(previewRequest, stillRequest, maxPreviewSz, 797 maxStillSz, resultListener, imageListener, false /*isHeic*/); 798 799 // Set AE mode to ON_AUTO_FLASH if flash is available. 800 if (mStaticInfo.hasFlash()) { 801 previewRequest.set(CaptureRequest.CONTROL_AE_MODE, 802 CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); 803 stillRequest.set(CaptureRequest.CONTROL_AE_MODE, 804 CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); 805 } 806 807 Camera2Focuser focuser = null; 808 /** 809 * Step 1: trigger an auto focus run, and wait for AF locked. 810 */ 811 boolean canSetAfRegion = hasFocuser && (afRegions != null) && 812 isRegionsSupportedFor3A(MAX_REGIONS_AF_INDEX); 813 if (hasFocuser) { 814 SimpleAutoFocusListener afListener = new SimpleAutoFocusListener(); 815 focuser = new Camera2Focuser(mCamera, mSession, mPreviewSurface, afListener, 816 mStaticInfo.getCharacteristics(), mHandler); 817 if (canSetAfRegion) { 818 previewRequest.set(CaptureRequest.CONTROL_AF_REGIONS, afRegions); 819 stillRequest.set(CaptureRequest.CONTROL_AF_REGIONS, afRegions); 820 } 821 focuser.startAutoFocus(afRegions); 822 afListener.waitForAutoFocusDone(WAIT_FOR_FOCUS_DONE_TIMEOUT_MS); 823 } 824 825 /** 826 * Have to get the current AF mode to be used for other 3A repeating 827 * request, otherwise, the new AF mode in AE/AWB request could be 828 * different with existing repeating requests being sent by focuser, 829 * then it could make AF unlocked too early. Beside that, for still 830 * capture, AF mode must not be different with the one in current 831 * repeating request, otherwise, the still capture itself would trigger 832 * an AF mode change, and the AF lock would be lost for this capture. 833 */ 834 int currentAfMode = CaptureRequest.CONTROL_AF_MODE_OFF; 835 if (hasFocuser) { 836 currentAfMode = focuser.getCurrentAfMode(); 837 } 838 previewRequest.set(CaptureRequest.CONTROL_AF_MODE, currentAfMode); 839 stillRequest.set(CaptureRequest.CONTROL_AF_MODE, currentAfMode); 840 841 /** 842 * Step 2: AF is already locked, wait for AWB converged, then lock it. 843 */ 844 resultListener = new SimpleCaptureCallback(); 845 boolean canSetAwbRegion = 846 (awbRegions != null) && isRegionsSupportedFor3A(MAX_REGIONS_AWB_INDEX); 847 if (canSetAwbRegion) { 848 previewRequest.set(CaptureRequest.CONTROL_AWB_REGIONS, awbRegions); 849 stillRequest.set(CaptureRequest.CONTROL_AWB_REGIONS, awbRegions); 850 } 851 mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler); 852 if (mStaticInfo.isHardwareLevelAtLeastLimited()) { 853 waitForResultValue(resultListener, CaptureResult.CONTROL_AWB_STATE, 854 CaptureResult.CONTROL_AWB_STATE_CONVERGED, NUM_RESULTS_WAIT_TIMEOUT); 855 } else { 856 // LEGACY Devices don't have the AWB_STATE reported in results, so just wait 857 waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY); 858 } 859 boolean canSetAwbLock = mStaticInfo.isAwbLockSupported(); 860 if (canSetAwbLock) { 861 previewRequest.set(CaptureRequest.CONTROL_AWB_LOCK, true); 862 } 863 mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler); 864 // Validate the next result immediately for region and mode. 865 result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS); 866 mCollector.expectEquals("AWB mode in result and request should be same", 867 previewRequest.get(CaptureRequest.CONTROL_AWB_MODE), 868 result.get(CaptureResult.CONTROL_AWB_MODE)); 869 if (canSetAwbRegion) { 870 MeteringRectangle[] resultAwbRegions = 871 getValueNotNull(result, CaptureResult.CONTROL_AWB_REGIONS); 872 mCollector.expectEquals("AWB regions in result and request should be same", 873 awbRegions, resultAwbRegions); 874 } 875 876 /** 877 * Step 3: trigger an AE precapture metering sequence and wait for AE converged. 878 */ 879 resultListener = new SimpleCaptureCallback(); 880 boolean canSetAeRegion = 881 (aeRegions != null) && isRegionsSupportedFor3A(MAX_REGIONS_AE_INDEX); 882 if (canSetAeRegion) { 883 previewRequest.set(CaptureRequest.CONTROL_AE_REGIONS, aeRegions); 884 stillRequest.set(CaptureRequest.CONTROL_AE_REGIONS, aeRegions); 885 } 886 mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler); 887 previewRequest.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, 888 CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START); 889 mSession.capture(previewRequest.build(), resultListener, mHandler); 890 if (addAeTriggerCancel) { 891 // Cancel the current precapture trigger, then send another trigger. 892 // The camera device should behave as if the first trigger is not sent. 893 // Wait one request to make the trigger start doing something before cancel. 894 waitForNumResults(resultListener, /*numResultsWait*/ 1); 895 previewRequest.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, 896 CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL); 897 mSession.capture(previewRequest.build(), resultListener, mHandler); 898 waitForResultValue(resultListener, CaptureResult.CONTROL_AE_PRECAPTURE_TRIGGER, 899 CaptureResult.CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL, 900 NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY); 901 // Issue another trigger 902 previewRequest.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, 903 CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START); 904 mSession.capture(previewRequest.build(), resultListener, mHandler); 905 } 906 waitForAeStable(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY); 907 908 // Validate the next result immediately for region and mode. 909 result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS); 910 mCollector.expectEquals("AE mode in result and request should be same", 911 previewRequest.get(CaptureRequest.CONTROL_AE_MODE), 912 result.get(CaptureResult.CONTROL_AE_MODE)); 913 if (canSetAeRegion) { 914 MeteringRectangle[] resultAeRegions = 915 getValueNotNull(result, CaptureResult.CONTROL_AE_REGIONS); 916 917 mCollector.expectMeteringRegionsAreSimilar( 918 "AE regions in result and request should be similar", 919 aeRegions, 920 resultAeRegions, 921 METERING_REGION_ERROR_PERCENT_DELTA); 922 } 923 924 /** 925 * Step 4: take a picture when all 3A are in good state. 926 */ 927 resultListener = new SimpleCaptureCallback(); 928 CaptureRequest request = stillRequest.build(); 929 mSession.capture(request, resultListener, mHandler); 930 // Validate the next result immediately for region and mode. 931 result = resultListener.getCaptureResultForRequest(request, WAIT_FOR_RESULT_TIMEOUT_MS); 932 mCollector.expectEquals("AF mode in result and request should be same", 933 stillRequest.get(CaptureRequest.CONTROL_AF_MODE), 934 result.get(CaptureResult.CONTROL_AF_MODE)); 935 if (canSetAfRegion) { 936 MeteringRectangle[] resultAfRegions = 937 getValueNotNull(result, CaptureResult.CONTROL_AF_REGIONS); 938 mCollector.expectMeteringRegionsAreSimilar( 939 "AF regions in result and request should be similar", 940 afRegions, 941 resultAfRegions, 942 METERING_REGION_ERROR_PERCENT_DELTA); 943 } 944 945 if (hasFocuser) { 946 // Unlock auto focus. 947 focuser.cancelAutoFocus(); 948 } 949 950 // validate image 951 Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS); 952 validateJpegCapture(image, maxStillSz); 953 // Test if the system can allocate 3 bitmap successfully, per android CDD camera memory 954 // requirements added by CDD 5.0 955 if (allocateBitmap) { 956 Bitmap bm[] = new Bitmap[MAX_ALLOCATED_BITMAPS]; 957 for (int i = 0; i < MAX_ALLOCATED_BITMAPS; i++) { 958 bm[i] = Bitmap.createBitmap( 959 maxStillSz.getWidth(), maxStillSz.getHeight(), Config.ARGB_8888); 960 assertNotNull("Created bitmap #" + i + " shouldn't be null", bm[i]); 961 } 962 } 963 964 // Free image resources 965 image.close(); 966 967 stopPreview(); 968 } 969 970 /** 971 * Test touch region for focus by camera. 972 */ touchForFocusTestByCamera()973 private void touchForFocusTestByCamera() throws Exception { 974 SimpleCaptureCallback listener = new SimpleCaptureCallback(); 975 CaptureRequest.Builder requestBuilder = 976 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 977 Size maxPreviewSz = mOrderedPreviewSizes.get(0); 978 startPreview(requestBuilder, maxPreviewSz, listener); 979 980 SimpleAutoFocusListener afListener = new SimpleAutoFocusListener(); 981 Camera2Focuser focuser = new Camera2Focuser(mCamera, mSession, mPreviewSurface, afListener, 982 mStaticInfo.getCharacteristics(), mHandler); 983 ArrayList<MeteringRectangle[]> testAfRegions = get3ARegionTestCasesForCamera(); 984 985 for (MeteringRectangle[] afRegions : testAfRegions) { 986 focuser.touchForAutoFocus(afRegions); 987 afListener.waitForAutoFocusDone(WAIT_FOR_FOCUS_DONE_TIMEOUT_MS); 988 focuser.cancelAutoFocus(); 989 } 990 } 991 previewStillCombinationTestByCamera()992 private void previewStillCombinationTestByCamera() throws Exception { 993 SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); 994 SimpleImageReaderListener imageListener = new SimpleImageReaderListener(); 995 996 Size QCIF = new Size(176, 144); 997 Size FULL_HD = new Size(1920, 1080); 998 for (Size stillSz : mOrderedStillSizes) 999 for (Size previewSz : mOrderedPreviewSizes) { 1000 if (VERBOSE) { 1001 Log.v(TAG, "Testing JPEG capture size " + stillSz.toString() 1002 + " with preview size " + previewSz.toString() + " for camera " 1003 + mCamera.getId()); 1004 } 1005 1006 // Skip testing QCIF + >FullHD combinations 1007 if (stillSz.equals(QCIF) && 1008 ((previewSz.getWidth() > FULL_HD.getWidth()) || 1009 (previewSz.getHeight() > FULL_HD.getHeight()))) { 1010 continue; 1011 } 1012 1013 if (previewSz.equals(QCIF) && 1014 ((stillSz.getWidth() > FULL_HD.getWidth()) || 1015 (stillSz.getHeight() > FULL_HD.getHeight()))) { 1016 continue; 1017 } 1018 1019 CaptureRequest.Builder previewRequest = 1020 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 1021 CaptureRequest.Builder stillRequest = 1022 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 1023 prepareStillCaptureAndStartPreview(previewRequest, stillRequest, previewSz, 1024 stillSz, resultListener, imageListener, false /*isHeic*/); 1025 mSession.capture(stillRequest.build(), resultListener, mHandler); 1026 Image image = imageListener.getImage((mStaticInfo.isHardwareLevelLegacy()) ? 1027 RELAXED_CAPTURE_IMAGE_TIMEOUT_MS : CAPTURE_IMAGE_TIMEOUT_MS); 1028 validateJpegCapture(image, stillSz); 1029 1030 // Free image resources 1031 image.close(); 1032 1033 // stopPreview must be called here to make sure next time a preview stream 1034 // is created with new size. 1035 stopPreview(); 1036 // Drain the results after each combination. Depending on the device the results 1037 // can be relatively big and could accumulate fairly quickly after many iterations. 1038 resultListener.drain(); 1039 } 1040 } 1041 1042 /** 1043 * Basic raw capture test for each camera. 1044 */ rawCaptureTestByCamera(CaptureRequest.Builder stillRequest)1045 private void rawCaptureTestByCamera(CaptureRequest.Builder stillRequest) throws Exception { 1046 Size maxPreviewSz = mOrderedPreviewSizes.get(0); 1047 Size size = mStaticInfo.getRawDimensChecked(); 1048 1049 // Prepare raw capture and start preview. 1050 CaptureRequest.Builder previewBuilder = 1051 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 1052 CaptureRequest.Builder rawBuilder = (stillRequest != null) ? stillRequest : 1053 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 1054 SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); 1055 SimpleImageReaderListener imageListener = new SimpleImageReaderListener(); 1056 prepareRawCaptureAndStartPreview(previewBuilder, rawBuilder, maxPreviewSz, size, 1057 resultListener, imageListener); 1058 1059 if (VERBOSE) { 1060 Log.v(TAG, "Testing Raw capture with size " + size.toString() 1061 + ", preview size " + maxPreviewSz); 1062 } 1063 1064 CaptureRequest rawRequest = rawBuilder.build(); 1065 mSession.capture(rawRequest, resultListener, mHandler); 1066 1067 Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS); 1068 validateRaw16Image(image, size); 1069 if (DEBUG) { 1070 byte[] rawBuffer = getDataFromImage(image); 1071 String rawFileName = mDebugFileNameBase + "/test" + "_" + size.toString() + "_cam" + 1072 mCamera.getId() + ".raw16"; 1073 Log.d(TAG, "Dump raw file into " + rawFileName); 1074 dumpFile(rawFileName, rawBuffer); 1075 } 1076 1077 // Free image resources 1078 image.close(); 1079 1080 stopPreview(); 1081 } 1082 fullRawCaptureTestByCamera(CaptureRequest.Builder stillRequest)1083 private void fullRawCaptureTestByCamera(CaptureRequest.Builder stillRequest) throws Exception { 1084 Size maxPreviewSz = mOrderedPreviewSizes.get(0); 1085 Size maxStillSz = mOrderedStillSizes.get(0); 1086 1087 SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); 1088 SimpleImageReaderListener jpegListener = new SimpleImageReaderListener(); 1089 SimpleImageReaderListener rawListener = new SimpleImageReaderListener(); 1090 1091 Size size = mStaticInfo.getRawDimensChecked(); 1092 1093 if (VERBOSE) { 1094 Log.v(TAG, "Testing multi capture with size " + size.toString() 1095 + ", preview size " + maxPreviewSz); 1096 } 1097 1098 // Prepare raw capture and start preview. 1099 CaptureRequest.Builder previewBuilder = 1100 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 1101 CaptureRequest.Builder multiBuilder = (stillRequest != null) ? stillRequest : 1102 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 1103 1104 ImageReader rawReader = null; 1105 ImageReader jpegReader = null; 1106 1107 try { 1108 // Create ImageReaders. 1109 rawReader = makeImageReader(size, 1110 ImageFormat.RAW_SENSOR, MAX_READER_IMAGES, rawListener, mHandler); 1111 jpegReader = makeImageReader(maxStillSz, 1112 ImageFormat.JPEG, MAX_READER_IMAGES, jpegListener, mHandler); 1113 updatePreviewSurface(maxPreviewSz); 1114 1115 // Configure output streams with preview and jpeg streams. 1116 List<Surface> outputSurfaces = new ArrayList<Surface>(); 1117 outputSurfaces.add(rawReader.getSurface()); 1118 outputSurfaces.add(jpegReader.getSurface()); 1119 outputSurfaces.add(mPreviewSurface); 1120 mSessionListener = new BlockingSessionCallback(); 1121 mSession = configureCameraSession(mCamera, outputSurfaces, 1122 mSessionListener, mHandler); 1123 1124 // Configure the requests. 1125 previewBuilder.addTarget(mPreviewSurface); 1126 multiBuilder.addTarget(mPreviewSurface); 1127 multiBuilder.addTarget(rawReader.getSurface()); 1128 multiBuilder.addTarget(jpegReader.getSurface()); 1129 1130 // Start preview. 1131 mSession.setRepeatingRequest(previewBuilder.build(), null, mHandler); 1132 1133 // Poor man's 3A, wait 2 seconds for AE/AF (if any) to settle. 1134 // TODO: Do proper 3A trigger and lock (see testTakePictureTest). 1135 Thread.sleep(3000); 1136 1137 multiBuilder.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE, 1138 CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_ON); 1139 CaptureRequest multiRequest = multiBuilder.build(); 1140 1141 mSession.capture(multiRequest, resultListener, mHandler); 1142 1143 CaptureResult result = resultListener.getCaptureResultForRequest(multiRequest, 1144 NUM_RESULTS_WAIT_TIMEOUT); 1145 Image jpegImage = jpegListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS); 1146 basicValidateBlobImage(jpegImage, maxStillSz, ImageFormat.JPEG); 1147 Image rawImage = rawListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS); 1148 validateRaw16Image(rawImage, size); 1149 verifyRawCaptureResult(multiRequest, result); 1150 1151 1152 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 1153 try (DngCreator dngCreator = new DngCreator(mStaticInfo.getCharacteristics(), result)) { 1154 dngCreator.writeImage(outputStream, rawImage); 1155 } 1156 1157 if (DEBUG) { 1158 byte[] rawBuffer = outputStream.toByteArray(); 1159 String rawFileName = mDebugFileNameBase + "/raw16_" + TAG + size.toString() + 1160 "_cam_" + mCamera.getId() + ".dng"; 1161 Log.d(TAG, "Dump raw file into " + rawFileName); 1162 dumpFile(rawFileName, rawBuffer); 1163 1164 byte[] jpegBuffer = getDataFromImage(jpegImage); 1165 String jpegFileName = mDebugFileNameBase + "/jpeg_" + TAG + size.toString() + 1166 "_cam_" + mCamera.getId() + ".jpg"; 1167 Log.d(TAG, "Dump jpeg file into " + rawFileName); 1168 dumpFile(jpegFileName, jpegBuffer); 1169 } 1170 1171 stopPreview(); 1172 } finally { 1173 CameraTestUtils.closeImageReader(rawReader); 1174 CameraTestUtils.closeImageReader(jpegReader); 1175 rawReader = null; 1176 jpegReader = null; 1177 } 1178 } 1179 1180 /** 1181 * Validate that raw {@link CaptureResult}. 1182 * 1183 * @param rawRequest a {@link CaptureRequest} use to capture a RAW16 image. 1184 * @param rawResult the {@link CaptureResult} corresponding to the given request. 1185 */ verifyRawCaptureResult(CaptureRequest rawRequest, CaptureResult rawResult)1186 private void verifyRawCaptureResult(CaptureRequest rawRequest, CaptureResult rawResult) { 1187 assertNotNull(rawRequest); 1188 assertNotNull(rawResult); 1189 1190 if (!mStaticInfo.isMonochromeCamera()) { 1191 Rational[] empty = new Rational[] { Rational.ZERO, Rational.ZERO, Rational.ZERO}; 1192 Rational[] neutralColorPoint = mCollector.expectKeyValueNotNull("NeutralColorPoint", 1193 rawResult, CaptureResult.SENSOR_NEUTRAL_COLOR_POINT); 1194 if (neutralColorPoint != null) { 1195 mCollector.expectEquals("NeutralColorPoint length", empty.length, 1196 neutralColorPoint.length); 1197 mCollector.expectNotEquals("NeutralColorPoint cannot be all zeroes, ", empty, 1198 neutralColorPoint); 1199 mCollector.expectValuesGreaterOrEqual("NeutralColorPoint", neutralColorPoint, 1200 Rational.ZERO); 1201 } 1202 1203 mCollector.expectKeyValueGreaterOrEqual(rawResult, 1204 CaptureResult.SENSOR_GREEN_SPLIT, 0.0f); 1205 } 1206 1207 Pair<Double, Double>[] noiseProfile = mCollector.expectKeyValueNotNull("NoiseProfile", 1208 rawResult, CaptureResult.SENSOR_NOISE_PROFILE); 1209 if (noiseProfile != null) { 1210 int cfa = mStaticInfo.getCFAChecked(); 1211 int numCfaChannels = 0; 1212 switch (cfa) { 1213 case CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB: 1214 case CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG: 1215 case CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG: 1216 case CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR: 1217 numCfaChannels = 4; 1218 break; 1219 case CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO: 1220 case CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR: 1221 numCfaChannels = 1; 1222 break; 1223 default: 1224 Assert.fail("Invalid color filter arrangement " + cfa); 1225 break; 1226 } 1227 mCollector.expectEquals("NoiseProfile length", noiseProfile.length, numCfaChannels); 1228 for (Pair<Double, Double> p : noiseProfile) { 1229 mCollector.expectTrue("NoiseProfile coefficients " + p + 1230 " must have: S > 0, O >= 0", p.first > 0 && p.second >= 0); 1231 } 1232 } 1233 1234 Integer hotPixelMode = mCollector.expectKeyValueNotNull("HotPixelMode", rawResult, 1235 CaptureResult.HOT_PIXEL_MODE); 1236 Boolean hotPixelMapMode = mCollector.expectKeyValueNotNull("HotPixelMapMode", rawResult, 1237 CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE); 1238 Point[] hotPixelMap = rawResult.get(CaptureResult.STATISTICS_HOT_PIXEL_MAP); 1239 1240 Size pixelArraySize = mStaticInfo.getPixelArraySizeChecked(); 1241 boolean[] availableHotPixelMapModes = mStaticInfo.getValueFromKeyNonNull( 1242 CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES); 1243 1244 if (hotPixelMode != null) { 1245 Integer requestMode = mCollector.expectKeyValueNotNull(rawRequest, 1246 CaptureRequest.HOT_PIXEL_MODE); 1247 if (requestMode != null) { 1248 mCollector.expectKeyValueEquals(rawResult, CaptureResult.HOT_PIXEL_MODE, 1249 requestMode); 1250 } 1251 } 1252 1253 if (hotPixelMapMode != null) { 1254 Boolean requestMapMode = mCollector.expectKeyValueNotNull(rawRequest, 1255 CaptureRequest.STATISTICS_HOT_PIXEL_MAP_MODE); 1256 if (requestMapMode != null) { 1257 mCollector.expectKeyValueEquals(rawResult, 1258 CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE, requestMapMode); 1259 } 1260 1261 if (!hotPixelMapMode) { 1262 mCollector.expectTrue("HotPixelMap must be empty", hotPixelMap == null || 1263 hotPixelMap.length == 0); 1264 } else { 1265 mCollector.expectTrue("HotPixelMap must not be empty", hotPixelMap != null); 1266 mCollector.expectNotNull("AvailableHotPixelMapModes must not be null", 1267 availableHotPixelMapModes); 1268 if (availableHotPixelMapModes != null) { 1269 mCollector.expectContains("HotPixelMapMode", availableHotPixelMapModes, true); 1270 } 1271 1272 int height = pixelArraySize.getHeight(); 1273 int width = pixelArraySize.getWidth(); 1274 for (Point p : hotPixelMap) { 1275 mCollector.expectTrue("Hotpixel " + p + " must be in pixelArray " + 1276 pixelArraySize, p.x >= 0 && p.x < width && p.y >= 0 && p.y < height); 1277 } 1278 } 1279 } 1280 // TODO: profileHueSatMap, and profileToneCurve aren't supported yet. 1281 1282 } 1283 1284 /** 1285 * Issue a still capture and validate the exif information. 1286 * <p> 1287 * TODO: Differentiate full and limited device, some of the checks rely on 1288 * per frame control and synchronization, most of them don't. 1289 * </p> 1290 */ stillExifTestByCamera(int format, Size stillSize)1291 private void stillExifTestByCamera(int format, Size stillSize) throws Exception { 1292 assertTrue(format == ImageFormat.JPEG || format == ImageFormat.HEIC); 1293 boolean isHeic = (format == ImageFormat.HEIC); 1294 1295 Size maxPreviewSz = mOrderedPreviewSizes.get(0); 1296 if (VERBOSE) { 1297 Log.v(TAG, "Testing exif with size " + stillSize.toString() 1298 + ", preview size " + maxPreviewSz); 1299 } 1300 1301 // prepare capture and start preview. 1302 CaptureRequest.Builder previewBuilder = 1303 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 1304 CaptureRequest.Builder stillBuilder = 1305 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 1306 SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); 1307 SimpleImageReaderListener imageListener = new SimpleImageReaderListener(); 1308 prepareStillCaptureAndStartPreview(previewBuilder, stillBuilder, maxPreviewSz, stillSize, 1309 resultListener, imageListener, isHeic); 1310 1311 // Set the jpeg keys, then issue a capture 1312 Size[] thumbnailSizes = mStaticInfo.getAvailableThumbnailSizesChecked(); 1313 Size maxThumbnailSize = thumbnailSizes[thumbnailSizes.length - 1]; 1314 Size[] testThumbnailSizes = new Size[EXIF_TEST_DATA.length]; 1315 Arrays.fill(testThumbnailSizes, maxThumbnailSize); 1316 // Make sure thumbnail size (0, 0) is covered. 1317 testThumbnailSizes[0] = new Size(0, 0); 1318 1319 for (int i = 0; i < EXIF_TEST_DATA.length; i++) { 1320 setJpegKeys(stillBuilder, EXIF_TEST_DATA[i], testThumbnailSizes[i], mCollector); 1321 1322 // Capture a jpeg/heic image. 1323 CaptureRequest request = stillBuilder.build(); 1324 mSession.capture(request, resultListener, mHandler); 1325 CaptureResult stillResult = 1326 resultListener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT); 1327 Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS); 1328 1329 verifyJpegKeys(image, stillResult, stillSize, testThumbnailSizes[i], EXIF_TEST_DATA[i], 1330 mStaticInfo, mCollector, mDebugFileNameBase, format); 1331 1332 // Free image resources 1333 image.close(); 1334 } 1335 } 1336 1337 /** 1338 * Issue a still capture and validate the dynamic depth output. 1339 */ stillDynamicDepthTestByCamera(int format, Size stillSize)1340 private void stillDynamicDepthTestByCamera(int format, Size stillSize) throws Exception { 1341 assertTrue(format == ImageFormat.DEPTH_JPEG); 1342 1343 Size maxPreviewSz = mOrderedPreviewSizes.get(0); 1344 if (VERBOSE) { 1345 Log.v(TAG, "Testing dynamic depth with size " + stillSize.toString() 1346 + ", preview size " + maxPreviewSz); 1347 } 1348 1349 // prepare capture and start preview. 1350 CaptureRequest.Builder previewBuilder = 1351 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 1352 CaptureRequest.Builder stillBuilder = 1353 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 1354 SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); 1355 SimpleImageReaderListener imageListener = new SimpleImageReaderListener(); 1356 prepareCaptureAndStartPreview(previewBuilder, stillBuilder, maxPreviewSz, stillSize, 1357 ImageFormat.DEPTH_JPEG, resultListener, /*sessionListener*/null, 1358 MAX_READER_IMAGES, imageListener); 1359 1360 // Capture a few dynamic depth images and check whether they are valid jpegs. 1361 for (int i = 0; i < MAX_READER_IMAGES; i++) { 1362 CaptureRequest request = stillBuilder.build(); 1363 mSession.capture(request, resultListener, mHandler); 1364 CaptureResult stillResult = 1365 resultListener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT); 1366 Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS); 1367 assertNotNull("Unable to acquire next image", image); 1368 CameraTestUtils.validateImage(image, stillSize.getWidth(), stillSize.getHeight(), 1369 format, null /*filePath*/); 1370 1371 // Free image resources 1372 image.close(); 1373 } 1374 } 1375 aeCompensationTestByCamera()1376 private void aeCompensationTestByCamera() throws Exception { 1377 Range<Integer> compensationRange = mStaticInfo.getAeCompensationRangeChecked(); 1378 // Skip the test if exposure compensation is not supported. 1379 if (compensationRange.equals(Range.create(0, 0))) { 1380 return; 1381 } 1382 1383 Rational step = mStaticInfo.getAeCompensationStepChecked(); 1384 float stepF = (float) step.getNumerator() / step.getDenominator(); 1385 int stepsPerEv = (int) Math.round(1.0 / stepF); 1386 int numSteps = (compensationRange.getUpper() - compensationRange.getLower()) / stepsPerEv; 1387 1388 Size maxStillSz = mOrderedStillSizes.get(0); 1389 Size maxPreviewSz = mOrderedPreviewSizes.get(0); 1390 SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); 1391 SimpleImageReaderListener imageListener = new SimpleImageReaderListener(); 1392 CaptureRequest.Builder previewRequest = 1393 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 1394 CaptureRequest.Builder stillRequest = 1395 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 1396 boolean canSetAeLock = mStaticInfo.isAeLockSupported(); 1397 boolean canReadSensorSettings = mStaticInfo.isCapabilitySupported( 1398 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS); 1399 1400 if (canSetAeLock) { 1401 stillRequest.set(CaptureRequest.CONTROL_AE_LOCK, true); 1402 } 1403 1404 CaptureResult normalResult; 1405 CaptureResult compensatedResult; 1406 1407 boolean canReadExposureValueRange = mStaticInfo.areKeysAvailable( 1408 CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE, 1409 CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE); 1410 boolean canVerifyExposureValue = canReadSensorSettings && canReadExposureValueRange; 1411 long minExposureValue = -1; 1412 long maxExposureValuePreview = -1; 1413 long maxExposureValueStill = -1; 1414 if (canReadExposureValueRange) { 1415 // Minimum exposure settings is mostly static while maximum exposure setting depends on 1416 // frame rate range which in term depends on capture request. 1417 minExposureValue = mStaticInfo.getSensitivityMinimumOrDefault() * 1418 mStaticInfo.getExposureMinimumOrDefault() / 1000; 1419 long maxSensitivity = mStaticInfo.getSensitivityMaximumOrDefault(); 1420 long maxExposureTimeUs = mStaticInfo.getExposureMaximumOrDefault() / 1000; 1421 maxExposureValuePreview = getMaxExposureValue(previewRequest, maxExposureTimeUs, 1422 maxSensitivity); 1423 maxExposureValueStill = getMaxExposureValue(stillRequest, maxExposureTimeUs, 1424 maxSensitivity); 1425 } 1426 1427 // Set the max number of images to be same as the burst count, as the verification 1428 // could be much slower than producing rate, and we don't want to starve producer. 1429 prepareStillCaptureAndStartPreview(previewRequest, stillRequest, maxPreviewSz, 1430 maxStillSz, resultListener, numSteps, imageListener, false /*isHeic*/); 1431 1432 for (int i = 0; i <= numSteps; i++) { 1433 int exposureCompensation = i * stepsPerEv + compensationRange.getLower(); 1434 double expectedRatio = Math.pow(2.0, exposureCompensation / stepsPerEv); 1435 1436 // Wait for AE to be stabilized before capture: CONVERGED or FLASH_REQUIRED. 1437 waitForAeStable(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY); 1438 normalResult = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS); 1439 1440 long normalExposureValue = -1; 1441 if (canVerifyExposureValue) { 1442 // get and check if current exposure value is valid 1443 normalExposureValue = getExposureValue(normalResult); 1444 mCollector.expectInRange("Exposure setting out of bound", normalExposureValue, 1445 minExposureValue, maxExposureValuePreview); 1446 1447 // Only run the test if expectedExposureValue is within valid range 1448 long expectedExposureValue = (long) (normalExposureValue * expectedRatio); 1449 if (expectedExposureValue < minExposureValue || 1450 expectedExposureValue > maxExposureValueStill) { 1451 continue; 1452 } 1453 Log.v(TAG, "Expect ratio: " + expectedRatio + 1454 " normalExposureValue: " + normalExposureValue + 1455 " expectedExposureValue: " + expectedExposureValue + 1456 " minExposureValue: " + minExposureValue + 1457 " maxExposureValuePreview: " + maxExposureValuePreview + 1458 " maxExposureValueStill: " + maxExposureValueStill); 1459 } 1460 1461 // Now issue exposure compensation and wait for AE locked. AE could take a few 1462 // frames to go back to locked state 1463 previewRequest.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 1464 exposureCompensation); 1465 if (canSetAeLock) { 1466 previewRequest.set(CaptureRequest.CONTROL_AE_LOCK, true); 1467 } 1468 mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler); 1469 if (canSetAeLock) { 1470 waitForAeLocked(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY); 1471 } else { 1472 waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY); 1473 } 1474 1475 // Issue still capture 1476 if (VERBOSE) { 1477 Log.v(TAG, "Verifying capture result for ae compensation value " 1478 + exposureCompensation); 1479 } 1480 1481 stillRequest.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, exposureCompensation); 1482 CaptureRequest request = stillRequest.build(); 1483 mSession.capture(request, resultListener, mHandler); 1484 1485 compensatedResult = resultListener.getCaptureResultForRequest( 1486 request, WAIT_FOR_RESULT_TIMEOUT_MS); 1487 1488 if (canVerifyExposureValue) { 1489 // Verify the exposure value compensates as requested 1490 long compensatedExposureValue = getExposureValue(compensatedResult); 1491 mCollector.expectInRange("Exposure setting out of bound", compensatedExposureValue, 1492 minExposureValue, maxExposureValueStill); 1493 double observedRatio = (double) compensatedExposureValue / normalExposureValue; 1494 double error = observedRatio / expectedRatio; 1495 String errorString = String.format( 1496 "Exposure compensation ratio exceeds error tolerence:" + 1497 " expected(%f) observed(%f)." + 1498 " Normal exposure time %d us, sensitivity %d." + 1499 " Compensated exposure time %d us, sensitivity %d", 1500 expectedRatio, observedRatio, 1501 (int) (getValueNotNull( 1502 normalResult, CaptureResult.SENSOR_EXPOSURE_TIME) / 1000), 1503 getValueNotNull(normalResult, CaptureResult.SENSOR_SENSITIVITY), 1504 (int) (getValueNotNull( 1505 compensatedResult, CaptureResult.SENSOR_EXPOSURE_TIME) / 1000), 1506 getValueNotNull(compensatedResult, CaptureResult.SENSOR_SENSITIVITY)); 1507 mCollector.expectInRange(errorString, error, 1508 1.0 - AE_COMPENSATION_ERROR_TOLERANCE, 1509 1.0 + AE_COMPENSATION_ERROR_TOLERANCE); 1510 } 1511 1512 mCollector.expectEquals("Exposure compensation result should match requested value.", 1513 exposureCompensation, 1514 compensatedResult.get(CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION)); 1515 if (canSetAeLock) { 1516 mCollector.expectTrue("Exposure lock should be set", 1517 compensatedResult.get(CaptureResult.CONTROL_AE_LOCK)); 1518 } 1519 1520 Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS); 1521 validateJpegCapture(image, maxStillSz); 1522 image.close(); 1523 1524 // Recover AE compensation and lock 1525 previewRequest.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0); 1526 if (canSetAeLock) { 1527 previewRequest.set(CaptureRequest.CONTROL_AE_LOCK, false); 1528 } 1529 mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler); 1530 } 1531 } 1532 getExposureValue(CaptureResult result)1533 private long getExposureValue(CaptureResult result) throws Exception { 1534 int expTimeUs = (int) (getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME) / 1000); 1535 int sensitivity = getValueNotNull(result, CaptureResult.SENSOR_SENSITIVITY); 1536 Integer postRawSensitivity = result.get(CaptureResult.CONTROL_POST_RAW_SENSITIVITY_BOOST); 1537 if (postRawSensitivity != null) { 1538 return (long) sensitivity * postRawSensitivity / 100 * expTimeUs; 1539 } 1540 return (long) sensitivity * expTimeUs; 1541 } 1542 getMaxExposureValue(CaptureRequest.Builder request, long maxExposureTimeUs, long maxSensitivity)1543 private long getMaxExposureValue(CaptureRequest.Builder request, long maxExposureTimeUs, 1544 long maxSensitivity) throws Exception { 1545 Range<Integer> fpsRange = request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE); 1546 long maxFrameDurationUs = Math.round(1000000.0 / fpsRange.getLower()); 1547 long currentMaxExposureTimeUs = Math.min(maxFrameDurationUs, maxExposureTimeUs); 1548 return currentMaxExposureTimeUs * maxSensitivity; 1549 } 1550 1551 1552 //---------------------------------------------------------------- 1553 //---------Below are common functions for all tests.-------------- 1554 //---------------------------------------------------------------- 1555 /** 1556 * Validate standard raw (RAW16) capture image. 1557 * 1558 * @param image The raw16 format image captured 1559 * @param rawSize The expected raw size 1560 */ validateRaw16Image(Image image, Size rawSize)1561 private static void validateRaw16Image(Image image, Size rawSize) { 1562 CameraTestUtils.validateImage(image, rawSize.getWidth(), rawSize.getHeight(), 1563 ImageFormat.RAW_SENSOR, /*filePath*/null); 1564 } 1565 1566 /** 1567 * Validate JPEG capture image object correctness and test. 1568 * <p> 1569 * In addition to image object correctness, this function also does the decoding 1570 * test, which is slower. 1571 * </p> 1572 * 1573 * @param image The JPEG image to be verified. 1574 * @param jpegSize The JPEG capture size to be verified against. 1575 */ validateJpegCapture(Image image, Size jpegSize)1576 private static void validateJpegCapture(Image image, Size jpegSize) { 1577 CameraTestUtils.validateImage(image, jpegSize.getWidth(), jpegSize.getHeight(), 1578 ImageFormat.JPEG, /*filePath*/null); 1579 } 1580 1581 private static class SimpleAutoFocusListener implements Camera2Focuser.AutoFocusListener { 1582 final ConditionVariable focusDone = new ConditionVariable(); 1583 @Override onAutoFocusLocked(boolean success)1584 public void onAutoFocusLocked(boolean success) { 1585 focusDone.open(); 1586 } 1587 waitForAutoFocusDone(long timeoutMs)1588 public void waitForAutoFocusDone(long timeoutMs) { 1589 if (focusDone.block(timeoutMs)) { 1590 focusDone.close(); 1591 } else { 1592 throw new TimeoutRuntimeException("Wait for auto focus done timed out after " 1593 + timeoutMs + "ms"); 1594 } 1595 } 1596 } 1597 1598 /** 1599 * Get 5 3A region test cases, each with one square region in it. 1600 * The first one is at center, the other four are at corners of 1601 * active array rectangle. 1602 * 1603 * @return array of test 3A regions 1604 */ get3ARegionTestCasesForCamera()1605 private ArrayList<MeteringRectangle[]> get3ARegionTestCasesForCamera() { 1606 final int TEST_3A_REGION_NUM = 5; 1607 final int DEFAULT_REGION_WEIGHT = 30; 1608 final int DEFAULT_REGION_SCALE_RATIO = 8; 1609 ArrayList<MeteringRectangle[]> testCases = 1610 new ArrayList<MeteringRectangle[]>(TEST_3A_REGION_NUM); 1611 final Rect activeArraySize = mStaticInfo.getActiveArraySizeChecked(); 1612 int regionWidth = activeArraySize.width() / DEFAULT_REGION_SCALE_RATIO - 1; 1613 int regionHeight = activeArraySize.height() / DEFAULT_REGION_SCALE_RATIO - 1; 1614 int centerX = activeArraySize.width() / 2; 1615 int centerY = activeArraySize.height() / 2; 1616 int bottomRightX = activeArraySize.width() - 1; 1617 int bottomRightY = activeArraySize.height() - 1; 1618 1619 // Center region 1620 testCases.add( 1621 new MeteringRectangle[] { 1622 new MeteringRectangle( 1623 centerX - regionWidth / 2, // x 1624 centerY - regionHeight / 2, // y 1625 regionWidth, // width 1626 regionHeight, // height 1627 DEFAULT_REGION_WEIGHT)}); 1628 1629 // Upper left corner 1630 testCases.add( 1631 new MeteringRectangle[] { 1632 new MeteringRectangle( 1633 0, // x 1634 0, // y 1635 regionWidth, // width 1636 regionHeight, // height 1637 DEFAULT_REGION_WEIGHT)}); 1638 1639 // Upper right corner 1640 testCases.add( 1641 new MeteringRectangle[] { 1642 new MeteringRectangle( 1643 bottomRightX - regionWidth, // x 1644 0, // y 1645 regionWidth, // width 1646 regionHeight, // height 1647 DEFAULT_REGION_WEIGHT)}); 1648 1649 // Bottom left corner 1650 testCases.add( 1651 new MeteringRectangle[] { 1652 new MeteringRectangle( 1653 0, // x 1654 bottomRightY - regionHeight, // y 1655 regionWidth, // width 1656 regionHeight, // height 1657 DEFAULT_REGION_WEIGHT)}); 1658 1659 // Bottom right corner 1660 testCases.add( 1661 new MeteringRectangle[] { 1662 new MeteringRectangle( 1663 bottomRightX - regionWidth, // x 1664 bottomRightY - regionHeight, // y 1665 regionWidth, // width 1666 regionHeight, // height 1667 DEFAULT_REGION_WEIGHT)}); 1668 1669 if (VERBOSE) { 1670 StringBuilder sb = new StringBuilder(); 1671 for (MeteringRectangle[] mr : testCases) { 1672 sb.append("{"); 1673 sb.append(Arrays.toString(mr)); 1674 sb.append("}, "); 1675 } 1676 if (sb.length() > 1) 1677 sb.setLength(sb.length() - 2); // Remove the redundant comma and space at the end 1678 Log.v(TAG, "Generated test regions are: " + sb.toString()); 1679 } 1680 1681 return testCases; 1682 } 1683 isRegionsSupportedFor3A(int index)1684 private boolean isRegionsSupportedFor3A(int index) { 1685 int maxRegions = 0; 1686 switch (index) { 1687 case MAX_REGIONS_AE_INDEX: 1688 maxRegions = mStaticInfo.getAeMaxRegionsChecked(); 1689 break; 1690 case MAX_REGIONS_AWB_INDEX: 1691 maxRegions = mStaticInfo.getAwbMaxRegionsChecked(); 1692 break; 1693 case MAX_REGIONS_AF_INDEX: 1694 maxRegions = mStaticInfo.getAfMaxRegionsChecked(); 1695 break; 1696 default: 1697 throw new IllegalArgumentException("Unknown algorithm index"); 1698 } 1699 boolean isRegionsSupported = maxRegions > 0; 1700 if (index == MAX_REGIONS_AF_INDEX && isRegionsSupported) { 1701 mCollector.expectTrue( 1702 "Device reports non-zero max AF region count for a camera without focuser!", 1703 mStaticInfo.hasFocuser()); 1704 isRegionsSupported = isRegionsSupported && mStaticInfo.hasFocuser(); 1705 } 1706 1707 return isRegionsSupported; 1708 } 1709 } 1710