1 /* 2 * Copyright (C) 2013 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 com.android.mediaframeworktest.unit; 18 19 import android.os.Parcel; 20 import android.test.suitebuilder.annotation.SmallTest; 21 import android.graphics.Point; 22 import android.graphics.Rect; 23 import android.hardware.camera2.CameraCharacteristics; 24 import android.hardware.camera2.CaptureResult; 25 import android.hardware.camera2.Face; 26 import android.hardware.camera2.Rational; 27 import android.hardware.camera2.Size; 28 import android.hardware.camera2.impl.CameraMetadataNative; 29 30 import static android.hardware.camera2.impl.CameraMetadataNative.*; 31 32 import java.lang.reflect.Array; 33 import java.nio.ByteBuffer; 34 import java.nio.ByteOrder; 35 36 /** 37 * <pre> 38 * adb shell am instrument \ 39 * -e class 'com.android.mediaframeworktest.unit.CameraMetadataTest' \ 40 * -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner 41 * </pre> 42 */ 43 public class CameraMetadataTest extends junit.framework.TestCase { 44 45 CameraMetadataNative mMetadata; 46 Parcel mParcel; 47 48 // Sections 49 static final int ANDROID_COLOR_CORRECTION = 0; 50 static final int ANDROID_CONTROL = 1; 51 52 // Section starts 53 static final int ANDROID_COLOR_CORRECTION_START = ANDROID_COLOR_CORRECTION << 16; 54 static final int ANDROID_CONTROL_START = ANDROID_CONTROL << 16; 55 56 // Tags 57 static final int ANDROID_COLOR_CORRECTION_MODE = ANDROID_COLOR_CORRECTION_START; 58 static final int ANDROID_COLOR_CORRECTION_TRANSFORM = ANDROID_COLOR_CORRECTION_START + 1; 59 static final int ANDROID_COLOR_CORRECTION_GAINS = ANDROID_COLOR_CORRECTION_START + 2; 60 61 static final int ANDROID_CONTROL_AE_ANTIBANDING_MODE = ANDROID_CONTROL_START; 62 static final int ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION = ANDROID_CONTROL_START + 1; 63 64 @Override 65 public void setUp() { 66 mMetadata = new CameraMetadataNative(); 67 mParcel = Parcel.obtain(); 68 } 69 70 @Override 71 public void tearDown() throws Exception { 72 mMetadata = null; 73 74 mParcel.recycle(); 75 mParcel = null; 76 } 77 78 @SmallTest 79 public void testNew() { 80 assertEquals(0, mMetadata.getEntryCount()); 81 assertTrue(mMetadata.isEmpty()); 82 } 83 84 @SmallTest 85 public void testGetTagFromKey() { 86 87 // Test success 88 89 assertEquals(ANDROID_COLOR_CORRECTION_MODE, 90 CameraMetadataNative.getTag("android.colorCorrection.mode")); 91 assertEquals(ANDROID_COLOR_CORRECTION_TRANSFORM, 92 CameraMetadataNative.getTag("android.colorCorrection.transform")); 93 assertEquals(ANDROID_CONTROL_AE_ANTIBANDING_MODE, 94 CameraMetadataNative.getTag("android.control.aeAntibandingMode")); 95 assertEquals(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, 96 CameraMetadataNative.getTag("android.control.aeExposureCompensation")); 97 98 // Test failures 99 100 try { 101 CameraMetadataNative.getTag(null); 102 fail("A null key should throw NPE"); 103 } catch(NullPointerException e) { 104 } 105 106 try { 107 CameraMetadataNative.getTag("android.control"); 108 fail("A section name only should not be a valid key"); 109 } catch(IllegalArgumentException e) { 110 } 111 112 try { 113 CameraMetadataNative.getTag("android.control.thisTagNameIsFakeAndDoesNotExist"); 114 fail("A valid section with an invalid tag name should not be a valid key"); 115 } catch(IllegalArgumentException e) { 116 } 117 118 try { 119 CameraMetadataNative.getTag("android"); 120 fail("A namespace name only should not be a valid key"); 121 } catch(IllegalArgumentException e) { 122 } 123 124 try { 125 CameraMetadataNative.getTag("this.key.is.definitely.invalid"); 126 fail("A completely fake key name should not be valid"); 127 } catch(IllegalArgumentException e) { 128 } 129 } 130 131 @SmallTest 132 public void testGetTypeFromTag() { 133 assertEquals(TYPE_BYTE, CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_MODE)); 134 assertEquals(TYPE_RATIONAL, CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_TRANSFORM)); 135 assertEquals(TYPE_FLOAT, CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_GAINS)); 136 assertEquals(TYPE_BYTE, CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_ANTIBANDING_MODE)); 137 assertEquals(TYPE_INT32, 138 CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION)); 139 140 try { 141 CameraMetadataNative.getNativeType(0xDEADF00D); 142 fail("No type should exist for invalid tag 0xDEADF00D"); 143 } catch(IllegalArgumentException e) { 144 } 145 } 146 147 @SmallTest 148 public void testReadWriteValues() { 149 final byte ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY = 2; 150 byte[] valueResult; 151 152 assertEquals(0, mMetadata.getEntryCount()); 153 assertEquals(true, mMetadata.isEmpty()); 154 155 // 156 // android.colorCorrection.mode (single enum byte) 157 // 158 159 assertEquals(null, mMetadata.readValues(ANDROID_COLOR_CORRECTION_MODE)); 160 161 // Write/read null values 162 mMetadata.writeValues(ANDROID_COLOR_CORRECTION_MODE, null); 163 assertEquals(null, mMetadata.readValues(ANDROID_COLOR_CORRECTION_MODE)); 164 165 // Write 0 values 166 mMetadata.writeValues(ANDROID_COLOR_CORRECTION_MODE, new byte[] {}); 167 168 // Read 0 values 169 valueResult = mMetadata.readValues(ANDROID_COLOR_CORRECTION_MODE); 170 assertNotNull(valueResult); 171 assertEquals(0, valueResult.length); 172 173 assertEquals(1, mMetadata.getEntryCount()); 174 assertEquals(false, mMetadata.isEmpty()); 175 176 // Write 1 value 177 mMetadata.writeValues(ANDROID_COLOR_CORRECTION_MODE, new byte[] { 178 ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY 179 }); 180 181 // Read 1 value 182 valueResult = mMetadata.readValues(ANDROID_COLOR_CORRECTION_MODE); 183 assertNotNull(valueResult); 184 assertEquals(1, valueResult.length); 185 assertEquals(ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY, valueResult[0]); 186 187 assertEquals(1, mMetadata.getEntryCount()); 188 assertEquals(false, mMetadata.isEmpty()); 189 190 // 191 // android.colorCorrection.colorCorrectionGains (float x 4 array) 192 // 193 194 final float[] colorCorrectionGains = new float[] { 1.0f, 2.0f, 3.0f, 4.0f}; 195 byte[] colorCorrectionGainsAsByteArray = new byte[colorCorrectionGains.length * 4]; 196 ByteBuffer colorCorrectionGainsByteBuffer = 197 ByteBuffer.wrap(colorCorrectionGainsAsByteArray).order(ByteOrder.nativeOrder()); 198 for (float f : colorCorrectionGains) 199 colorCorrectionGainsByteBuffer.putFloat(f); 200 201 // Read 202 assertNull(mMetadata.readValues(ANDROID_COLOR_CORRECTION_GAINS)); 203 mMetadata.writeValues(ANDROID_COLOR_CORRECTION_GAINS, colorCorrectionGainsAsByteArray); 204 205 // Write 206 assertArrayEquals(colorCorrectionGainsAsByteArray, 207 mMetadata.readValues(ANDROID_COLOR_CORRECTION_GAINS)); 208 209 assertEquals(2, mMetadata.getEntryCount()); 210 assertEquals(false, mMetadata.isEmpty()); 211 212 // Erase 213 mMetadata.writeValues(ANDROID_COLOR_CORRECTION_GAINS, null); 214 assertNull(mMetadata.readValues(ANDROID_COLOR_CORRECTION_GAINS)); 215 assertEquals(1, mMetadata.getEntryCount()); 216 } 217 218 private static <T> void assertArrayEquals(T expected, T actual) { 219 assertEquals(Array.getLength(expected), Array.getLength(actual)); 220 221 int len = Array.getLength(expected); 222 for (int i = 0; i < len; ++i) { 223 assertEquals(Array.get(expected, i), Array.get(actual, i)); 224 } 225 } 226 227 private <T> void checkKeyGetAndSet(String keyStr, Class<T> type, T value) { 228 assertFalse("Use checkKeyGetAndSetArray to compare array Keys", type.isArray()); 229 230 Key<T> key = new Key<T>(keyStr, type); 231 assertNull(mMetadata.get(key)); 232 mMetadata.set(key, null); 233 assertNull(mMetadata.get(key)); 234 mMetadata.set(key, value); 235 236 T actual = mMetadata.get(key); 237 assertEquals(value, actual); 238 } 239 240 private <T> void checkKeyGetAndSetArray(String keyStr, Class<T> type, T value) { 241 assertTrue(type.isArray()); 242 243 Key<T> key = new Key<T>(keyStr, type); 244 assertNull(mMetadata.get(key)); 245 mMetadata.set(key, value); 246 assertArrayEquals(value, mMetadata.get(key)); 247 } 248 249 @SmallTest 250 public void testReadWritePrimitive() { 251 // int32 (single) 252 checkKeyGetAndSet("android.control.aeExposureCompensation", Integer.TYPE, 0xC0FFEE); 253 254 // byte (single) 255 checkKeyGetAndSet("android.flash.maxEnergy", Byte.TYPE, (byte)6); 256 257 // int64 (single) 258 checkKeyGetAndSet("android.flash.firingTime", Long.TYPE, 0xABCD12345678FFFFL); 259 260 // float (single) 261 checkKeyGetAndSet("android.lens.aperture", Float.TYPE, Float.MAX_VALUE); 262 263 // double (single) -- technically double x 3, but we fake it 264 checkKeyGetAndSet("android.jpeg.gpsCoordinates", Double.TYPE, Double.MAX_VALUE); 265 266 // rational (single) 267 checkKeyGetAndSet("android.sensor.baseGainFactor", Rational.class, new Rational(1, 2)); 268 269 /** 270 * Weirder cases, that don't map 1:1 with the native types 271 */ 272 273 // bool (single) -- with TYPE_BYTE 274 checkKeyGetAndSet("android.control.aeLock", Boolean.TYPE, true); 275 276 // integer (single) -- with TYPE_BYTE 277 checkKeyGetAndSet("android.control.aePrecaptureTrigger", Integer.TYPE, 6); 278 } 279 280 @SmallTest 281 public void testReadWritePrimitiveArray() { 282 // int32 (n) 283 checkKeyGetAndSetArray("android.sensor.info.sensitivityRange", int[].class, 284 new int[] { 285 0xC0FFEE, 0xDEADF00D 286 }); 287 288 // byte (n) 289 checkKeyGetAndSetArray("android.statistics.faceScores", byte[].class, new byte[] { 290 1, 2, 3, 4 291 }); 292 293 // int64 (n) 294 checkKeyGetAndSetArray("android.scaler.availableProcessedMinDurations", long[].class, 295 new long[] { 296 0xABCD12345678FFFFL, 0x1234ABCD5678FFFFL, 0xFFFF12345678ABCDL 297 }); 298 299 // float (n) 300 checkKeyGetAndSetArray("android.lens.info.availableApertures", float[].class, 301 new float[] { 302 Float.MAX_VALUE, Float.MIN_NORMAL, Float.MIN_VALUE 303 }); 304 305 // double (n) -- in particular double x 3 306 checkKeyGetAndSetArray("android.jpeg.gpsCoordinates", double[].class, 307 new double[] { 308 Double.MAX_VALUE, Double.MIN_NORMAL, Double.MIN_VALUE 309 }); 310 311 // rational (n) -- in particular rational x 9 312 checkKeyGetAndSetArray("android.sensor.calibrationTransform1", Rational[].class, 313 new Rational[] { 314 new Rational(1, 2), new Rational(3, 4), new Rational(5, 6), 315 new Rational(7, 8), new Rational(9, 10), new Rational(10, 11), 316 new Rational(12, 13), new Rational(14, 15), new Rational(15, 16) 317 }); 318 319 /** 320 * Weirder cases, that don't map 1:1 with the native types 321 */ 322 323 // bool (n) -- with TYPE_BYTE 324 checkKeyGetAndSetArray("android.control.aeLock", boolean[].class, new boolean[] { 325 true, false, true 326 }); 327 328 329 // integer (n) -- with TYPE_BYTE 330 checkKeyGetAndSetArray("android.control.aeAvailableModes", int[].class, new int[] { 331 1, 2, 3, 4 332 }); 333 } 334 335 private enum ColorCorrectionMode { 336 TRANSFORM_MATRIX, 337 FAST, 338 HIGH_QUALITY 339 } 340 341 private enum AeAntibandingMode { 342 OFF, 343 _50HZ, 344 _60HZ, 345 AUTO 346 } 347 348 // TODO: special values for the enum. 349 private enum AvailableFormat { 350 RAW_SENSOR, 351 YV12, 352 YCrCb_420_SP, 353 IMPLEMENTATION_DEFINED, 354 YCbCr_420_888, 355 BLOB 356 } 357 358 @SmallTest 359 public void testReadWriteEnum() { 360 // byte (single) 361 checkKeyGetAndSet("android.colorCorrection.mode", ColorCorrectionMode.class, 362 ColorCorrectionMode.HIGH_QUALITY); 363 364 // byte (single) 365 checkKeyGetAndSet("android.control.aeAntibandingMode", AeAntibandingMode.class, 366 AeAntibandingMode.AUTO); 367 368 // byte (n) 369 checkKeyGetAndSetArray("android.control.aeAvailableAntibandingModes", 370 AeAntibandingMode[].class, new AeAntibandingMode[] { 371 AeAntibandingMode.OFF, AeAntibandingMode._50HZ, AeAntibandingMode._60HZ, 372 AeAntibandingMode.AUTO 373 }); 374 375 /** 376 * Stranger cases that don't use byte enums 377 */ 378 // int (n) 379 checkKeyGetAndSetArray("android.scaler.availableFormats", AvailableFormat[].class, 380 new AvailableFormat[] { 381 AvailableFormat.RAW_SENSOR, 382 AvailableFormat.YV12, 383 AvailableFormat.IMPLEMENTATION_DEFINED, 384 AvailableFormat.YCbCr_420_888, 385 AvailableFormat.BLOB 386 }); 387 388 } 389 390 @SmallTest 391 public void testReadWriteEnumWithCustomValues() { 392 CameraMetadataNative.registerEnumValues(AeAntibandingMode.class, new int[] { 393 0, 394 10, 395 20, 396 30 397 }); 398 399 // byte (single) 400 checkKeyGetAndSet("android.control.aeAntibandingMode", AeAntibandingMode.class, 401 AeAntibandingMode.AUTO); 402 403 // byte (n) 404 checkKeyGetAndSetArray("android.control.aeAvailableAntibandingModes", 405 AeAntibandingMode[].class, new AeAntibandingMode[] { 406 AeAntibandingMode.OFF, AeAntibandingMode._50HZ, AeAntibandingMode._60HZ, 407 AeAntibandingMode.AUTO 408 }); 409 410 Key<AeAntibandingMode[]> aeAntibandingModeKey = 411 new Key<AeAntibandingMode[]>("android.control.aeAvailableAntibandingModes", 412 AeAntibandingMode[].class); 413 byte[] aeAntibandingModeValues = mMetadata.readValues(CameraMetadataNative 414 .getTag("android.control.aeAvailableAntibandingModes")); 415 byte[] expectedValues = new byte[] { 0, 10, 20, 30 }; 416 assertArrayEquals(expectedValues, aeAntibandingModeValues); 417 418 419 /** 420 * Stranger cases that don't use byte enums 421 */ 422 // int (n) 423 CameraMetadataNative.registerEnumValues(AvailableFormat.class, new int[] { 424 0x20, 425 0x32315659, 426 0x11, 427 0x22, 428 0x23, 429 0x21, 430 }); 431 432 checkKeyGetAndSetArray("android.scaler.availableFormats", AvailableFormat[].class, 433 new AvailableFormat[] { 434 AvailableFormat.RAW_SENSOR, 435 AvailableFormat.YV12, 436 AvailableFormat.IMPLEMENTATION_DEFINED, 437 AvailableFormat.YCbCr_420_888, 438 AvailableFormat.BLOB 439 }); 440 441 Key<AvailableFormat[]> availableFormatsKey = 442 new Key<AvailableFormat[]>("android.scaler.availableFormats", 443 AvailableFormat[].class); 444 byte[] availableFormatValues = mMetadata.readValues(CameraMetadataNative 445 .getTag(availableFormatsKey.getName())); 446 447 int[] expectedIntValues = new int[] { 448 0x20, 449 0x32315659, 450 0x22, 451 0x23, 452 0x21 453 }; 454 455 ByteBuffer bf = ByteBuffer.wrap(availableFormatValues).order(ByteOrder.nativeOrder()); 456 457 assertEquals(expectedIntValues.length * 4, availableFormatValues.length); 458 for (int i = 0; i < expectedIntValues.length; ++i) { 459 assertEquals(expectedIntValues[i], bf.getInt()); 460 } 461 } 462 463 @SmallTest 464 public void testReadWriteSize() { 465 // int32 x n 466 checkKeyGetAndSet("android.jpeg.thumbnailSize", Size.class, new Size(123, 456)); 467 468 // int32 x 2 x n 469 checkKeyGetAndSetArray("android.scaler.availableJpegSizes", Size[].class, new Size[] { 470 new Size(123, 456), 471 new Size(0xDEAD, 0xF00D), 472 new Size(0xF00, 0xB00) 473 }); 474 } 475 476 @SmallTest 477 public void testReadWriteRectangle() { 478 // int32 x n 479 checkKeyGetAndSet("android.scaler.cropRegion", Rect.class, new Rect(10, 11, 1280, 1024)); 480 481 // int32 x 2 x n 482 checkKeyGetAndSetArray("android.statistics.faceRectangles", Rect[].class, new Rect[] { 483 new Rect(110, 111, 11280, 11024), 484 new Rect(210, 111, 21280, 21024), 485 new Rect(310, 111, 31280, 31024) 486 }); 487 } 488 489 @SmallTest 490 public void testReadWriteString() { 491 // (byte) string 492 Key<String> gpsProcessingMethodKey = 493 new Key<String>("android.jpeg.gpsProcessingMethod", String.class); 494 495 String helloWorld = new String("HelloWorld"); 496 byte[] helloWorldBytes = new byte[] { 497 'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '\0' }; 498 499 mMetadata.set(gpsProcessingMethodKey, helloWorld); 500 501 String actual = mMetadata.get(gpsProcessingMethodKey); 502 assertEquals(helloWorld, actual); 503 504 byte[] actualBytes = mMetadata.readValues(getTag(gpsProcessingMethodKey.getName())); 505 assertArrayEquals(helloWorldBytes, actualBytes); 506 507 // Does not yet test as a string[] since we don't support that in native code. 508 509 // (byte) string 510 Key<String[]> gpsProcessingMethodKeyArray = 511 new Key<String[]>("android.jpeg.gpsProcessingMethod", String[].class); 512 513 String[] gpsStrings = new String[] { "HelloWorld", "FooBar", "Shazbot" }; 514 byte[] gpsBytes = new byte[] { 515 'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '\0', 516 'F', 'o', 'o', 'B', 'a', 'r', '\0', 517 'S', 'h', 'a', 'z', 'b', 'o', 't', '\0'}; 518 519 mMetadata.set(gpsProcessingMethodKeyArray, gpsStrings); 520 521 String[] actualArray = mMetadata.get(gpsProcessingMethodKeyArray); 522 assertArrayEquals(gpsStrings, actualArray); 523 524 byte[] actualBytes2 = mMetadata.readValues(getTag(gpsProcessingMethodKeyArray.getName())); 525 assertArrayEquals(gpsBytes, actualBytes2); 526 } 527 528 <T> void compareGeneric(T expected, T actual) { 529 assertEquals(expected, actual); 530 } 531 532 @SmallTest 533 public void testReadWriteOverride() { 534 // 535 // android.scaler.availableFormats (int x n array) 536 // 537 int[] availableFormats = new int[] { 538 0x20, // RAW_SENSOR 539 0x32315659, // YV12 540 0x11, // YCrCb_420_SP 541 0x100, // ImageFormat.JPEG 542 0x22, // IMPLEMENTATION_DEFINED 543 0x23, // YCbCr_420_888 544 }; 545 int[] expectedIntValues = new int[] { 546 0x20, // RAW_SENSOR 547 0x32315659, // YV12 548 0x11, // YCrCb_420_SP 549 0x21, // BLOB 550 0x22, // IMPLEMENTATION_DEFINED 551 0x23, // YCbCr_420_888 552 }; 553 int availableFormatTag = CameraMetadataNative.getTag("android.scaler.availableFormats"); 554 555 // Write 556 mMetadata.set(CameraCharacteristics.SCALER_AVAILABLE_FORMATS, availableFormats); 557 558 byte[] availableFormatValues = mMetadata.readValues(availableFormatTag); 559 560 ByteBuffer bf = ByteBuffer.wrap(availableFormatValues).order(ByteOrder.nativeOrder()); 561 562 assertEquals(expectedIntValues.length * 4, availableFormatValues.length); 563 for (int i = 0; i < expectedIntValues.length; ++i) { 564 assertEquals(expectedIntValues[i], bf.getInt()); 565 } 566 // Read 567 byte[] availableFormatsAsByteArray = new byte[expectedIntValues.length * 4]; 568 ByteBuffer availableFormatsByteBuffer = 569 ByteBuffer.wrap(availableFormatsAsByteArray).order(ByteOrder.nativeOrder()); 570 for (int value : expectedIntValues) { 571 availableFormatsByteBuffer.putInt(value); 572 } 573 mMetadata.writeValues(availableFormatTag, availableFormatsAsByteArray); 574 575 int[] resultFormats = mMetadata.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS); 576 assertNotNull("result available formats shouldn't be null", resultFormats); 577 assertArrayEquals(availableFormats, resultFormats); 578 579 // 580 // android.statistics.faces (Face x n array) 581 // 582 int[] expectedFaceIds = new int[] {1, 2, 3, 4, 5}; 583 byte[] expectedFaceScores = new byte[] {10, 20, 30, 40, 50}; 584 int numFaces = expectedFaceIds.length; 585 Rect[] expectedRects = new Rect[numFaces]; 586 for (int i = 0; i < numFaces; i++) { 587 expectedRects[i] = new Rect(i*4 + 1, i * 4 + 2, i * 4 + 3, i * 4 + 4); 588 } 589 int[] expectedFaceLM = new int[] { 590 1, 2, 3, 4, 5, 6, 591 7, 8, 9, 10, 11, 12, 592 13, 14, 15, 16, 17, 18, 593 19, 20, 21, 22, 23, 24, 594 25, 26, 27, 28, 29, 30, 595 }; 596 Point[] expectedFaceLMPoints = new Point[numFaces * 3]; 597 for (int i = 0; i < numFaces; i++) { 598 expectedFaceLMPoints[i*3] = new Point(expectedFaceLM[i*6], expectedFaceLM[i*6+1]); 599 expectedFaceLMPoints[i*3+1] = new Point(expectedFaceLM[i*6+2], expectedFaceLM[i*6+3]); 600 expectedFaceLMPoints[i*3+2] = new Point(expectedFaceLM[i*6+4], expectedFaceLM[i*6+5]); 601 } 602 603 /** 604 * Read - FACE_DETECT_MODE == FULL 605 */ 606 mMetadata.set(CaptureResult.STATISTICS_FACE_DETECT_MODE, 607 CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL); 608 mMetadata.set(CaptureResult.STATISTICS_FACE_IDS, expectedFaceIds); 609 mMetadata.set(CaptureResult.STATISTICS_FACE_SCORES, expectedFaceScores); 610 mMetadata.set(CaptureResult.STATISTICS_FACE_RECTANGLES, expectedRects); 611 mMetadata.set(CaptureResult.STATISTICS_FACE_LANDMARKS, expectedFaceLM); 612 Face[] resultFaces = mMetadata.get(CaptureResult.STATISTICS_FACES); 613 assertEquals(numFaces, resultFaces.length); 614 for (int i = 0; i < numFaces; i++) { 615 assertEquals(expectedFaceIds[i], resultFaces[i].getId()); 616 assertEquals(expectedFaceScores[i], resultFaces[i].getScore()); 617 assertEquals(expectedRects[i], resultFaces[i].getBounds()); 618 assertEquals(expectedFaceLMPoints[i*3], resultFaces[i].getLeftEyePosition()); 619 assertEquals(expectedFaceLMPoints[i*3+1], resultFaces[i].getRightEyePosition()); 620 assertEquals(expectedFaceLMPoints[i*3+2], resultFaces[i].getMouthPosition()); 621 } 622 623 /** 624 * Read - FACE_DETECT_MODE == SIMPLE 625 */ 626 mMetadata.set(CaptureResult.STATISTICS_FACE_DETECT_MODE, 627 CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE); 628 mMetadata.set(CaptureResult.STATISTICS_FACE_SCORES, expectedFaceScores); 629 mMetadata.set(CaptureResult.STATISTICS_FACE_RECTANGLES, expectedRects); 630 Face[] resultSimpleFaces = mMetadata.get(CaptureResult.STATISTICS_FACES); 631 assertEquals(numFaces, resultSimpleFaces.length); 632 for (int i = 0; i < numFaces; i++) { 633 assertEquals(Face.ID_UNSUPPORTED, resultSimpleFaces[i].getId()); 634 assertEquals(expectedFaceScores[i], resultSimpleFaces[i].getScore()); 635 assertEquals(expectedRects[i], resultSimpleFaces[i].getBounds()); 636 assertNull(resultSimpleFaces[i].getLeftEyePosition()); 637 assertNull(resultSimpleFaces[i].getRightEyePosition()); 638 assertNull(resultSimpleFaces[i].getMouthPosition()); 639 } 640 641 } 642 } 643