diff options
author | Igor Murashkin <iam@google.com> | 2013-07-02 11:23:44 -0700 |
---|---|---|
committer | Igor Murashkin <iam@google.com> | 2013-07-11 13:06:56 -0700 |
commit | b519cc52ecba8f44da31173c9fc90a7b66d52b79 (patch) | |
tree | 0f537a5a46f279c843192b2edb17f0f26177a208 /media/tests/MediaFrameworkTest/src | |
parent | 6b0693a318f8474f545cdccfb63cc74f847b3256 (diff) | |
download | frameworks_base-b519cc52ecba8f44da31173c9fc90a7b66d52b79.zip frameworks_base-b519cc52ecba8f44da31173c9fc90a7b66d52b79.tar.gz frameworks_base-b519cc52ecba8f44da31173c9fc90a7b66d52b79.tar.bz2 |
camera2 api: Add CameraMetadata get/set support
* Add a Rational class
* Can get/set Key<T> where T is a primitive (or Rational)
* Can get/set Key<T> where T is a primitive array
* Can get/set Key<T> where T is an enum (synthetic constructor only)
Not implemented yet:
* When T is anything else, i.e. Rect, Size, etc
Bug: 9529161
Change-Id: I64438024a1e8327a38dd2672652626f0ffbb70e3
Diffstat (limited to 'media/tests/MediaFrameworkTest/src')
2 files changed, 444 insertions, 0 deletions
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java index 3400434..8a2d347 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java @@ -18,7 +18,17 @@ package com.android.mediaframeworktest.unit; import android.os.Parcel; import android.test.suitebuilder.annotation.SmallTest; +import android.graphics.ImageFormat; import android.hardware.photography.CameraMetadata; +import android.hardware.photography.Rational; + +import static android.hardware.photography.CameraMetadata.*; + +import java.lang.reflect.Array; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import static org.junit.Assert.assertArrayEquals; /** * <pre> @@ -32,6 +42,21 @@ public class CameraMetadataTest extends junit.framework.TestCase { CameraMetadata mMetadata; Parcel mParcel; + // Sections + static final int ANDROID_COLOR_CORRECTION = 0; + static final int ANDROID_CONTROL = 1; + + // Section starts + static final int ANDROID_COLOR_CORRECTION_START = ANDROID_COLOR_CORRECTION << 16; + static final int ANDROID_CONTROL_START = ANDROID_CONTROL << 16; + + // Tags + static final int ANDROID_COLOR_CORRECTION_MODE = ANDROID_COLOR_CORRECTION_START; + static final int ANDROID_COLOR_CORRECTION_TRANSFORM = ANDROID_COLOR_CORRECTION_START + 1; + + static final int ANDROID_CONTROL_AE_ANTIBANDING_MODE = ANDROID_CONTROL_START; + static final int ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION = ANDROID_CONTROL_START + 1; + @Override public void setUp() { mMetadata = new CameraMetadata(); @@ -105,5 +130,310 @@ public class CameraMetadataTest extends junit.framework.TestCase { } catch (IllegalStateException e) { // good: we expect calling this method after close to fail } + + try { + mMetadata.readValues(/*tag*/0); + fail("Unreachable -- readValues after close should throw IllegalStateException"); + } catch (IllegalStateException e) { + // good: we expect calling this method after close to fail + } + + try { + mMetadata.writeValues(/*tag*/0, /*source*/new byte[] { 1,2,3 }); + fail("Unreachable -- readValues after close should throw IllegalStateException"); + } catch (IllegalStateException e) { + // good: we expect calling this method after close to fail + } + } + + @SmallTest + public void testGetTagFromKey() { + + // Test success + + assertEquals(ANDROID_COLOR_CORRECTION_MODE, + CameraMetadata.getTag("android.colorCorrection.mode")); + assertEquals(ANDROID_COLOR_CORRECTION_TRANSFORM, + CameraMetadata.getTag("android.colorCorrection.transform")); + assertEquals(ANDROID_CONTROL_AE_ANTIBANDING_MODE, + CameraMetadata.getTag("android.control.aeAntibandingMode")); + assertEquals(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, + CameraMetadata.getTag("android.control.aeExposureCompensation")); + + // Test failures + + try { + CameraMetadata.getTag(null); + fail("A null key should throw NPE"); + } catch(NullPointerException e) { + } + + try { + CameraMetadata.getTag("android.control"); + fail("A section name only should not be a valid key"); + } catch(IllegalArgumentException e) { + } + + try { + CameraMetadata.getTag("android.control.thisTagNameIsFakeAndDoesNotExist"); + fail("A valid section with an invalid tag name should not be a valid key"); + } catch(IllegalArgumentException e) { + } + + try { + CameraMetadata.getTag("android"); + fail("A namespace name only should not be a valid key"); + } catch(IllegalArgumentException e) { + } + + try { + CameraMetadata.getTag("this.key.is.definitely.invalid"); + fail("A completely fake key name should not be valid"); + } catch(IllegalArgumentException e) { + } + } + + @SmallTest + public void testGetTypeFromTag() { + assertEquals(TYPE_BYTE, CameraMetadata.getNativeType(ANDROID_COLOR_CORRECTION_MODE)); + assertEquals(TYPE_FLOAT, CameraMetadata.getNativeType(ANDROID_COLOR_CORRECTION_TRANSFORM)); + assertEquals(TYPE_BYTE, CameraMetadata.getNativeType(ANDROID_CONTROL_AE_ANTIBANDING_MODE)); + assertEquals(TYPE_INT32, + CameraMetadata.getNativeType(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION)); + + try { + CameraMetadata.getNativeType(0xDEADF00D); + fail("No type should exist for invalid tag 0xDEADF00D"); + } catch(IllegalArgumentException e) { + } + } + + @SmallTest + public void testReadWriteValues() { + final byte ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY = 2; + byte[] valueResult; + + assertEquals(0, mMetadata.getEntryCount()); + assertEquals(true, mMetadata.isEmpty()); + + // + // android.colorCorrection.mode (single enum byte) + // + + assertEquals(null, mMetadata.readValues(ANDROID_COLOR_CORRECTION_MODE)); + + // Write 0 values + mMetadata.writeValues(ANDROID_COLOR_CORRECTION_MODE, new byte[] {}); + + // Read 0 values + valueResult = mMetadata.readValues(ANDROID_COLOR_CORRECTION_MODE); + assertNotNull(valueResult); + assertEquals(0, valueResult.length); + + assertEquals(1, mMetadata.getEntryCount()); + assertEquals(false, mMetadata.isEmpty()); + + // Write 1 value + mMetadata.writeValues(ANDROID_COLOR_CORRECTION_MODE, new byte[] { + ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY + }); + + // Read 1 value + valueResult = mMetadata.readValues(ANDROID_COLOR_CORRECTION_MODE); + assertNotNull(valueResult); + assertEquals(1, valueResult.length); + assertEquals(ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY, valueResult[0]); + + assertEquals(1, mMetadata.getEntryCount()); + assertEquals(false, mMetadata.isEmpty()); + + // + // android.colorCorrection.transform (3x3 matrix) + // + + final float[] transformMatrix = new float[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + byte[] transformMatrixAsByteArray = new byte[transformMatrix.length * 4]; + ByteBuffer transformMatrixByteBuffer = + ByteBuffer.wrap(transformMatrixAsByteArray).order(ByteOrder.nativeOrder()); + for (float f : transformMatrix) + transformMatrixByteBuffer.putFloat(f); + + // Read + assertNull(mMetadata.readValues(ANDROID_COLOR_CORRECTION_TRANSFORM)); + mMetadata.writeValues(ANDROID_COLOR_CORRECTION_TRANSFORM, transformMatrixAsByteArray); + + // Write + assertArrayEquals(transformMatrixAsByteArray, + mMetadata.readValues(ANDROID_COLOR_CORRECTION_TRANSFORM)); + + assertEquals(2, mMetadata.getEntryCount()); + assertEquals(false, mMetadata.isEmpty()); + + // Erase + mMetadata.writeValues(ANDROID_COLOR_CORRECTION_TRANSFORM, null); + assertNull(mMetadata.readValues(ANDROID_COLOR_CORRECTION_TRANSFORM)); + assertEquals(1, mMetadata.getEntryCount()); + } + + private static <T> void assertArrayEquals(T expected, T actual) { + assertEquals(Array.getLength(expected), Array.getLength(actual)); + + int len = Array.getLength(expected); + for (int i = 0; i < len; ++i) { + assertEquals(Array.get(expected, i), Array.get(actual, i)); + } + } + + private <T> void checkKeyGetAndSet(String keyStr, Class<T> type, T value) { + Key<T> key = new Key<T>(keyStr, type); + assertNull(mMetadata.get(key)); + mMetadata.set(key, value); + assertEquals(value, mMetadata.get(key)); + } + + private <T> void checkKeyGetAndSetArray(String keyStr, Class<T> type, T value) { + Key<T> key = new Key<T>(keyStr, type); + assertNull(mMetadata.get(key)); + mMetadata.set(key, value); + assertArrayEquals(value, mMetadata.get(key)); + } + + @SmallTest + public void testReadWritePrimitive() { + // int32 (single) + checkKeyGetAndSet("android.control.aeExposureCompensation", Integer.TYPE, 0xC0FFEE); + + // byte (single) + checkKeyGetAndSet("android.flash.maxEnergy", Byte.TYPE, (byte)6); + + // int64 (single) + checkKeyGetAndSet("android.flash.firingTime", Long.TYPE, 0xABCD12345678FFFFL); + + // float (single) + checkKeyGetAndSet("android.lens.aperture", Float.TYPE, Float.MAX_VALUE); + + // double (single) -- technically double x 3, but we fake it + checkKeyGetAndSet("android.jpeg.gpsCoordinates", Double.TYPE, Double.MAX_VALUE); + + // rational (single) + checkKeyGetAndSet("android.sensor.baseGainFactor", Rational.class, new Rational(1, 2)); + + /** + * Weirder cases, that don't map 1:1 with the native types + */ + + // bool (single) -- with TYPE_BYTE + checkKeyGetAndSet("android.control.aeLock", Boolean.TYPE, true); + + // integer (single) -- with TYPE_BYTE + checkKeyGetAndSet("android.control.aePrecaptureTrigger", Integer.TYPE, 6); + } + + @SmallTest + public void testReadWritePrimitiveArray() { + // int32 (n) + checkKeyGetAndSetArray("android.sensor.info.availableSensitivities", int[].class, + new int[] { + 0xC0FFEE, 0xDEADF00D + }); + + // byte (n) + checkKeyGetAndSetArray("android.statistics.faceScores", byte[].class, new byte[] { + 1, 2, 3, 4 + }); + + // int64 (n) + checkKeyGetAndSetArray("android.scaler.availableProcessedMinDurations", long[].class, + new long[] { + 0xABCD12345678FFFFL, 0x1234ABCD5678FFFFL, 0xFFFF12345678ABCDL + }); + + // float (n) + checkKeyGetAndSetArray("android.lens.info.availableApertures", float[].class, + new float[] { + Float.MAX_VALUE, Float.MIN_NORMAL, Float.MIN_VALUE + }); + + // double (n) -- in particular double x 3 + checkKeyGetAndSetArray("android.jpeg.gpsCoordinates", double[].class, + new double[] { + Double.MAX_VALUE, Double.MIN_NORMAL, Double.MIN_VALUE + }); + + // rational (n) -- in particular rational x 9 + checkKeyGetAndSetArray("android.sensor.calibrationTransform1", Rational[].class, + new Rational[] { + new Rational(1, 2), new Rational(3, 4), new Rational(5, 6), + new Rational(7, 8), new Rational(9, 10), new Rational(10, 11), + new Rational(12, 13), new Rational(14, 15), new Rational(15, 16) + }); + + /** + * Weirder cases, that don't map 1:1 with the native types + */ + + // bool (n) -- with TYPE_BYTE + checkKeyGetAndSetArray("android.control.aeLock", boolean[].class, new boolean[] { + true, false, true + }); + + + // integer (n) -- with TYPE_BYTE + checkKeyGetAndSetArray("android.control.aeAvailableModes", int[].class, new int[] { + 1, 2, 3, 4 + }); + } + + private enum ColorCorrectionMode { + TRANSFORM_MATRIX, + FAST, + HIGH_QUALITY + } + + private enum AeAntibandingMode { + OFF, + _50HZ, + _60HZ, + AUTO + } + + // TODO: special values for the enum. + private enum AvailableFormat { + RAW_SENSOR, + YV12, + YCrCb_420_SP, + IMPLEMENTATION_DEFINED, + YCbCr_420_888, + BLOB + } + + @SmallTest + public void testReadWriteEnum() { + // byte (single) + checkKeyGetAndSet("android.colorCorrection.mode", ColorCorrectionMode.class, + ColorCorrectionMode.HIGH_QUALITY); + + // byte (single) + checkKeyGetAndSet("android.control.aeAntibandingMode", AeAntibandingMode.class, + AeAntibandingMode.AUTO); + + // byte (n) + checkKeyGetAndSetArray("android.control.aeAvailableAntibandingModes", + AeAntibandingMode[].class, new AeAntibandingMode[] { + AeAntibandingMode.OFF, AeAntibandingMode._50HZ, AeAntibandingMode._60HZ, + AeAntibandingMode.AUTO + }); + + /** + * Stranger cases that don't use byte enums + */ + // int (n) + checkKeyGetAndSetArray("android.scaler.availableFormats", AvailableFormat[].class, + new AvailableFormat[] { + AvailableFormat.RAW_SENSOR, + AvailableFormat.YV12, + AvailableFormat.IMPLEMENTATION_DEFINED + }); + } } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RationalTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RationalTest.java new file mode 100644 index 0000000..c15d030 --- /dev/null +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/RationalTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.mediaframeworktest.unit; + +import android.test.suitebuilder.annotation.SmallTest; +import android.hardware.photography.Rational; + +/** + * <pre> + * adb shell am instrument \ + * -e class 'com.android.mediaframeworktest.unit.RationalTest' \ + * -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner + * </pre> + */ +public class RationalTest extends junit.framework.TestCase { + @SmallTest + public void testConstructor() { + + // Simple case + Rational r = new Rational(1, 2); + assertEquals(1, r.getNumerator()); + assertEquals(2, r.getDenominator()); + + // Denominator negative + r = new Rational(-1, 2); + assertEquals(-1, r.getNumerator()); + assertEquals(2, r.getDenominator()); + + // Numerator negative + r = new Rational(1, -2); + assertEquals(-1, r.getNumerator()); + assertEquals(2, r.getDenominator()); + + // Both negative + r = new Rational(-1, -2); + assertEquals(1, r.getNumerator()); + assertEquals(2, r.getDenominator()); + + // Dividing by zero is not allowed + try { + r = new Rational(1, 0); + fail("Expected Rational constructor to throw an IllegalArgumentException"); + } catch(IllegalArgumentException e) { + } + } + + @SmallTest + public void testGcd() { + Rational r = new Rational(1, 2); + assertEquals(1, r.gcd()); + + Rational twoThirds = new Rational(2, 3); + assertEquals(1, twoThirds.gcd()); + + Rational moreComplicated2 = new Rational(5*78, 7*78); + assertEquals(78, moreComplicated2.gcd()); + + Rational oneHalf = new Rational(-1, 2); + assertEquals(1, oneHalf.gcd()); + + twoThirds = new Rational(-2, 3); + assertEquals(1, twoThirds.gcd()); + } + + @SmallTest + public void testEquals() { + Rational r = new Rational(1, 2); + assertEquals(1, r.getNumerator()); + assertEquals(2, r.getDenominator()); + + assertEquals(r, r); + assertFalse(r.equals(null)); + assertFalse(r.equals(new Object())); + + Rational twoThirds = new Rational(2, 3); + assertFalse(r.equals(twoThirds)); + assertFalse(twoThirds.equals(r)); + + Rational fourSixths = new Rational(4, 6); + assertEquals(twoThirds, fourSixths); + assertEquals(fourSixths, twoThirds); + + Rational moreComplicated = new Rational(5*6*7*8*9, 1*2*3*4*5); + Rational moreComplicated2 = new Rational(5*6*7*8*9*78, 1*2*3*4*5*78); + assertEquals(moreComplicated, moreComplicated2); + assertEquals(moreComplicated2, moreComplicated); + + // Ensure negatives are fine + twoThirds = new Rational(-2, 3); + fourSixths = new Rational(-4, 6); + assertEquals(twoThirds, fourSixths); + assertEquals(fourSixths, twoThirds); + + moreComplicated = new Rational(-5*6*7*8*9, 1*2*3*4*5); + moreComplicated2 = new Rational(-5*6*7*8*9*78, 1*2*3*4*5*78); + assertEquals(moreComplicated, moreComplicated2); + assertEquals(moreComplicated2, moreComplicated); + + } +}
\ No newline at end of file |