170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin/*
270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * Copyright (C) 2013 The Android Open Source Project
370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin *
470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * Licensed under the Apache License, Version 2.0 (the "License");
570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * you may not use this file except in compliance with the License.
670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * You may obtain a copy of the License at
770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin *
870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin *      http://www.apache.org/licenses/LICENSE-2.0
970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin *
1070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * Unless required by applicable law or agreed to in writing, software
1170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * distributed under the License is distributed on an "AS IS" BASIS,
1270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * See the License for the specific language governing permissions and
1470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * limitations under the License.
1570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin */
1670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
1770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinpackage com.android.mediaframeworktest.unit;
1870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
1970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinimport android.test.suitebuilder.annotation.SmallTest;
20d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinimport android.util.Log;
215743868e15c88d2886915163652a1571a218bf39Igor Murashkinimport android.util.Pair;
223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.util.Range;
2372f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinimport android.util.Rational;
243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.util.SizeF;
253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.graphics.ImageFormat;
26b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun Heimport android.graphics.Point;
273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.graphics.PointF;
283710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkinimport android.graphics.Rect;
299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.graphics.SurfaceTexture;
30b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun Heimport android.hardware.camera2.CameraCharacteristics;
31d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinimport android.hardware.camera2.CameraMetadata;
32d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinimport android.hardware.camera2.CaptureRequest;
33b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun Heimport android.hardware.camera2.CaptureResult;
3472f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinimport android.util.Size;
3570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalaimport android.hardware.camera2.impl.CameraMetadataNative;
363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.marshal.impl.MarshalQueryableEnum;
3772f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinimport android.hardware.camera2.params.ColorSpaceTransform;
3872f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinimport android.hardware.camera2.params.Face;
3912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yehimport android.hardware.camera2.params.HighSpeedVideoConfiguration;
4072f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinimport android.hardware.camera2.params.MeteringRectangle;
419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.hardware.camera2.params.ReprocessFormatsMap;
4272f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinimport android.hardware.camera2.params.RggbChannelVector;
439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.hardware.camera2.params.StreamConfiguration;
449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.hardware.camera2.params.StreamConfigurationDuration;
459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.hardware.camera2.params.StreamConfigurationMap;
468490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yehimport android.hardware.camera2.params.TonemapCurve;
473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.utils.TypeReference;
48b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
4970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalaimport static android.hardware.camera2.impl.CameraMetadataNative.*;
503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport static com.android.mediaframeworktest.unit.ByteArrayHelpers.*;
51b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
52b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinimport java.lang.reflect.Array;
53b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinimport java.nio.ByteBuffer;
54b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinimport java.nio.ByteOrder;
55d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinimport java.util.List;
5670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
5770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin/**
5870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * <pre>
5970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * adb shell am instrument \
6070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin *      -e class 'com.android.mediaframeworktest.unit.CameraMetadataTest' \
6170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin *      -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner
6270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin * </pre>
6370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin */
6470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinpublic class CameraMetadataTest extends junit.framework.TestCase {
6570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
66d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    private static final boolean VERBOSE = false;
67d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    private static final String TAG = "CameraMetadataTest";
68d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
69d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
7070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    CameraMetadataNative mMetadata;
7170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
72b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Sections
73b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static final int ANDROID_COLOR_CORRECTION = 0;
74b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static final int ANDROID_CONTROL = 1;
75b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
76b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Section starts
77b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static final int ANDROID_COLOR_CORRECTION_START = ANDROID_COLOR_CORRECTION << 16;
78b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static final int ANDROID_CONTROL_START = ANDROID_CONTROL << 16;
79b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
80b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Tags
81b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static final int ANDROID_COLOR_CORRECTION_MODE = ANDROID_COLOR_CORRECTION_START;
82b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static final int ANDROID_COLOR_CORRECTION_TRANSFORM = ANDROID_COLOR_CORRECTION_START + 1;
83b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    static final int ANDROID_COLOR_CORRECTION_GAINS = ANDROID_COLOR_CORRECTION_START + 2;
84b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
85b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static final int ANDROID_CONTROL_AE_ANTIBANDING_MODE = ANDROID_CONTROL_START;
86b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static final int ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION = ANDROID_CONTROL_START + 1;
87b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
889c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    // From graphics.h
899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @Override
9270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    public void setUp() {
9370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        mMetadata = new CameraMetadataNative();
9470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
9570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
9670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @Override
9770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    public void tearDown() throws Exception {
9870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        mMetadata = null;
9970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
10070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
10170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @SmallTest
10270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    public void testNew() {
10370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        assertEquals(0, mMetadata.getEntryCount());
10470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        assertTrue(mMetadata.isEmpty());
10570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
10670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
10770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    @SmallTest
108b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public void testGetTagFromKey() {
109b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
110b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Test success
111b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
112b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(ANDROID_COLOR_CORRECTION_MODE,
11370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala                CameraMetadataNative.getTag("android.colorCorrection.mode"));
114b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(ANDROID_COLOR_CORRECTION_TRANSFORM,
11570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala                CameraMetadataNative.getTag("android.colorCorrection.transform"));
116b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(ANDROID_CONTROL_AE_ANTIBANDING_MODE,
11770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala                CameraMetadataNative.getTag("android.control.aeAntibandingMode"));
118b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
11970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala                CameraMetadataNative.getTag("android.control.aeExposureCompensation"));
120b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
121b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Test failures
122b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
123b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        try {
12470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            CameraMetadataNative.getTag(null);
125b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            fail("A null key should throw NPE");
126b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        } catch(NullPointerException e) {
127b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
128b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
129b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        try {
13070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            CameraMetadataNative.getTag("android.control");
131b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            fail("A section name only should not be a valid key");
132b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        } catch(IllegalArgumentException e) {
133b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
134b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
135b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        try {
13670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            CameraMetadataNative.getTag("android.control.thisTagNameIsFakeAndDoesNotExist");
137b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            fail("A valid section with an invalid tag name should not be a valid key");
138b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        } catch(IllegalArgumentException e) {
139b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
140b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
141b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        try {
14270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            CameraMetadataNative.getTag("android");
143b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            fail("A namespace name only should not be a valid key");
144b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        } catch(IllegalArgumentException e) {
145b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
146b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
147b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        try {
14870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            CameraMetadataNative.getTag("this.key.is.definitely.invalid");
149b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            fail("A completely fake key name should not be valid");
150b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        } catch(IllegalArgumentException e) {
151b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
152b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
153b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
154b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    @SmallTest
155b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public void testGetTypeFromTag() {
1563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertEquals(TYPE_BYTE,
157de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev                CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_MODE, Long.MAX_VALUE));
1583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertEquals(TYPE_RATIONAL,
159de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev                CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_TRANSFORM, Long.MAX_VALUE));
1603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertEquals(TYPE_FLOAT,
161de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev                CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_GAINS, Long.MAX_VALUE));
1623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertEquals(TYPE_BYTE,
163de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev                CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_ANTIBANDING_MODE, Long.MAX_VALUE));
164b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(TYPE_INT32,
165de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev                CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, Long.MAX_VALUE));
166b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
167b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        try {
168de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            CameraMetadataNative.getNativeType(0xDEADF00D, Long.MAX_VALUE);
169b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            fail("No type should exist for invalid tag 0xDEADF00D");
170b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        } catch(IllegalArgumentException e) {
171b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
172b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
173b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
174b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    @SmallTest
175b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public void testReadWriteValues() {
176b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        final byte ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY = 2;
177b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        byte[] valueResult;
178b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
179b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(0, mMetadata.getEntryCount());
180b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(true, mMetadata.isEmpty());
181b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
182b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        //
183b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // android.colorCorrection.mode (single enum byte)
184b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        //
185b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
186b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(null, mMetadata.readValues(ANDROID_COLOR_CORRECTION_MODE));
187b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
1883710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        // Write/read null values
1893710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        mMetadata.writeValues(ANDROID_COLOR_CORRECTION_MODE, null);
1903710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        assertEquals(null, mMetadata.readValues(ANDROID_COLOR_CORRECTION_MODE));
1913710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
192b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Write 0 values
193b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        mMetadata.writeValues(ANDROID_COLOR_CORRECTION_MODE, new byte[] {});
194b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
195b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Read 0 values
196b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        valueResult = mMetadata.readValues(ANDROID_COLOR_CORRECTION_MODE);
197b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertNotNull(valueResult);
198b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(0, valueResult.length);
199b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
200b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(1, mMetadata.getEntryCount());
201b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(false, mMetadata.isEmpty());
202b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
203b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Write 1 value
204b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        mMetadata.writeValues(ANDROID_COLOR_CORRECTION_MODE, new byte[] {
205b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY
206b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        });
207b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
208b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Read 1 value
209b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        valueResult = mMetadata.readValues(ANDROID_COLOR_CORRECTION_MODE);
210b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertNotNull(valueResult);
211b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(1, valueResult.length);
212b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY, valueResult[0]);
213b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
214b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(1, mMetadata.getEntryCount());
215b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(false, mMetadata.isEmpty());
216b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
217b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        //
218b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        // android.colorCorrection.colorCorrectionGains (float x 4 array)
219b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        //
220b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
221b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        final float[] colorCorrectionGains = new float[] { 1.0f, 2.0f, 3.0f, 4.0f};
222b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        byte[] colorCorrectionGainsAsByteArray = new byte[colorCorrectionGains.length * 4];
223b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        ByteBuffer colorCorrectionGainsByteBuffer =
224b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                ByteBuffer.wrap(colorCorrectionGainsAsByteArray).order(ByteOrder.nativeOrder());
225b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        for (float f : colorCorrectionGains)
226b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            colorCorrectionGainsByteBuffer.putFloat(f);
227b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
228b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Read
229b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        assertNull(mMetadata.readValues(ANDROID_COLOR_CORRECTION_GAINS));
230b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.writeValues(ANDROID_COLOR_CORRECTION_GAINS, colorCorrectionGainsAsByteArray);
231b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
232b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Write
233b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        assertArrayEquals(colorCorrectionGainsAsByteArray,
234b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                mMetadata.readValues(ANDROID_COLOR_CORRECTION_GAINS));
235b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
236b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(2, mMetadata.getEntryCount());
237b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(false, mMetadata.isEmpty());
238b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
239b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Erase
240b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.writeValues(ANDROID_COLOR_CORRECTION_GAINS, null);
241b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        assertNull(mMetadata.readValues(ANDROID_COLOR_CORRECTION_GAINS));
242b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(1, mMetadata.getEntryCount());
243b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
244b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
2453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
2463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * Format an array into a string with the {@code badIndex} highlighted with {@code **}.
2473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
2483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>Numbers are printed as hexadecimal values.</p>
2493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
2503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>Example: {@code "[hello, **world**]"} for a {@code string[]},
2513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * or a {@code "[**0xFF**, 0xFF]"} for a {@code int[]}.</p>
2523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
2533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private static <T> String formatArray(T array, int badIndex) {
2543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        StringBuilder builder = new StringBuilder();
2553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        builder.append("[");
2573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        int len = Array.getLength(array);
2593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        for (int i = 0; i < len; ++i) {
2603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            Object elem = Array.get(array, i);
2623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            if (i == badIndex) {
2643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                builder.append("**");
2653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            }
2663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            if (elem instanceof Number) {
2683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                builder.append(String.format("%x", elem));
2693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            } else {
2703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                builder.append(elem);
2713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            }
2723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            if (i == badIndex) {
2743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                builder.append("**");
2753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            }
2763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            if (i != len - 1) {
2783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                builder.append(", ");
2793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            }
2803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
2813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        builder.append("]");
2833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return builder.toString();
2853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
2863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
287b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    private static <T> void assertArrayEquals(T expected, T actual) {
2883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        if (!expected.getClass().isArray() || !actual.getClass().isArray()) {
2893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            throw new IllegalArgumentException("expected, actual must both be arrays");
2903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
2913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertEquals("Array lengths must be equal",
2933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                Array.getLength(expected), Array.getLength(actual));
294b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
295b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        int len = Array.getLength(expected);
296b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        for (int i = 0; i < len; ++i) {
2973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
2983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            Object expectedElement = Array.get(expected, i);
2993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            Object actualElement = Array.get(actual, i);
3003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
3013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            if (!expectedElement.equals(actualElement)) {
3023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                fail(String.format(
3033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        "element %d in array was not equal (expected %s, actual %s). "
3043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                                + "Arrays were: (expected %s, actual %s).",
3053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                                i, expectedElement, actualElement,
3063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                                formatArray(expected, i),
3073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                                formatArray(actual, i)));
3083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            }
309b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
310b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
311b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
3129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static <T, T2> void assertArrayContains(T needle, T2 array) {
3139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (!array.getClass().isArray()) {
3149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            throw new IllegalArgumentException("actual must be array");
3159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
3169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
3179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int len = Array.getLength(array);
3189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (int i = 0; i < len; ++i) {
3199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
3209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            Object actualElement = Array.get(array, i);
3219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
3229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            if (needle.equals(actualElement)) {
3239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                return;
3249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            }
3259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
3269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
3279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        fail(String.format(
3289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                "could not find element in array (needle %s). "
3299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                        + "Array was: %s.",
3309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                        needle,
3319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                        formatArray(array, len)));
3329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
3339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
3343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private <T> void checkKeyGetAndSet(String keyStr, TypeReference<T> typeToken, T expected,
3353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            boolean reuse) {
3363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        Key<T> key = new Key<T>(keyStr, typeToken);
337b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertNull(mMetadata.get(key));
3383710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        mMetadata.set(key, null);
3393710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        assertNull(mMetadata.get(key));
3403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        mMetadata.set(key, expected);
3413710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
3423710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        T actual = mMetadata.get(key);
3433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
3443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        if (typeToken.getRawType().isArray()) {
3453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            assertArrayEquals(expected, actual);
3463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        } else {
3473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            assertEquals(expected, actual);
3483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
3493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
3503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        if (reuse) {
3513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            // reset the key incase we want to use it again
3523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            mMetadata.set(key, null);
3533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
3543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
3553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
3563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private <T> void checkKeyGetAndSet(String keyStr, TypeReference<T> typeToken, T expected) {
3573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet(keyStr, typeToken, expected, /*reuse*/false);
358b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
359b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
3603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private <T> void checkKeyGetAndSet(String keyStr, Class<T> type, T expected) {
3613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet(keyStr, TypeReference.createSpecializedTypeReference(type), expected);
3623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
3633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
3643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
3653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * Ensure that the data survives a marshal/unmarshal round-trip;
3663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * it must also be equal to the {@code expectedNative} byte array.
3673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
3683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>As a side-effect, the metadata value corresponding to the key is now set to
3693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * {@code expected}.</p>
3703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
3713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @return key created with {@code keyName} and {@code T}
3723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
3733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private <T> Key<T> checkKeyMarshal(String keyName, TypeReference<T> typeReference,
3743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            T expected, byte[] expectedNative) {
3753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        Key<T> key = new Key<T>(keyName, typeReference);
3763710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
3773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        mMetadata.set(key, null);
378b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertNull(mMetadata.get(key));
3793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
3803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // Write managed value -> make sure native bytes are what we expect
3813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        mMetadata.set(key, expected);
3823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
3833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        byte[] actualValues = mMetadata.readValues(key.getTag());
3843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertArrayEquals(expectedNative, actualValues);
3853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
3863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // Write managed value -> make sure read-out managed value is what we expect
3873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        T actual = mMetadata.get(key);
3883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
3893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        if (typeReference.getRawType().isArray()) {
3903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            assertArrayEquals(expected, actual);
3913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        } else {
3923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            assertEquals(expected, actual);
3933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
3943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
3953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // Write native bytes -> make sure read-out managed value is what we expect
3963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        mMetadata.writeValues(key.getTag(), expectedNative);
3973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        actual = mMetadata.get(key);
3983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
3993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        if (typeReference.getRawType().isArray()) {
4003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            assertArrayEquals(expected, actual);
4013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        } else {
4023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            assertEquals(expected, actual);
4033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
4043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
4053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return key;
4063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
4073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
4083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
4093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * Ensure that the data survives a marshal/unmarshal round-trip;
4103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * it must also be equal to the {@code expectedNative} byte array.
4113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
4123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>As a side-effect,
4133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * the metadata value corresponding to the key is now set to {@code expected}.</p>
4143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
4153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @return key created with {@code keyName} and {@code T}
4163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
4173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    private <T> Key<T> checkKeyMarshal(String keyName, T expected, byte[] expectedNative) {
4183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        @SuppressWarnings("unchecked")
4193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        Class<T> expectedClass = (Class<T>) expected.getClass();
4203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return checkKeyMarshal(keyName,
4213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                TypeReference.createSpecializedTypeReference(expectedClass),
4223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                expected,
4233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                expectedNative);
424b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
425b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
426b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    @SmallTest
427b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public void testReadWritePrimitive() {
428b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // int32 (single)
429b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        checkKeyGetAndSet("android.control.aeExposureCompensation", Integer.TYPE, 0xC0FFEE);
430b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
431b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // byte (single)
432b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        checkKeyGetAndSet("android.flash.maxEnergy", Byte.TYPE, (byte)6);
433b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
434b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // int64 (single)
435b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        checkKeyGetAndSet("android.flash.firingTime", Long.TYPE, 0xABCD12345678FFFFL);
436b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
437b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // float (single)
438b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        checkKeyGetAndSet("android.lens.aperture", Float.TYPE, Float.MAX_VALUE);
439b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
440b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // double (single) -- technically double x 3, but we fake it
441b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        checkKeyGetAndSet("android.jpeg.gpsCoordinates", Double.TYPE, Double.MAX_VALUE);
442b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
443b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // rational (single)
444b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        checkKeyGetAndSet("android.sensor.baseGainFactor", Rational.class, new Rational(1, 2));
445b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
446b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        /**
447b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         * Weirder cases, that don't map 1:1 with the native types
448b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         */
449b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
450b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // bool (single) -- with TYPE_BYTE
451b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        checkKeyGetAndSet("android.control.aeLock", Boolean.TYPE, true);
452b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
453b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // integer (single) -- with TYPE_BYTE
454b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        checkKeyGetAndSet("android.control.aePrecaptureTrigger", Integer.TYPE, 6);
455b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
456b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
457b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    @SmallTest
458b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public void testReadWritePrimitiveArray() {
459b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // int32 (n)
4603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.sensor.info.sensitivityRange", int[].class,
461b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                new int[] {
462b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        0xC0FFEE, 0xDEADF00D
463b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                });
464b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
465b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // byte (n)
4663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.statistics.faceScores", byte[].class, new byte[] {
467b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                1, 2, 3, 4
468b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        });
469b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
470b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // int64 (n)
4713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.scaler.availableProcessedMinDurations", long[].class,
472b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                new long[] {
473b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        0xABCD12345678FFFFL, 0x1234ABCD5678FFFFL, 0xFFFF12345678ABCDL
474b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                });
475b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
476b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // float (n)
4773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.lens.info.availableApertures", float[].class,
478b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                new float[] {
479b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        Float.MAX_VALUE, Float.MIN_NORMAL, Float.MIN_VALUE
480b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                });
481b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
482b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // double (n) -- in particular double x 3
4833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.jpeg.gpsCoordinates", double[].class,
484b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                new double[] {
485b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        Double.MAX_VALUE, Double.MIN_NORMAL, Double.MIN_VALUE
486b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                });
487b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
488b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // rational (n) -- in particular rational x 9
4893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.sensor.calibrationTransform1", Rational[].class,
490b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                new Rational[] {
491b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        new Rational(1, 2), new Rational(3, 4), new Rational(5, 6),
492b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        new Rational(7, 8), new Rational(9, 10), new Rational(10, 11),
493b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        new Rational(12, 13), new Rational(14, 15), new Rational(15, 16)
494b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                });
495b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
496b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        /**
497b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         * Weirder cases, that don't map 1:1 with the native types
498b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         */
499b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
500b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // bool (n) -- with TYPE_BYTE
5013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.control.aeLock", boolean[].class, new boolean[] {
502b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                true, false, true
503b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        });
504b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
505b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // integer (n) -- with TYPE_BYTE
5063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.control.aeAvailableModes", int[].class, new int[] {
507b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            1, 2, 3, 4
508b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        });
509b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
510b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
511b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    private enum ColorCorrectionMode {
512b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        TRANSFORM_MATRIX,
513b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        FAST,
514b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        HIGH_QUALITY
515b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
516b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
517b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    private enum AeAntibandingMode {
518b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        OFF,
519b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        _50HZ,
520b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        _60HZ,
521b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        AUTO
522b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
523b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
524b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    private enum AvailableFormat {
525b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        RAW_SENSOR,
526b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        YV12,
527b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        YCrCb_420_SP,
528b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        IMPLEMENTATION_DEFINED,
529b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        YCbCr_420_888,
530b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        BLOB
531b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
532b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
533b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    @SmallTest
534b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public void testReadWriteEnum() {
535b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // byte (single)
536b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        checkKeyGetAndSet("android.colorCorrection.mode", ColorCorrectionMode.class,
537b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                ColorCorrectionMode.HIGH_QUALITY);
538b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
539b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // byte (single)
540b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        checkKeyGetAndSet("android.control.aeAntibandingMode", AeAntibandingMode.class,
541b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                AeAntibandingMode.AUTO);
542b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
543b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // byte (n)
5443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.control.aeAvailableAntibandingModes",
545b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                AeAntibandingMode[].class, new AeAntibandingMode[] {
546b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        AeAntibandingMode.OFF, AeAntibandingMode._50HZ, AeAntibandingMode._60HZ,
547b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        AeAntibandingMode.AUTO
548b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                });
549b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
550b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        /**
551b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         * Stranger cases that don't use byte enums
552b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         */
553b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // int (n)
5543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.scaler.availableFormats", AvailableFormat[].class,
555b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                new AvailableFormat[] {
556b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        AvailableFormat.RAW_SENSOR,
557b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        AvailableFormat.YV12,
558b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                        AvailableFormat.IMPLEMENTATION_DEFINED,
559b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                        AvailableFormat.YCbCr_420_888,
560b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                        AvailableFormat.BLOB
561b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                });
562b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
56370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
564b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin
565b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin    @SmallTest
566b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin    public void testReadWriteEnumWithCustomValues() {
5673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        MarshalQueryableEnum.registerEnumValues(AeAntibandingMode.class, new int[] {
568b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin            0,
569b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin            10,
570b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin            20,
571b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin            30
572b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        });
573b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin
574b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        // byte (single)
575b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        checkKeyGetAndSet("android.control.aeAntibandingMode", AeAntibandingMode.class,
576b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                AeAntibandingMode.AUTO);
577b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin
578b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        // byte (n)
5793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.control.aeAvailableAntibandingModes",
580b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                AeAntibandingMode[].class, new AeAntibandingMode[] {
581b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                        AeAntibandingMode.OFF, AeAntibandingMode._50HZ, AeAntibandingMode._60HZ,
582b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                        AeAntibandingMode.AUTO
583b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                });
584b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin
58570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        byte[] aeAntibandingModeValues = mMetadata.readValues(CameraMetadataNative
586b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                .getTag("android.control.aeAvailableAntibandingModes"));
587b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        byte[] expectedValues = new byte[] { 0, 10, 20, 30 };
588b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        assertArrayEquals(expectedValues, aeAntibandingModeValues);
589b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin
590b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin
591b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        /**
592b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin         * Stranger cases that don't use byte enums
593b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin         */
594b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        // int (n)
5953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        MarshalQueryableEnum.registerEnumValues(AvailableFormat.class, new int[] {
596b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin            0x20,
597b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin            0x32315659,
598b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin            0x11,
599b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin            0x22,
600b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin            0x23,
601b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin            0x21,
602b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        });
603b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin
6043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.scaler.availableFormats", AvailableFormat[].class,
605b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                new AvailableFormat[] {
606b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                        AvailableFormat.RAW_SENSOR,
607b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                        AvailableFormat.YV12,
608d7bf1778df666e82268d1e4549d248ce3dfc9665Igor Murashkin                        AvailableFormat.IMPLEMENTATION_DEFINED,
609b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                        AvailableFormat.YCbCr_420_888,
610b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                        AvailableFormat.BLOB
611b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                });
612b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin
613b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        Key<AvailableFormat[]> availableFormatsKey =
614b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                new Key<AvailableFormat[]>("android.scaler.availableFormats",
615b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                        AvailableFormat[].class);
61670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        byte[] availableFormatValues = mMetadata.readValues(CameraMetadataNative
617b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                .getTag(availableFormatsKey.getName()));
618b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin
619b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        int[] expectedIntValues = new int[] {
620b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                0x20,
621b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin                0x32315659,
622d7bf1778df666e82268d1e4549d248ce3dfc9665Igor Murashkin                0x22,
623b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x23,
624b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x21
625b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        };
626b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin
627b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        ByteBuffer bf = ByteBuffer.wrap(availableFormatValues).order(ByteOrder.nativeOrder());
628b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin
629b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        assertEquals(expectedIntValues.length * 4, availableFormatValues.length);
630b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        for (int i = 0; i < expectedIntValues.length; ++i) {
631b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin            assertEquals(expectedIntValues[i], bf.getInt());
632b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin        }
633b9dd637f830e6bd4f257ffb2c807c3ea27f8feeeIgor Murashkin    }
6343710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
6353710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin    @SmallTest
6363710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin    public void testReadWriteSize() {
6373710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        // int32 x n
6383710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        checkKeyGetAndSet("android.jpeg.thumbnailSize", Size.class, new Size(123, 456));
6393710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
6403710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        // int32 x 2 x n
6413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyGetAndSet("android.scaler.availableJpegSizes", Size[].class, new Size[] {
6423710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            new Size(123, 456),
6433710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            new Size(0xDEAD, 0xF00D),
6443710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            new Size(0xF00, 0xB00)
6453710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        });
6463710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin    }
6473710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
6483710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin    @SmallTest
6493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteRggbChannelVector() {
6503710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        // int32 x n
6513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.colorCorrection.gains",
6523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new RggbChannelVector(1.0f, 2.1f, 3.2f, 4.5f),
6533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(1.0f, 2.1f, 3.2f, 4.5f));
6543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
6553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x 2 x n [pretend; actual is not array]
6563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.colorCorrection.gains",
6573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new RggbChannelVector[] {
6583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new RggbChannelVector(1.0f, 2.0f, 3.0f, 4.0f),
6593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new RggbChannelVector(9.0f, 8.0f, 7.0f, 6.0f),
6603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new RggbChannelVector(1.3f, 5.5f, 2.4f, 6.7f),
6613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                }, toByteArray(
6623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        1.0f, 2.0f, 3.0f, 4.0f,
6633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        9.0f, 8.0f, 7.0f, 6.0f,
6643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        1.3f, 5.5f, 2.4f, 6.7f
6653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                ));
6663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
6673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
6683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
6693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteSizeF() {
6703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x n
6713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.sensor.info.physicalSize",
6723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new SizeF(123f, 456f),
6733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(123f, 456f));
6743710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
6753710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        // int32 x 2 x n
6763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.sensor.info.physicalSize",
6773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new SizeF[] {
6783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new SizeF(123f, 456f),
6793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new SizeF(1.234f, 4.567f),
6803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new SizeF(999.0f, 555.0f)
6813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                },
6823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(
6833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        123f, 456f,
6843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        1.234f, 4.567f,
6853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        999.0f, 555.0f)
6863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        );
6873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
6883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
6893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
6903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteRectangle() {
6913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x n
6923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.scaler.cropRegion",
6933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                // x1, y1, x2, y2
6943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new Rect(10, 11, 1280, 1024),
6953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                // x, y, width, height
6963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(10, 11, 1280 - 10, 1024 - 11));
6973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
6983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x 2 x n  [actually not array, but we pretend it is]
6993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.scaler.cropRegion", new Rect[] {
7003710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            new Rect(110, 111, 11280, 11024),
7013710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            new Rect(210, 111, 21280, 21024),
7023710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            new Rect(310, 111, 31280, 31024)
7033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }, toByteArray(
7043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                110, 111, 11280 - 110, 11024 - 111,
7053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                210, 111, 21280 - 210, 21024 - 111,
7063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                310, 111, 31280 - 310, 31024 - 111
7073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        ));
7083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
7093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
7103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
7113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteMeteringRectangle() {
7123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x 5 x area_count [but we pretend it's a single element]
7133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.control.aeRegions",
7143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MeteringRectangle(/*x*/1, /*y*/2, /*width*/100, /*height*/200, /*weight*/5),
7153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                /* xmin, ymin, xmax, ymax, weight */
7163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(1, 2, 1 + 100, 2 + 200, 5));
7173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
7183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x 5 x area_count
7193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.control.afRegions",
7203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new MeteringRectangle[] {
7213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new MeteringRectangle(/*x*/5, /*y*/6, /*width*/123, /*height*/456, /*weight*/7),
7223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new MeteringRectangle(/*x*/7, /*y*/8, /*width*/456, /*height*/999, /*weight*/6),
7233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new MeteringRectangle(/*x*/1, /*y*/2, /*width*/100, /*height*/200, /*weight*/5)
7243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                },
7253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(
7263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        5, 6, 5 + 123, 6 + 456, 7,
7273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        7, 8, 7 + 456, 8 + 999, 6,
7283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        1, 2, 1 + 100, 2 + 200, 5
7293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        ));
7303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
7313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
7323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
73312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    public void testReadWriteHighSpeedVideoConfiguration() {
734b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He        // int32 x 5 x 1
73512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        checkKeyMarshal("android.control.availableHighSpeedVideoConfigurations",
73612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                new HighSpeedVideoConfiguration(
737b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He                        /*width*/1000, /*height*/255, /*fpsMin*/30, /*fpsMax*/200,
738b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He                        /*batchSizeMax*/8),
73912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                /* width, height, fpsMin, fpsMax */
740b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He                toByteArray(1000, 255, 30, 200, 8));
74112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh
742b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He        // int32 x 5 x 3
74312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        checkKeyMarshal("android.control.availableHighSpeedVideoConfigurations",
74412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                new HighSpeedVideoConfiguration[] {
74512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                    new HighSpeedVideoConfiguration(
746b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He                            /*width*/1280, /*height*/720, /*fpsMin*/60, /*fpsMax*/120,
747b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He                            /*batchSizeMax*/8),
74812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                    new HighSpeedVideoConfiguration(
749b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He                            /*width*/123, /*height*/456, /*fpsMin*/1, /*fpsMax*/200,
750b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He                            /*batchSizeMax*/4),
75112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                    new HighSpeedVideoConfiguration(
752b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He                            /*width*/4096, /*height*/2592, /*fpsMin*/30, /*fpsMax*/60,
753b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He                            /*batchSizeMax*/2)
75412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                },
75512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                toByteArray(
756b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He                        1280, 720, 60, 120, 8,
757b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He                        123, 456, 1, 200, 4,
758b1300e39c7974937d563b3ec62f5246248a157b3Zhijun He                        4096, 2592, 30, 60, 2
75912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        ));
76012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    }
76112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh
76212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    @SmallTest
7633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteColorSpaceTransform() {
7643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // rational x 3 x 3
7653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.colorCorrection.transform",
7663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new ColorSpaceTransform(new Rational[] {
7673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        new Rational(1, 2), new Rational(3, 4), new Rational(5, 6),
7683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        new Rational(7, 8), new Rational(8, 9), new Rational(10, 11),
7693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        new Rational(1, 5), new Rational(2, 8), new Rational(3, 9),
7703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                }),
7713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(
7723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        1, 2, 3, 4, 5, 6,
7733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        7, 8, 8, 9, 10, 11,
77412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                        1, 5, 1, 4, 1, 3));
7753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
7763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
7773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
7783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWritePoint() {
7793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x 2 [actually 'x n' but pretend it's a single value for now]
7803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.statistics.hotPixelMap",
7813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new Point(1, 2),
7823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(1, 2));
7833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
7843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x 2 x samples
7853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.statistics.hotPixelMap",
7863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new Point[] {
7873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new Point(1, 2),
7883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new Point(3, 4),
7893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new Point(5, 6),
7903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new Point(7, 8),
7913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                },
7923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(
7933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        1, 2,
7943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        3, 4,
7953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        5, 6,
7963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        7, 8)
7973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        );
7983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
7993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
8013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWritePointF() {
8023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // float x 2 [actually 'x samples' but pretend it's a single value for now]
8033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal(
8043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                "android.sensor.profileToneCurve",
8053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new PointF(1.0f, 2.0f),
8063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(1.0f, 2.0f));
8073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // float x 2 x samples
8093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.sensor.profileToneCurve",
8103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new PointF[] {
8113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new PointF(1.0f, 2.0f),
8123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new PointF(3.0f, 4.0f),
8133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new PointF(5.0f, 6.0f),
8143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new PointF(7.0f, 8.0f),
8153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                },
8163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(
8173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        1.0f, 2.0f,
8183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        3.0f, 4.0f,
8193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        5.0f, 6.0f,
8203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        7.0f, 8.0f));
8213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
8223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
8245743868e15c88d2886915163652a1571a218bf39Igor Murashkin    public void testReadWritePair() {
8255743868e15c88d2886915163652a1571a218bf39Igor Murashkin        // float x 2
8265743868e15c88d2886915163652a1571a218bf39Igor Murashkin        checkKeyMarshal("android.lens.focusRange",
8275743868e15c88d2886915163652a1571a218bf39Igor Murashkin                new TypeReference<Pair<Float, Float>>() {{ }},
8285743868e15c88d2886915163652a1571a218bf39Igor Murashkin                Pair.create(1.0f / 2.0f, 1.0f / 3.0f),
8295743868e15c88d2886915163652a1571a218bf39Igor Murashkin                toByteArray(1.0f / 2.0f, 1.0f / 3.0f));
8305743868e15c88d2886915163652a1571a218bf39Igor Murashkin
8315743868e15c88d2886915163652a1571a218bf39Igor Murashkin        // byte, int (fake from TYPE_BYTE)
8325743868e15c88d2886915163652a1571a218bf39Igor Murashkin        // This takes advantage of the TYPE_BYTE -> int marshaler designed for enums.
8335743868e15c88d2886915163652a1571a218bf39Igor Murashkin        checkKeyMarshal("android.flash.mode",
8345743868e15c88d2886915163652a1571a218bf39Igor Murashkin                new TypeReference<Pair<Byte, Integer>>() {{ }},
8355743868e15c88d2886915163652a1571a218bf39Igor Murashkin                Pair.create((byte)123, 22),
8365743868e15c88d2886915163652a1571a218bf39Igor Murashkin                toByteArray((byte)123, (byte)22));
8375743868e15c88d2886915163652a1571a218bf39Igor Murashkin    }
8385743868e15c88d2886915163652a1571a218bf39Igor Murashkin
8395743868e15c88d2886915163652a1571a218bf39Igor Murashkin    @SmallTest
8403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteRange() {
8413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x 2
8423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.control.aeTargetFpsRange",
8433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new TypeReference<Range<Integer>>() {{ }},
8443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                Range.create(123, 456),
8453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(123, 456));
8463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int64 x 2
8483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.sensor.info.exposureTimeRange",
8493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new TypeReference<Range<Long>>() {{ }},
8503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                Range.create(123L, 456L),
8513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(123L, 456L));
8523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
8533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
8553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteStreamConfiguration() {
8563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x 4 x n
8573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.scaler.availableStreamConfigurations",
8583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new StreamConfiguration[] {
8593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new StreamConfiguration(ImageFormat.YUV_420_888, 640, 480, /*input*/false),
8603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new StreamConfiguration(ImageFormat.RGB_565, 320, 240, /*input*/true),
8613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                },
8623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(
8633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        ImageFormat.YUV_420_888, 640, 480, /*input*/0,
8643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        ImageFormat.RGB_565, 320, 240, /*input*/1)
8653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        );
8663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
8673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
8693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteStreamConfigurationDuration() {
8703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // Avoid sign extending ints when converting to a long
8713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        final long MASK_UNSIGNED_INT = 0x00000000ffffffffL;
8723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int64 x 4 x n
8743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.scaler.availableMinFrameDurations",
8753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new StreamConfigurationDuration[] {
8763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new StreamConfigurationDuration(
8773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                            ImageFormat.YUV_420_888, 640, 480, /*duration*/123L),
8783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new StreamConfigurationDuration(
8793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                            ImageFormat.RGB_565, 320, 240, /*duration*/345L),
8803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                },
8813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(
8823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        ImageFormat.YUV_420_888 & MASK_UNSIGNED_INT, 640L, 480L, /*duration*/123L,
8833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        ImageFormat.RGB_565 & MASK_UNSIGNED_INT, 320L, 240L, /*duration*/345L)
8843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        );
8853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
8863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
8893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteReprocessFormatsMap() {
8903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // final int RAW_OPAQUE = 0x24; // TODO: add RAW_OPAQUE to ImageFormat
8923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        final int RAW16 = ImageFormat.RAW_SENSOR;
8933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        final int YUV_420_888 = ImageFormat.YUV_420_888;
8943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        final int BLOB = 0x21;
8953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // TODO: also test HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED as an output
8973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        int[] contents = new int[] {
8989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                YUV_420_888, 3, YUV_420_888, ImageFormat.NV21, BLOB,
8993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                RAW16, 2, YUV_420_888, BLOB,
9009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        };
9023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
9033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x n
9049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Key<ReprocessFormatsMap> key = new Key<ReprocessFormatsMap>(
9059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                "android.scaler.availableInputOutputFormatsMap", ReprocessFormatsMap.class);
9069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mMetadata.writeValues(key.getTag(), toByteArray(contents));
9079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        ReprocessFormatsMap map = mMetadata.get(key);
9099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        /*
9119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * Make sure the inputs/outputs were what we expected.
9129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * - Use public image format constants here.
9139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         */
9149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int[] expectedInputs = new int[] {
9169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                YUV_420_888, RAW16
9179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
9189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertArrayEquals(expectedInputs, map.getInputs());
9199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int[] expectedYuvOutputs = new int[] {
9219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                YUV_420_888, ImageFormat.NV21, ImageFormat.JPEG,
9229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
9239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertArrayEquals(expectedYuvOutputs, map.getOutputs(ImageFormat.YUV_420_888));
9249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int[] expectedRaw16Outputs = new int[] {
9269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                YUV_420_888, ImageFormat.JPEG,
9279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
9289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertArrayEquals(expectedRaw16Outputs, map.getOutputs(ImageFormat.RAW_SENSOR));
9299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // Finally, do a round-trip check as a sanity
9319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkKeyMarshal(
9329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                "android.scaler.availableInputOutputFormatsMap",
9333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new ReprocessFormatsMap(contents),
9343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(contents)
9353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        );
9363710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin    }
9373710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9383710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin    @SmallTest
9393710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin    public void testReadWriteString() {
9403710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        // (byte) string
9413710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        Key<String> gpsProcessingMethodKey =
9423710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin                new Key<String>("android.jpeg.gpsProcessingMethod", String.class);
9433710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9443710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        String helloWorld = new String("HelloWorld");
9453710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        byte[] helloWorldBytes = new byte[] {
9463710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin                'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '\0' };
9473710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9483710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        mMetadata.set(gpsProcessingMethodKey, helloWorld);
9493710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9503710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        String actual = mMetadata.get(gpsProcessingMethodKey);
9513710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        assertEquals(helloWorld, actual);
9523710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9533710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        byte[] actualBytes = mMetadata.readValues(getTag(gpsProcessingMethodKey.getName()));
9543710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        assertArrayEquals(helloWorldBytes, actualBytes);
9553710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9563710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        // Does not yet test as a string[] since we don't support that in native code.
9573710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9583710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        // (byte) string
9593710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        Key<String[]> gpsProcessingMethodKeyArray =
9603710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin                new Key<String[]>("android.jpeg.gpsProcessingMethod", String[].class);
9613710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9623710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        String[] gpsStrings = new String[] { "HelloWorld", "FooBar", "Shazbot" };
9633710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        byte[] gpsBytes = new byte[] {
9643710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin                'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '\0',
9653710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin                'F', 'o', 'o', 'B', 'a', 'r', '\0',
9663710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin                'S', 'h', 'a', 'z', 'b', 'o', 't', '\0'};
9673710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9683710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        mMetadata.set(gpsProcessingMethodKeyArray, gpsStrings);
9693710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9703710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        String[] actualArray = mMetadata.get(gpsProcessingMethodKeyArray);
9713710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        assertArrayEquals(gpsStrings, actualArray);
9723710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9733710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        byte[] actualBytes2 = mMetadata.readValues(getTag(gpsProcessingMethodKeyArray.getName()));
9743710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        assertArrayEquals(gpsBytes, actualBytes2);
9753710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin    }
9763710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
977b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    @SmallTest
978b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    public void testReadWriteOverride() {
979b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        //
980b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        // android.scaler.availableFormats (int x n array)
981b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        //
982b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int[] availableFormats = new int[] {
983b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x20,       // RAW_SENSOR
984b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x32315659, // YV12
985b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x11,       // YCrCb_420_SP
986b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x100,      // ImageFormat.JPEG
987b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x22,       // IMPLEMENTATION_DEFINED
988b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x23,       // YCbCr_420_888
989b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        };
990b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int[] expectedIntValues = new int[] {
991b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x20,       // RAW_SENSOR
992b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x32315659, // YV12
993b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x11,       // YCrCb_420_SP
994b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x21,       // BLOB
995b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x22,       // IMPLEMENTATION_DEFINED
996b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x23,       // YCbCr_420_888
997b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        };
998b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int availableFormatTag = CameraMetadataNative.getTag("android.scaler.availableFormats");
999b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
1000d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        Key<int[]> formatKey = CameraCharacteristics.SCALER_AVAILABLE_FORMATS.getNativeKey();
1001b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
10028d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        validateArrayMetadataReadWriteOverride(formatKey, availableFormats,
10038d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He                expectedIntValues, availableFormatTag);
1004b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
10058d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        //
1006b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        // android.statistics.faces (Face x n array)
1007b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        //
1008b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int[] expectedFaceIds = new int[] {1, 2, 3, 4, 5};
1009b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        byte[] expectedFaceScores = new byte[] {10, 20, 30, 40, 50};
1010b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int numFaces = expectedFaceIds.length;
1011b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        Rect[] expectedRects = new Rect[numFaces];
1012b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        for (int i = 0; i < numFaces; i++) {
1013b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            expectedRects[i] = new Rect(i*4 + 1, i * 4 + 2, i * 4 + 3, i * 4 + 4);
1014b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
1015b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int[] expectedFaceLM = new int[] {
1016b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                1, 2, 3, 4, 5, 6,
1017b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                7, 8, 9, 10, 11, 12,
1018b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                13, 14, 15, 16, 17, 18,
1019b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                19, 20, 21, 22, 23, 24,
1020b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                25, 26, 27, 28, 29, 30,
1021b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        };
1022b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        Point[] expectedFaceLMPoints = new Point[numFaces * 3];
1023b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        for (int i = 0; i < numFaces; i++) {
1024b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            expectedFaceLMPoints[i*3] = new Point(expectedFaceLM[i*6], expectedFaceLM[i*6+1]);
1025b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            expectedFaceLMPoints[i*3+1] = new Point(expectedFaceLM[i*6+2], expectedFaceLM[i*6+3]);
1026b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            expectedFaceLMPoints[i*3+2] = new Point(expectedFaceLM[i*6+4], expectedFaceLM[i*6+5]);
1027b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
1028b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
1029b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        /**
1030b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He         * Read - FACE_DETECT_MODE == FULL
1031b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He         */
1032b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_DETECT_MODE,
1033b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL);
1034b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_IDS, expectedFaceIds);
1035b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_SCORES, expectedFaceScores);
1036b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_RECTANGLES, expectedRects);
1037b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_LANDMARKS, expectedFaceLM);
1038b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        Face[] resultFaces = mMetadata.get(CaptureResult.STATISTICS_FACES);
1039b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        assertEquals(numFaces, resultFaces.length);
1040b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        for (int i = 0; i < numFaces; i++) {
1041b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedFaceIds[i], resultFaces[i].getId());
1042b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedFaceScores[i], resultFaces[i].getScore());
1043b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedRects[i], resultFaces[i].getBounds());
1044b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedFaceLMPoints[i*3], resultFaces[i].getLeftEyePosition());
1045b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedFaceLMPoints[i*3+1], resultFaces[i].getRightEyePosition());
1046b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedFaceLMPoints[i*3+2], resultFaces[i].getMouthPosition());
1047b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
1048b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
1049b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        /**
1050b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He         * Read - FACE_DETECT_MODE == SIMPLE
1051b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He         */
1052b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_DETECT_MODE,
1053b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE);
1054b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_SCORES, expectedFaceScores);
1055b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_RECTANGLES, expectedRects);
1056b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        Face[] resultSimpleFaces = mMetadata.get(CaptureResult.STATISTICS_FACES);
1057b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        assertEquals(numFaces, resultSimpleFaces.length);
1058b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        for (int i = 0; i < numFaces; i++) {
1059b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(Face.ID_UNSUPPORTED, resultSimpleFaces[i].getId());
1060b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedFaceScores[i], resultSimpleFaces[i].getScore());
1061b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedRects[i], resultSimpleFaces[i].getBounds());
1062b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertNull(resultSimpleFaces[i].getLeftEyePosition());
1063b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertNull(resultSimpleFaces[i].getRightEyePosition());
1064b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertNull(resultSimpleFaces[i].getMouthPosition());
1065b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
1066b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
10678490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        /**
10688490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh         * Read/Write TonemapCurve
10698490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh         */
10708490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] red = new float[] {0.0f, 0.0f, 1.0f, 1.0f};
10718490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] green = new float[] {0.0f, 1.0f, 1.0f, 0.0f};
10728490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] blue = new float[] {
10738490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh                0.0000f, 0.0000f, 0.0667f, 0.2920f, 0.1333f, 0.4002f, 0.2000f, 0.4812f,
10748490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh                0.2667f, 0.5484f, 0.3333f, 0.6069f, 0.4000f, 0.6594f, 0.4667f, 0.7072f,
10758490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh                0.5333f, 0.7515f, 0.6000f, 0.7928f, 0.6667f, 0.8317f, 0.7333f, 0.8685f,
10768490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh                0.8000f, 0.9035f, 0.8667f, 0.9370f, 0.9333f, 0.9691f, 1.0000f, 1.0000f};
10778490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        TonemapCurve tcIn = new TonemapCurve(red, green, blue);
10788490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        mMetadata.set(CaptureResult.TONEMAP_CURVE, tcIn);
10798490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] redOut = mMetadata.get(CaptureResult.TONEMAP_CURVE_RED);
10808490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] greenOut = mMetadata.get(CaptureResult.TONEMAP_CURVE_GREEN);
10818490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] blueOut = mMetadata.get(CaptureResult.TONEMAP_CURVE_BLUE);
108282984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        assertArrayEquals(red, redOut);
108382984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        assertArrayEquals(green, greenOut);
108482984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        assertArrayEquals(blue, blueOut);
10858490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        TonemapCurve tcOut = mMetadata.get(CaptureResult.TONEMAP_CURVE);
108682984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        assertEquals(tcIn, tcOut);
108782984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        mMetadata.set(CaptureResult.TONEMAP_CURVE_GREEN, null);
108882984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        // If any of channel has null curve, return a null TonemapCurve
108982984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        assertNull(mMetadata.get(CaptureResult.TONEMAP_CURVE));
1090b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    }
10918d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
10928d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He    /**
10939c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Set the raw native value of the available stream configurations; ensure that
10949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * the read-out managed value is consistent with what we write in.
10959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
10969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    @SmallTest
10979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public void testOverrideStreamConfigurationMap() {
10989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        /*
11009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * First, write all the raw values:
11019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * - availableStreamConfigurations
11029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * - availableMinFrameDurations
11039c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * - availableStallDurations
11049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         *
11059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * Then, read this out as a synthetic multi-key 'streamConfigurationMap'
11069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         *
11079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * Finally, validate that the map was unmarshaled correctly
11089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * and is converting the internal formats to public formats properly.
11099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         */
11109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // android.scaler.availableStreamConfigurations (int x n x 4 array)
11139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        final int OUTPUT = 0;
11159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        final int INPUT = 1;
11169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int[] rawAvailableStreamConfigs = new int[] {
11179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x20, 3280, 2464, OUTPUT, // RAW16
11189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3264, 2448, OUTPUT, // YCbCr_420_888
11199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3200, 2400, OUTPUT, // YCbCr_420_888
11209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 3264, 2448, OUTPUT, // BLOB
11219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 3200, 2400, OUTPUT, // BLOB
11229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 2592, 1944, OUTPUT, // BLOB
11239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 2048, 1536, OUTPUT, // BLOB
11249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 1920, 1080, OUTPUT, // BLOB
11259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x22, 640, 480, OUTPUT,   // IMPLEMENTATION_DEFINED
11269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x20, 320, 240, INPUT,   // RAW16
11279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
11289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Key<StreamConfiguration[]> configKey =
1129d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS.getNativeKey();
11309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mMetadata.writeValues(configKey.getTag(),
11319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                toByteArray(rawAvailableStreamConfigs));
11329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // android.scaler.availableMinFrameDurations (int x n x 4 array)
11359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        long[] expectedAvailableMinDurations = new long[] {
11379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x20, 3280, 2464, 33333331, // RAW16
11389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3264, 2448, 33333332, // YCbCr_420_888
11399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3200, 2400, 33333333, // YCbCr_420_888
11409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 3264, 2448, 33333334, // ImageFormat.JPEG
11419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 3200, 2400, 33333335, // ImageFormat.JPEG
11429c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 2592, 1944, 33333336, // ImageFormat.JPEG
11439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 2048, 1536, 33333337, // ImageFormat.JPEG
11449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 1920, 1080, 33333338  // ImageFormat.JPEG
11459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
11469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        long[] rawAvailableMinDurations = new long[] {
11479c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x20, 3280, 2464, 33333331, // RAW16
11489c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3264, 2448, 33333332, // YCbCr_420_888
11499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3200, 2400, 33333333, // YCbCr_420_888
11509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 3264, 2448, 33333334, // BLOB
11519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 3200, 2400, 33333335, // BLOB
11529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 2592, 1944, 33333336, // BLOB
11539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 2048, 1536, 33333337, // BLOB
11549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 1920, 1080, 33333338  // BLOB
11559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
11569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Key<StreamConfigurationDuration[]> durationKey =
1157d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS.getNativeKey();
11589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mMetadata.writeValues(durationKey.getTag(),
11599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                toByteArray(rawAvailableMinDurations));
11609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // android.scaler.availableStallDurations (int x n x 4 array)
11639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        long[] expectedAvailableStallDurations = new long[] {
11659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x20, 3280, 2464, 0,        // RAW16
11669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3264, 2448, 0,        // YCbCr_420_888
11679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3200, 2400, 0,        // YCbCr_420_888
11689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 3264, 2448, 33333334, // ImageFormat.JPEG
11699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 3200, 2400, 33333335, // ImageFormat.JPEG
11709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 2592, 1944, 33333336, // ImageFormat.JPEG
11719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 2048, 1536, 33333337, // ImageFormat.JPEG
11729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 1920, 1080, 33333338  // ImageFormat.JPEG
11739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
11749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // Note: RAW16 and YUV_420_888 omitted intentionally; omitted values should default to 0
11759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        long[] rawAvailableStallDurations = new long[] {
11769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 3264, 2448, 33333334, // BLOB
11779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 3200, 2400, 33333335, // BLOB
11789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 2592, 1944, 33333336, // BLOB
11799c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 2048, 1536, 33333337, // BLOB
11809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 1920, 1080, 33333338  // BLOB
11819c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
11829c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Key<StreamConfigurationDuration[]> stallDurationKey =
1183d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                CameraCharacteristics.SCALER_AVAILABLE_STALL_DURATIONS.getNativeKey();
11849c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mMetadata.writeValues(stallDurationKey.getTag(),
11859c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                toByteArray(rawAvailableStallDurations));
11869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11889c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // android.scaler.streamConfigurationMap (synthetic as StreamConfigurationMap)
11899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        StreamConfigurationMap streamConfigMap = mMetadata.get(
11919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
11929c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11939c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // Inputs
11949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
11959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.RAW_SENSOR, 320, 240, /*output*/false);
11969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // Outputs
11989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
11999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 640, 480, /*output*/true);
12009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
12019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.JPEG, 1920, 1080, /*output*/true);
12029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
12039c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.JPEG, 2048, 1536, /*output*/true);
12049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
12059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.JPEG, 2592, 1944, /*output*/true);
12069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
12079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.JPEG, 3200, 2400, /*output*/true);
12089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
12099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.YUV_420_888, 3200, 2400, /*output*/true);
12109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
12119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.YUV_420_888, 3264, 2448, /*output*/true);
12129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
12139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.RAW_SENSOR, 3280, 2464, /*output*/true);
12149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
12159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // Min Frame Durations
12169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
12179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        final int DURATION_TUPLE_SIZE = 4;
12189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (int i = 0; i < expectedAvailableMinDurations.length; i += DURATION_TUPLE_SIZE) {
12199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            checkStreamConfigurationMapDurationByFormatSize(
12209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    streamConfigMap,
12219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    (int)expectedAvailableMinDurations[i],
12229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    (int)expectedAvailableMinDurations[i+1],
12239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    (int)expectedAvailableMinDurations[i+2],
12249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    Duration.MinFrame,
12259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    expectedAvailableMinDurations[i+3]);
12269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
12279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
12289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // Stall Frame Durations
12299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
12309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (int i = 0; i < expectedAvailableStallDurations.length; i += DURATION_TUPLE_SIZE) {
12319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            checkStreamConfigurationMapDurationByFormatSize(
12329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    streamConfigMap,
12339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    (int)expectedAvailableStallDurations[i],
12349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    (int)expectedAvailableStallDurations[i+1],
12359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    (int)expectedAvailableStallDurations[i+2],
12369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    Duration.Stall,
12379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    expectedAvailableStallDurations[i+3]);
12389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
12399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
12409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
124178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    private <T> void assertKeyValueEquals(T expected, CameraCharacteristics.Key<T> key) {
124278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(expected, key.getNativeKey());
124378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    }
124478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
124578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    private <T> void assertKeyValueEquals(T expected, Key<T> key) {
124678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        T actual = mMetadata.get(key);
124778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
124878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertEquals("Expected value for key " + key + " to match", expected, actual);
124978712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    }
125078712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
125178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    @SmallTest
125278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    public void testOverrideMaxRegions() {
125378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        // All keys are null before doing any writes.
125478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(null, CameraCharacteristics.CONTROL_MAX_REGIONS_AE);
125578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(null, CameraCharacteristics.CONTROL_MAX_REGIONS_AWB);
125678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(null, CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
125778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
125878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        mMetadata.set(CameraCharacteristics.CONTROL_MAX_REGIONS,
125978712a8bd7275542013ba099f33536eead0167fbIgor Murashkin                new int[] { /*AE*/1, /*AWB*/2, /*AF*/3 });
126078712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
126178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        // All keys are the expected value after doing a write
126278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(1, CameraCharacteristics.CONTROL_MAX_REGIONS_AE);
126378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(2, CameraCharacteristics.CONTROL_MAX_REGIONS_AWB);
126478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(3, CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
126578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    }
126678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
126778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    @SmallTest
126878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    public void testOverrideMaxNumOutputStreams() {
126978712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        // All keys are null before doing any writes.
127078712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(null, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW);
127178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(null, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC);
127278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(null, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING);
127378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
127478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        mMetadata.set(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS,
127578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin                new int[] { /*AE*/1, /*AWB*/2, /*AF*/3 });
127678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
127778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        // All keys are the expected value after doing a write
127878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(1, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW);
127978712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(2, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC);
128078712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(3, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING);
128178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    }
128278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
1283d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    @SmallTest
1284d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    public void testCaptureResult() {
1285d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        mMetadata.set(CaptureRequest.CONTROL_AE_MODE,
1286d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH);
1287d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
1288d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (VERBOSE) mMetadata.dumpToLog();
1289d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
1290d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        CaptureResult captureResult = new CaptureResult(mMetadata, /*sequenceId*/0);
1291d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
1292d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        List<CaptureResult.Key<?>> allKeys = captureResult.getKeys();
1293d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (VERBOSE) Log.v(TAG, "testCaptureResult: key list size " + allKeys);
1294d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        for (CaptureResult.Key<?> key : captureResult.getKeys()) {
1295d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            if (VERBOSE) {
1296d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                Log.v(TAG,
1297d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    "testCaptureResult: key " + key + " value" + captureResult.get(key));
1298d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            }
1299d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
1300d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
1301d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        assertTrue(allKeys.size() >= 1); // FIXME: android.statistics.faces counts as a key
1302d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        assertTrue(allKeys.contains(CaptureResult.CONTROL_AE_MODE));
1303d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
1304d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        assertEquals(CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH,
1305d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                (int)captureResult.get(CaptureResult.CONTROL_AE_MODE));
1306d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
1307d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
13089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static void checkStreamConfigurationMapByFormatSize(StreamConfigurationMap configMap,
13099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            int format, int width, int height,
13109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            boolean output) {
13119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        /** arbitrary class for which StreamConfigurationMap#isOutputSupportedFor(Class) is true */
13139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        final Class<?> IMPLEMENTATION_DEFINED_OUTPUT_CLASS = SurfaceTexture.class;
13149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        android.util.Size[] sizes;
13169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int[] formats;
13179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (output) {
13199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
13209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                sizes = configMap.getOutputSizes(IMPLEMENTATION_DEFINED_OUTPUT_CLASS);
13219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                // in this case the 'is output format supported' is vacuously true
13229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                formats = new int[] { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED };
13239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            } else {
13249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                sizes = configMap.getOutputSizes(format);
13259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                formats = configMap.getOutputFormats();
13269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                assertTrue("Format must be supported by stream configuration map",
13279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                        configMap.isOutputSupportedFor(format));
13289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            }
13299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        } else {
13309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            // NOTE: No function to do input sizes from IMPL_DEFINED, so it would just fail for that
13319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            sizes = configMap.getInputSizes(format);
13329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            formats = configMap.getInputFormats();
13339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
13349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        android.util.Size expectedSize = new android.util.Size(width, height);
13369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertArrayContains(format, formats);
13389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertArrayContains(expectedSize, sizes);
13399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
13409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private enum Duration {
13429c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        MinFrame,
13439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Stall
13449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
13459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static void checkStreamConfigurationMapDurationByFormatSize(
13479c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            StreamConfigurationMap configMap,
13489c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            int format, int width, int height, Duration durationKind, long expectedDuration) {
13499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        /** arbitrary class for which StreamConfigurationMap#isOutputSupportedFor(Class) is true */
13519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        final Class<?> IMPLEMENTATION_DEFINED_OUTPUT_CLASS = SurfaceTexture.class;
13529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        long actualDuration;
13549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        android.util.Size size = new android.util.Size(width, height);
13569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        switch (durationKind) {
13579c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case MinFrame:
13589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
13599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    actualDuration = configMap.getOutputMinFrameDuration(
13609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                            IMPLEMENTATION_DEFINED_OUTPUT_CLASS, size);
13619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                } else {
13629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    actualDuration = configMap.getOutputMinFrameDuration(format, size);
13639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                }
13649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                break;
13669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case Stall:
13679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
13689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    actualDuration = configMap.getOutputStallDuration(
13699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                            IMPLEMENTATION_DEFINED_OUTPUT_CLASS, size);
13709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                } else {
13719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    actualDuration = configMap.getOutputStallDuration(format, size);
13729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                }
13739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                break;
13759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            default:
13769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                throw new AssertionError();
13779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
13789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13799c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertEquals("Expected " + durationKind + " to match actual value", expectedDuration,
13809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                actualDuration);
13819c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
13829c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13839c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
13848d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He     * Validate metadata array tag read/write override.
13858d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He     *
13868d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He     * <p>Only support long and int array for now, can be easily extend to support other
13878d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He     * primitive arrays.</p>
13888d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He     */
13899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private <T> void validateArrayMetadataReadWriteOverride(Key<T> key, T expectedWriteValues,
13909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            T expectedReadValues, int tag) {
13919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Class<?> type = expectedWriteValues.getClass();
13928d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        if (!type.isArray()) {
13938d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            throw new IllegalArgumentException("This function expects an key with array type");
13948d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        } else if (type != int[].class && type != long[].class) {
13958d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            throw new IllegalArgumentException("This function expects long or int array values");
13968d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        }
13978d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
13988d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        // Write
13999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mMetadata.set(key, expectedWriteValues);
14008d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
14018d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        byte[] readOutValues = mMetadata.readValues(tag);
14028d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
14038d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        ByteBuffer bf = ByteBuffer.wrap(readOutValues).order(ByteOrder.nativeOrder());
14048d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
14059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int readValuesLength = Array.getLength(expectedReadValues);
14068d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        int readValuesNumBytes = readValuesLength * 4;
14078d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        if (type == long[].class) {
14088d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            readValuesNumBytes = readValuesLength * 8;
14098d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        }
14108d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
14118d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        assertEquals(readValuesNumBytes, readOutValues.length);
14128d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        for (int i = 0; i < readValuesLength; ++i) {
14138d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            if (type == int[].class) {
14149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                assertEquals(Array.getInt(expectedReadValues, i), bf.getInt());
14158d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            } else if (type == long[].class) {
14169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                assertEquals(Array.getLong(expectedReadValues, i), bf.getLong());
14178d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            }
14188d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        }
14198d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
14208d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        // Read
14218d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        byte[] readOutValuesAsByteArray = new byte[readValuesNumBytes];
14228d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        ByteBuffer readOutValuesByteBuffer =
14238d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He                ByteBuffer.wrap(readOutValuesAsByteArray).order(ByteOrder.nativeOrder());
14248d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        for (int i = 0; i < readValuesLength; ++i) {
14258d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            if (type == int[].class) {
14269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                readOutValuesByteBuffer.putInt(Array.getInt(expectedReadValues, i));
14278d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            } else if (type == long[].class) {
14289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                readOutValuesByteBuffer.putLong(Array.getLong(expectedReadValues, i));
14298d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            }
14308d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        }
14318d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        mMetadata.writeValues(tag, readOutValuesAsByteArray);
14328d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
14338d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        T result = mMetadata.get(key);
14348d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        assertNotNull(key.getName() + " result shouldn't be null", result);
14359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertArrayEquals(expectedWriteValues, result);
14368d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He    }
14373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
14383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    // TODO: move somewhere else
14393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
14403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testToByteArray() {
14413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertArrayEquals(new byte[] { 5, 0, 0, 0, 6, 0, 0, 0 },
14423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(5, 6));
14433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertArrayEquals(new byte[] { 5, 0, 6, 0, },
14443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray((short)5, (short)6));
14453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertArrayEquals(new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,
14463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                                        (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,},
14473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(~0, ~0));
14483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
14493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertArrayEquals(new byte[] { (byte)0xAB, (byte)0xFF, 0, 0,
14503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                0x0D, (byte)0xF0, (byte)0xAD, (byte)0xDE },
14513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(0xFFAB, 0xDEADF00D));
14523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
145370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
1454