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,
1573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_MODE));
1583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertEquals(TYPE_RATIONAL,
1593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_TRANSFORM));
1603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertEquals(TYPE_FLOAT,
1613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_GAINS));
1623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertEquals(TYPE_BYTE,
1633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_ANTIBANDING_MODE));
164b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        assertEquals(TYPE_INT32,
16570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala                CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION));
166b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
167b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        try {
16870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            CameraMetadataNative.getNativeType(0xDEADF00D);
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() {
73412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        // int32 x 4 x 1
73512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        checkKeyMarshal("android.control.availableHighSpeedVideoConfigurations",
73612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                new HighSpeedVideoConfiguration(
73712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                        /*width*/1000, /*height*/255, /*fpsMin*/30, /*fpsMax*/200),
73812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                /* width, height, fpsMin, fpsMax */
73912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                toByteArray(1000, 255, 30, 200));
74012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh
74112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        // int32 x 4 x 3
74212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        checkKeyMarshal("android.control.availableHighSpeedVideoConfigurations",
74312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                new HighSpeedVideoConfiguration[] {
74412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                    new HighSpeedVideoConfiguration(
74512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                            /*width*/1280, /*height*/720, /*fpsMin*/60, /*fpsMax*/120),
74612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                    new HighSpeedVideoConfiguration(
74712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                            /*width*/123, /*height*/456, /*fpsMin*/1, /*fpsMax*/200),
74812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                    new HighSpeedVideoConfiguration(
74912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                            /*width*/4096, /*height*/2592, /*fpsMin*/30, /*fpsMax*/60)
75012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                },
75112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                toByteArray(
75212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                        1280, 720, 60, 120,
75312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                        123, 456, 1, 200,
75412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                        4096, 2592, 30, 60
75512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        ));
75612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    }
75712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh
75812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    @SmallTest
7593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteColorSpaceTransform() {
7603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // rational x 3 x 3
7613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.colorCorrection.transform",
7623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new ColorSpaceTransform(new Rational[] {
7633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        new Rational(1, 2), new Rational(3, 4), new Rational(5, 6),
7643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        new Rational(7, 8), new Rational(8, 9), new Rational(10, 11),
7653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        new Rational(1, 5), new Rational(2, 8), new Rational(3, 9),
7663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                }),
7673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(
7683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        1, 2, 3, 4, 5, 6,
7693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        7, 8, 8, 9, 10, 11,
77012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                        1, 5, 1, 4, 1, 3));
7713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
7723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
7733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
7743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWritePoint() {
7753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x 2 [actually 'x n' but pretend it's a single value for now]
7763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.statistics.hotPixelMap",
7773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new Point(1, 2),
7783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(1, 2));
7793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
7803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x 2 x samples
7813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.statistics.hotPixelMap",
7823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new Point[] {
7833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new Point(1, 2),
7843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new Point(3, 4),
7853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new Point(5, 6),
7863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new Point(7, 8),
7873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                },
7883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(
7893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        1, 2,
7903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        3, 4,
7913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        5, 6,
7923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        7, 8)
7933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        );
7943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
7953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
7963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
7973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWritePointF() {
7983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // float x 2 [actually 'x samples' but pretend it's a single value for now]
7993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal(
8003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                "android.sensor.profileToneCurve",
8013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new PointF(1.0f, 2.0f),
8023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(1.0f, 2.0f));
8033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // float x 2 x samples
8053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.sensor.profileToneCurve",
8063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new PointF[] {
8073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new PointF(1.0f, 2.0f),
8083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new PointF(3.0f, 4.0f),
8093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new PointF(5.0f, 6.0f),
8103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new PointF(7.0f, 8.0f),
8113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                },
8123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(
8133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        1.0f, 2.0f,
8143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        3.0f, 4.0f,
8153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        5.0f, 6.0f,
8163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        7.0f, 8.0f));
8173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
8183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
8205743868e15c88d2886915163652a1571a218bf39Igor Murashkin    public void testReadWritePair() {
8215743868e15c88d2886915163652a1571a218bf39Igor Murashkin        // float x 2
8225743868e15c88d2886915163652a1571a218bf39Igor Murashkin        checkKeyMarshal("android.lens.focusRange",
8235743868e15c88d2886915163652a1571a218bf39Igor Murashkin                new TypeReference<Pair<Float, Float>>() {{ }},
8245743868e15c88d2886915163652a1571a218bf39Igor Murashkin                Pair.create(1.0f / 2.0f, 1.0f / 3.0f),
8255743868e15c88d2886915163652a1571a218bf39Igor Murashkin                toByteArray(1.0f / 2.0f, 1.0f / 3.0f));
8265743868e15c88d2886915163652a1571a218bf39Igor Murashkin
8275743868e15c88d2886915163652a1571a218bf39Igor Murashkin        // byte, int (fake from TYPE_BYTE)
8285743868e15c88d2886915163652a1571a218bf39Igor Murashkin        // This takes advantage of the TYPE_BYTE -> int marshaler designed for enums.
8295743868e15c88d2886915163652a1571a218bf39Igor Murashkin        checkKeyMarshal("android.flash.mode",
8305743868e15c88d2886915163652a1571a218bf39Igor Murashkin                new TypeReference<Pair<Byte, Integer>>() {{ }},
8315743868e15c88d2886915163652a1571a218bf39Igor Murashkin                Pair.create((byte)123, 22),
8325743868e15c88d2886915163652a1571a218bf39Igor Murashkin                toByteArray((byte)123, (byte)22));
8335743868e15c88d2886915163652a1571a218bf39Igor Murashkin    }
8345743868e15c88d2886915163652a1571a218bf39Igor Murashkin
8355743868e15c88d2886915163652a1571a218bf39Igor Murashkin    @SmallTest
8363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteRange() {
8373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x 2
8383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.control.aeTargetFpsRange",
8393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new TypeReference<Range<Integer>>() {{ }},
8403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                Range.create(123, 456),
8413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(123, 456));
8423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int64 x 2
8443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.sensor.info.exposureTimeRange",
8453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new TypeReference<Range<Long>>() {{ }},
8463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                Range.create(123L, 456L),
8473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(123L, 456L));
8483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
8493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
8513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteStreamConfiguration() {
8523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x 4 x n
8533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.scaler.availableStreamConfigurations",
8543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new StreamConfiguration[] {
8553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new StreamConfiguration(ImageFormat.YUV_420_888, 640, 480, /*input*/false),
8563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new StreamConfiguration(ImageFormat.RGB_565, 320, 240, /*input*/true),
8573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                },
8583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(
8593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        ImageFormat.YUV_420_888, 640, 480, /*input*/0,
8603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        ImageFormat.RGB_565, 320, 240, /*input*/1)
8613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        );
8623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
8633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
8653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteStreamConfigurationDuration() {
8663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // Avoid sign extending ints when converting to a long
8673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        final long MASK_UNSIGNED_INT = 0x00000000ffffffffL;
8683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int64 x 4 x n
8703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        checkKeyMarshal("android.scaler.availableMinFrameDurations",
8713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new StreamConfigurationDuration[] {
8723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new StreamConfigurationDuration(
8733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                            ImageFormat.YUV_420_888, 640, 480, /*duration*/123L),
8743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    new StreamConfigurationDuration(
8753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                            ImageFormat.RGB_565, 320, 240, /*duration*/345L),
8763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                },
8773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(
8783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        ImageFormat.YUV_420_888 & MASK_UNSIGNED_INT, 640L, 480L, /*duration*/123L,
8793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                        ImageFormat.RGB_565 & MASK_UNSIGNED_INT, 320L, 240L, /*duration*/345L)
8803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        );
8813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
8823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
8853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testReadWriteReprocessFormatsMap() {
8863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // final int RAW_OPAQUE = 0x24; // TODO: add RAW_OPAQUE to ImageFormat
8883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        final int RAW16 = ImageFormat.RAW_SENSOR;
8893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        final int YUV_420_888 = ImageFormat.YUV_420_888;
8903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        final int BLOB = 0x21;
8913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8929c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // TODO: also test HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED as an output
8933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        int[] contents = new int[] {
8949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                YUV_420_888, 3, YUV_420_888, ImageFormat.NV21, BLOB,
8953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                RAW16, 2, YUV_420_888, BLOB,
8969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
8973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        };
8983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
8993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // int32 x n
9009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Key<ReprocessFormatsMap> key = new Key<ReprocessFormatsMap>(
9019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                "android.scaler.availableInputOutputFormatsMap", ReprocessFormatsMap.class);
9029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mMetadata.writeValues(key.getTag(), toByteArray(contents));
9039c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        ReprocessFormatsMap map = mMetadata.get(key);
9059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        /*
9079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * Make sure the inputs/outputs were what we expected.
9089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * - Use public image format constants here.
9099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         */
9109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int[] expectedInputs = new int[] {
9129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                YUV_420_888, RAW16
9139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
9149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertArrayEquals(expectedInputs, map.getInputs());
9159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int[] expectedYuvOutputs = new int[] {
9179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                YUV_420_888, ImageFormat.NV21, ImageFormat.JPEG,
9189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
9199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertArrayEquals(expectedYuvOutputs, map.getOutputs(ImageFormat.YUV_420_888));
9209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int[] expectedRaw16Outputs = new int[] {
9229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                YUV_420_888, ImageFormat.JPEG,
9239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
9249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertArrayEquals(expectedRaw16Outputs, map.getOutputs(ImageFormat.RAW_SENSOR));
9259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // Finally, do a round-trip check as a sanity
9279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkKeyMarshal(
9289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                "android.scaler.availableInputOutputFormatsMap",
9293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                new ReprocessFormatsMap(contents),
9303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(contents)
9313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        );
9323710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin    }
9333710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9343710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin    @SmallTest
9353710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin    public void testReadWriteString() {
9363710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        // (byte) string
9373710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        Key<String> gpsProcessingMethodKey =
9383710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin                new Key<String>("android.jpeg.gpsProcessingMethod", String.class);
9393710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9403710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        String helloWorld = new String("HelloWorld");
9413710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        byte[] helloWorldBytes = new byte[] {
9423710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin                'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '\0' };
9433710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9443710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        mMetadata.set(gpsProcessingMethodKey, helloWorld);
9453710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9463710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        String actual = mMetadata.get(gpsProcessingMethodKey);
9473710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        assertEquals(helloWorld, actual);
9483710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9493710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        byte[] actualBytes = mMetadata.readValues(getTag(gpsProcessingMethodKey.getName()));
9503710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        assertArrayEquals(helloWorldBytes, actualBytes);
9513710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9523710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        // Does not yet test as a string[] since we don't support that in native code.
9533710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9543710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        // (byte) string
9553710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        Key<String[]> gpsProcessingMethodKeyArray =
9563710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin                new Key<String[]>("android.jpeg.gpsProcessingMethod", String[].class);
9573710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9583710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        String[] gpsStrings = new String[] { "HelloWorld", "FooBar", "Shazbot" };
9593710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        byte[] gpsBytes = new byte[] {
9603710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin                'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '\0',
9613710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin                'F', 'o', 'o', 'B', 'a', 'r', '\0',
9623710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin                'S', 'h', 'a', 'z', 'b', 'o', 't', '\0'};
9633710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9643710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        mMetadata.set(gpsProcessingMethodKeyArray, gpsStrings);
9653710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9663710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        String[] actualArray = mMetadata.get(gpsProcessingMethodKeyArray);
9673710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        assertArrayEquals(gpsStrings, actualArray);
9683710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
9693710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        byte[] actualBytes2 = mMetadata.readValues(getTag(gpsProcessingMethodKeyArray.getName()));
9703710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        assertArrayEquals(gpsBytes, actualBytes2);
9713710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin    }
9723710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
973b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    @SmallTest
974b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    public void testReadWriteOverride() {
975b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        //
976b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        // android.scaler.availableFormats (int x n array)
977b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        //
978b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int[] availableFormats = new int[] {
979b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x20,       // RAW_SENSOR
980b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x32315659, // YV12
981b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x11,       // YCrCb_420_SP
982b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x100,      // ImageFormat.JPEG
983b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x22,       // IMPLEMENTATION_DEFINED
984b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x23,       // YCbCr_420_888
985b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        };
986b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int[] expectedIntValues = new int[] {
987b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x20,       // RAW_SENSOR
988b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x32315659, // YV12
989b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x11,       // YCrCb_420_SP
990b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x21,       // BLOB
991b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x22,       // IMPLEMENTATION_DEFINED
992b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                0x23,       // YCbCr_420_888
993b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        };
994b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int availableFormatTag = CameraMetadataNative.getTag("android.scaler.availableFormats");
995b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
996d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        Key<int[]> formatKey = CameraCharacteristics.SCALER_AVAILABLE_FORMATS.getNativeKey();
997b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
9988d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        validateArrayMetadataReadWriteOverride(formatKey, availableFormats,
9998d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He                expectedIntValues, availableFormatTag);
1000b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
10018d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        //
1002b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        // android.statistics.faces (Face x n array)
1003b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        //
1004b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int[] expectedFaceIds = new int[] {1, 2, 3, 4, 5};
1005b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        byte[] expectedFaceScores = new byte[] {10, 20, 30, 40, 50};
1006b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int numFaces = expectedFaceIds.length;
1007b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        Rect[] expectedRects = new Rect[numFaces];
1008b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        for (int i = 0; i < numFaces; i++) {
1009b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            expectedRects[i] = new Rect(i*4 + 1, i * 4 + 2, i * 4 + 3, i * 4 + 4);
1010b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
1011b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        int[] expectedFaceLM = new int[] {
1012b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                1, 2, 3, 4, 5, 6,
1013b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                7, 8, 9, 10, 11, 12,
1014b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                13, 14, 15, 16, 17, 18,
1015b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                19, 20, 21, 22, 23, 24,
1016b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                25, 26, 27, 28, 29, 30,
1017b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        };
1018b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        Point[] expectedFaceLMPoints = new Point[numFaces * 3];
1019b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        for (int i = 0; i < numFaces; i++) {
1020b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            expectedFaceLMPoints[i*3] = new Point(expectedFaceLM[i*6], expectedFaceLM[i*6+1]);
1021b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            expectedFaceLMPoints[i*3+1] = new Point(expectedFaceLM[i*6+2], expectedFaceLM[i*6+3]);
1022b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            expectedFaceLMPoints[i*3+2] = new Point(expectedFaceLM[i*6+4], expectedFaceLM[i*6+5]);
1023b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
1024b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
1025b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        /**
1026b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He         * Read - FACE_DETECT_MODE == FULL
1027b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He         */
1028b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_DETECT_MODE,
1029b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL);
1030b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_IDS, expectedFaceIds);
1031b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_SCORES, expectedFaceScores);
1032b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_RECTANGLES, expectedRects);
1033b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_LANDMARKS, expectedFaceLM);
1034b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        Face[] resultFaces = mMetadata.get(CaptureResult.STATISTICS_FACES);
1035b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        assertEquals(numFaces, resultFaces.length);
1036b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        for (int i = 0; i < numFaces; i++) {
1037b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedFaceIds[i], resultFaces[i].getId());
1038b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedFaceScores[i], resultFaces[i].getScore());
1039b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedRects[i], resultFaces[i].getBounds());
1040b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedFaceLMPoints[i*3], resultFaces[i].getLeftEyePosition());
1041b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedFaceLMPoints[i*3+1], resultFaces[i].getRightEyePosition());
1042b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedFaceLMPoints[i*3+2], resultFaces[i].getMouthPosition());
1043b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
1044b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
1045b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        /**
1046b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He         * Read - FACE_DETECT_MODE == SIMPLE
1047b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He         */
1048b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_DETECT_MODE,
1049b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He                CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE);
1050b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_SCORES, expectedFaceScores);
1051b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        mMetadata.set(CaptureResult.STATISTICS_FACE_RECTANGLES, expectedRects);
1052b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        Face[] resultSimpleFaces = mMetadata.get(CaptureResult.STATISTICS_FACES);
1053b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        assertEquals(numFaces, resultSimpleFaces.length);
1054b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        for (int i = 0; i < numFaces; i++) {
1055b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(Face.ID_UNSUPPORTED, resultSimpleFaces[i].getId());
1056b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedFaceScores[i], resultSimpleFaces[i].getScore());
1057b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertEquals(expectedRects[i], resultSimpleFaces[i].getBounds());
1058b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertNull(resultSimpleFaces[i].getLeftEyePosition());
1059b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertNull(resultSimpleFaces[i].getRightEyePosition());
1060b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He            assertNull(resultSimpleFaces[i].getMouthPosition());
1061b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He        }
1062b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He
10638490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        /**
10648490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh         * Read/Write TonemapCurve
10658490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh         */
10668490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] red = new float[] {0.0f, 0.0f, 1.0f, 1.0f};
10678490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] green = new float[] {0.0f, 1.0f, 1.0f, 0.0f};
10688490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] blue = new float[] {
10698490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh                0.0000f, 0.0000f, 0.0667f, 0.2920f, 0.1333f, 0.4002f, 0.2000f, 0.4812f,
10708490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh                0.2667f, 0.5484f, 0.3333f, 0.6069f, 0.4000f, 0.6594f, 0.4667f, 0.7072f,
10718490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh                0.5333f, 0.7515f, 0.6000f, 0.7928f, 0.6667f, 0.8317f, 0.7333f, 0.8685f,
10728490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh                0.8000f, 0.9035f, 0.8667f, 0.9370f, 0.9333f, 0.9691f, 1.0000f, 1.0000f};
10738490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        TonemapCurve tcIn = new TonemapCurve(red, green, blue);
10748490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        mMetadata.set(CaptureResult.TONEMAP_CURVE, tcIn);
10758490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] redOut = mMetadata.get(CaptureResult.TONEMAP_CURVE_RED);
10768490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] greenOut = mMetadata.get(CaptureResult.TONEMAP_CURVE_GREEN);
10778490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        float[] blueOut = mMetadata.get(CaptureResult.TONEMAP_CURVE_BLUE);
107882984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        assertArrayEquals(red, redOut);
107982984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        assertArrayEquals(green, greenOut);
108082984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        assertArrayEquals(blue, blueOut);
10818490ace76fd350e53de9554c11fca715c5a37aafYin-Chia Yeh        TonemapCurve tcOut = mMetadata.get(CaptureResult.TONEMAP_CURVE);
108282984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        assertEquals(tcIn, tcOut);
108382984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        mMetadata.set(CaptureResult.TONEMAP_CURVE_GREEN, null);
108482984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        // If any of channel has null curve, return a null TonemapCurve
108582984727642c5705cfb5d7868bc92997bd2bfd4dYin-Chia Yeh        assertNull(mMetadata.get(CaptureResult.TONEMAP_CURVE));
1086b7bfdc7cf7f45805e8e7ebea77a15051b8ad3e8dZhijun He    }
10878d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
10888d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He    /**
10899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Set the raw native value of the available stream configurations; ensure that
10909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * the read-out managed value is consistent with what we write in.
10919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
10929c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    @SmallTest
10939c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public void testOverrideStreamConfigurationMap() {
10949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        /*
10969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * First, write all the raw values:
10979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * - availableStreamConfigurations
10989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * - availableMinFrameDurations
10999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * - availableStallDurations
11009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         *
11019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * Then, read this out as a synthetic multi-key 'streamConfigurationMap'
11029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         *
11039c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * Finally, validate that the map was unmarshaled correctly
11049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         * and is converting the internal formats to public formats properly.
11059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin         */
11069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // android.scaler.availableStreamConfigurations (int x n x 4 array)
11099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        final int OUTPUT = 0;
11119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        final int INPUT = 1;
11129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int[] rawAvailableStreamConfigs = new int[] {
11139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x20, 3280, 2464, OUTPUT, // RAW16
11149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3264, 2448, OUTPUT, // YCbCr_420_888
11159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3200, 2400, OUTPUT, // YCbCr_420_888
11169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 3264, 2448, OUTPUT, // BLOB
11179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 3200, 2400, OUTPUT, // BLOB
11189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 2592, 1944, OUTPUT, // BLOB
11199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 2048, 1536, OUTPUT, // BLOB
11209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 1920, 1080, OUTPUT, // BLOB
11219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x22, 640, 480, OUTPUT,   // IMPLEMENTATION_DEFINED
11229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x20, 320, 240, INPUT,   // RAW16
11239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
11249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Key<StreamConfiguration[]> configKey =
1125d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS.getNativeKey();
11269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mMetadata.writeValues(configKey.getTag(),
11279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                toByteArray(rawAvailableStreamConfigs));
11289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // android.scaler.availableMinFrameDurations (int x n x 4 array)
11319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        long[] expectedAvailableMinDurations = new long[] {
11339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x20, 3280, 2464, 33333331, // RAW16
11349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3264, 2448, 33333332, // YCbCr_420_888
11359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3200, 2400, 33333333, // YCbCr_420_888
11369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 3264, 2448, 33333334, // ImageFormat.JPEG
11379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 3200, 2400, 33333335, // ImageFormat.JPEG
11389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 2592, 1944, 33333336, // ImageFormat.JPEG
11399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 2048, 1536, 33333337, // ImageFormat.JPEG
11409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 1920, 1080, 33333338  // ImageFormat.JPEG
11419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
11429c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        long[] rawAvailableMinDurations = new long[] {
11439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x20, 3280, 2464, 33333331, // RAW16
11449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3264, 2448, 33333332, // YCbCr_420_888
11459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3200, 2400, 33333333, // YCbCr_420_888
11469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 3264, 2448, 33333334, // BLOB
11479c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 3200, 2400, 33333335, // BLOB
11489c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 2592, 1944, 33333336, // BLOB
11499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 2048, 1536, 33333337, // BLOB
11509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 1920, 1080, 33333338  // BLOB
11519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
11529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Key<StreamConfigurationDuration[]> durationKey =
1153d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS.getNativeKey();
11549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mMetadata.writeValues(durationKey.getTag(),
11559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                toByteArray(rawAvailableMinDurations));
11569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11579c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // android.scaler.availableStallDurations (int x n x 4 array)
11599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        long[] expectedAvailableStallDurations = new long[] {
11619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x20, 3280, 2464, 0,        // RAW16
11629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3264, 2448, 0,        // YCbCr_420_888
11639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x23, 3200, 2400, 0,        // YCbCr_420_888
11649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 3264, 2448, 33333334, // ImageFormat.JPEG
11659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 3200, 2400, 33333335, // ImageFormat.JPEG
11669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 2592, 1944, 33333336, // ImageFormat.JPEG
11679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 2048, 1536, 33333337, // ImageFormat.JPEG
11689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x100, 1920, 1080, 33333338  // ImageFormat.JPEG
11699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
11709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // Note: RAW16 and YUV_420_888 omitted intentionally; omitted values should default to 0
11719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        long[] rawAvailableStallDurations = new long[] {
11729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 3264, 2448, 33333334, // BLOB
11739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 3200, 2400, 33333335, // BLOB
11749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 2592, 1944, 33333336, // BLOB
11759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 2048, 1536, 33333337, // BLOB
11769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                0x21, 1920, 1080, 33333338  // BLOB
11779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        };
11789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Key<StreamConfigurationDuration[]> stallDurationKey =
1179d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                CameraCharacteristics.SCALER_AVAILABLE_STALL_DURATIONS.getNativeKey();
11809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mMetadata.writeValues(stallDurationKey.getTag(),
11819c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                toByteArray(rawAvailableStallDurations));
11829c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11839c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11849c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // android.scaler.streamConfigurationMap (synthetic as StreamConfigurationMap)
11859c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        //
11869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        StreamConfigurationMap streamConfigMap = mMetadata.get(
11879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
11889c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // Inputs
11909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
11919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.RAW_SENSOR, 320, 240, /*output*/false);
11929c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11939c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // Outputs
11949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
11959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 640, 480, /*output*/true);
11969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
11979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.JPEG, 1920, 1080, /*output*/true);
11989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
11999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.JPEG, 2048, 1536, /*output*/true);
12009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
12019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.JPEG, 2592, 1944, /*output*/true);
12029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
12039c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.JPEG, 3200, 2400, /*output*/true);
12049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
12059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.YUV_420_888, 3200, 2400, /*output*/true);
12069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
12079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.YUV_420_888, 3264, 2448, /*output*/true);
12089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkStreamConfigurationMapByFormatSize(
12099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                streamConfigMap, ImageFormat.RAW_SENSOR, 3280, 2464, /*output*/true);
12109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
12119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // Min Frame Durations
12129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
12139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        final int DURATION_TUPLE_SIZE = 4;
12149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (int i = 0; i < expectedAvailableMinDurations.length; i += DURATION_TUPLE_SIZE) {
12159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            checkStreamConfigurationMapDurationByFormatSize(
12169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    streamConfigMap,
12179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    (int)expectedAvailableMinDurations[i],
12189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    (int)expectedAvailableMinDurations[i+1],
12199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    (int)expectedAvailableMinDurations[i+2],
12209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    Duration.MinFrame,
12219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    expectedAvailableMinDurations[i+3]);
12229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
12239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
12249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // Stall Frame Durations
12259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
12269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (int i = 0; i < expectedAvailableStallDurations.length; i += DURATION_TUPLE_SIZE) {
12279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            checkStreamConfigurationMapDurationByFormatSize(
12289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    streamConfigMap,
12299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    (int)expectedAvailableStallDurations[i],
12309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    (int)expectedAvailableStallDurations[i+1],
12319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    (int)expectedAvailableStallDurations[i+2],
12329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    Duration.Stall,
12339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    expectedAvailableStallDurations[i+3]);
12349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
12359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
12369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
123778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    private <T> void assertKeyValueEquals(T expected, CameraCharacteristics.Key<T> key) {
123878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(expected, key.getNativeKey());
123978712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    }
124078712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
124178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    private <T> void assertKeyValueEquals(T expected, Key<T> key) {
124278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        T actual = mMetadata.get(key);
124378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
124478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertEquals("Expected value for key " + key + " to match", expected, actual);
124578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    }
124678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
124778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    @SmallTest
124878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    public void testOverrideMaxRegions() {
124978712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        // All keys are null before doing any writes.
125078712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(null, CameraCharacteristics.CONTROL_MAX_REGIONS_AE);
125178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(null, CameraCharacteristics.CONTROL_MAX_REGIONS_AWB);
125278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(null, CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
125378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
125478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        mMetadata.set(CameraCharacteristics.CONTROL_MAX_REGIONS,
125578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin                new int[] { /*AE*/1, /*AWB*/2, /*AF*/3 });
125678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
125778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        // All keys are the expected value after doing a write
125878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(1, CameraCharacteristics.CONTROL_MAX_REGIONS_AE);
125978712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(2, CameraCharacteristics.CONTROL_MAX_REGIONS_AWB);
126078712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(3, CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
126178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    }
126278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
126378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    @SmallTest
126478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    public void testOverrideMaxNumOutputStreams() {
126578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        // All keys are null before doing any writes.
126678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(null, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW);
126778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(null, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC);
126878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(null, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING);
126978712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
127078712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        mMetadata.set(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS,
127178712a8bd7275542013ba099f33536eead0167fbIgor Murashkin                new int[] { /*AE*/1, /*AWB*/2, /*AF*/3 });
127278712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
127378712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        // All keys are the expected value after doing a write
127478712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(1, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW);
127578712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(2, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC);
127678712a8bd7275542013ba099f33536eead0167fbIgor Murashkin        assertKeyValueEquals(3, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING);
127778712a8bd7275542013ba099f33536eead0167fbIgor Murashkin    }
127878712a8bd7275542013ba099f33536eead0167fbIgor Murashkin
1279d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    @SmallTest
1280d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    public void testCaptureResult() {
1281d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        mMetadata.set(CaptureRequest.CONTROL_AE_MODE,
1282d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH);
1283d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
1284d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (VERBOSE) mMetadata.dumpToLog();
1285d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
1286d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        CaptureResult captureResult = new CaptureResult(mMetadata, /*sequenceId*/0);
1287d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
1288d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        List<CaptureResult.Key<?>> allKeys = captureResult.getKeys();
1289d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (VERBOSE) Log.v(TAG, "testCaptureResult: key list size " + allKeys);
1290d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        for (CaptureResult.Key<?> key : captureResult.getKeys()) {
1291d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            if (VERBOSE) {
1292d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                Log.v(TAG,
1293d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    "testCaptureResult: key " + key + " value" + captureResult.get(key));
1294d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            }
1295d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
1296d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
1297d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        assertTrue(allKeys.size() >= 1); // FIXME: android.statistics.faces counts as a key
1298d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        assertTrue(allKeys.contains(CaptureResult.CONTROL_AE_MODE));
1299d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
1300d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        assertEquals(CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH,
1301d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                (int)captureResult.get(CaptureResult.CONTROL_AE_MODE));
1302d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
1303d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
13049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static void checkStreamConfigurationMapByFormatSize(StreamConfigurationMap configMap,
13059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            int format, int width, int height,
13069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            boolean output) {
13079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        /** arbitrary class for which StreamConfigurationMap#isOutputSupportedFor(Class) is true */
13099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        final Class<?> IMPLEMENTATION_DEFINED_OUTPUT_CLASS = SurfaceTexture.class;
13109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        android.util.Size[] sizes;
13129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int[] formats;
13139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (output) {
13159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
13169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                sizes = configMap.getOutputSizes(IMPLEMENTATION_DEFINED_OUTPUT_CLASS);
13179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                // in this case the 'is output format supported' is vacuously true
13189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                formats = new int[] { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED };
13199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            } else {
13209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                sizes = configMap.getOutputSizes(format);
13219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                formats = configMap.getOutputFormats();
13229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                assertTrue("Format must be supported by stream configuration map",
13239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                        configMap.isOutputSupportedFor(format));
13249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            }
13259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        } else {
13269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            // NOTE: No function to do input sizes from IMPL_DEFINED, so it would just fail for that
13279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            sizes = configMap.getInputSizes(format);
13289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            formats = configMap.getInputFormats();
13299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
13309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        android.util.Size expectedSize = new android.util.Size(width, height);
13329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertArrayContains(format, formats);
13349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertArrayContains(expectedSize, sizes);
13359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
13369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private enum Duration {
13389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        MinFrame,
13399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Stall
13409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
13419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13429c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static void checkStreamConfigurationMapDurationByFormatSize(
13439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            StreamConfigurationMap configMap,
13449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            int format, int width, int height, Duration durationKind, long expectedDuration) {
13459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        /** arbitrary class for which StreamConfigurationMap#isOutputSupportedFor(Class) is true */
13479c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        final Class<?> IMPLEMENTATION_DEFINED_OUTPUT_CLASS = SurfaceTexture.class;
13489c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        long actualDuration;
13509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        android.util.Size size = new android.util.Size(width, height);
13529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        switch (durationKind) {
13539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case MinFrame:
13549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
13559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    actualDuration = configMap.getOutputMinFrameDuration(
13569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                            IMPLEMENTATION_DEFINED_OUTPUT_CLASS, size);
13579c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                } else {
13589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    actualDuration = configMap.getOutputMinFrameDuration(format, size);
13599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                }
13609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                break;
13629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case Stall:
13639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
13649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    actualDuration = configMap.getOutputStallDuration(
13659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                            IMPLEMENTATION_DEFINED_OUTPUT_CLASS, size);
13669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                } else {
13679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    actualDuration = configMap.getOutputStallDuration(format, size);
13689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                }
13699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                break;
13719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            default:
13729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                throw new AssertionError();
13739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
13749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertEquals("Expected " + durationKind + " to match actual value", expectedDuration,
13769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                actualDuration);
13779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
13789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
13799c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
13808d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He     * Validate metadata array tag read/write override.
13818d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He     *
13828d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He     * <p>Only support long and int array for now, can be easily extend to support other
13838d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He     * primitive arrays.</p>
13848d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He     */
13859c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private <T> void validateArrayMetadataReadWriteOverride(Key<T> key, T expectedWriteValues,
13869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            T expectedReadValues, int tag) {
13879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Class<?> type = expectedWriteValues.getClass();
13888d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        if (!type.isArray()) {
13898d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            throw new IllegalArgumentException("This function expects an key with array type");
13908d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        } else if (type != int[].class && type != long[].class) {
13918d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            throw new IllegalArgumentException("This function expects long or int array values");
13928d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        }
13938d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
13948d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        // Write
13959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mMetadata.set(key, expectedWriteValues);
13968d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
13978d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        byte[] readOutValues = mMetadata.readValues(tag);
13988d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
13998d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        ByteBuffer bf = ByteBuffer.wrap(readOutValues).order(ByteOrder.nativeOrder());
14008d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
14019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int readValuesLength = Array.getLength(expectedReadValues);
14028d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        int readValuesNumBytes = readValuesLength * 4;
14038d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        if (type == long[].class) {
14048d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            readValuesNumBytes = readValuesLength * 8;
14058d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        }
14068d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
14078d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        assertEquals(readValuesNumBytes, readOutValues.length);
14088d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        for (int i = 0; i < readValuesLength; ++i) {
14098d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            if (type == int[].class) {
14109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                assertEquals(Array.getInt(expectedReadValues, i), bf.getInt());
14118d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            } else if (type == long[].class) {
14129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                assertEquals(Array.getLong(expectedReadValues, i), bf.getLong());
14138d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            }
14148d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        }
14158d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
14168d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        // Read
14178d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        byte[] readOutValuesAsByteArray = new byte[readValuesNumBytes];
14188d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        ByteBuffer readOutValuesByteBuffer =
14198d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He                ByteBuffer.wrap(readOutValuesAsByteArray).order(ByteOrder.nativeOrder());
14208d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        for (int i = 0; i < readValuesLength; ++i) {
14218d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            if (type == int[].class) {
14229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                readOutValuesByteBuffer.putInt(Array.getInt(expectedReadValues, i));
14238d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            } else if (type == long[].class) {
14249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                readOutValuesByteBuffer.putLong(Array.getLong(expectedReadValues, i));
14258d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He            }
14268d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        }
14278d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        mMetadata.writeValues(tag, readOutValuesAsByteArray);
14288d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He
14298d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        T result = mMetadata.get(key);
14308d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He        assertNotNull(key.getName() + " result shouldn't be null", result);
14319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        assertArrayEquals(expectedWriteValues, result);
14328d637b819b23d0fcca87a39d26d0350e062852f4Zhijun He    }
14333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
14343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    // TODO: move somewhere else
14353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    @SmallTest
14363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public void testToByteArray() {
14373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertArrayEquals(new byte[] { 5, 0, 0, 0, 6, 0, 0, 0 },
14383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(5, 6));
14393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertArrayEquals(new byte[] { 5, 0, 6, 0, },
14403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray((short)5, (short)6));
14413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertArrayEquals(new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,
14423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                                        (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,},
14433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(~0, ~0));
14443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
14453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        assertArrayEquals(new byte[] { (byte)0xAB, (byte)0xFF, 0, 0,
14463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                0x0D, (byte)0xF0, (byte)0xAD, (byte)0xDE },
14473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                toByteArray(0xFFAB, 0xDEADF00D));
14483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
144970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
1450