Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.hardware.camera2.cts;
     18 
     19 import android.content.Context;
     20 import android.graphics.ImageFormat;
     21 import android.hardware.camera2.CameraCharacteristics;
     22 import android.hardware.camera2.CameraCharacteristics.Key;
     23 import android.hardware.camera2.CameraManager;
     24 import android.hardware.camera2.cts.helpers.CameraErrorCollector;
     25 import android.hardware.camera2.params.BlackLevelPattern;
     26 import android.hardware.camera2.params.ColorSpaceTransform;
     27 import android.hardware.camera2.params.StreamConfigurationMap;
     28 import android.test.AndroidTestCase;
     29 import android.util.Log;
     30 import android.util.Rational;
     31 import android.util.Size;
     32 
     33 import java.util.ArrayList;
     34 import java.util.Arrays;
     35 import java.util.List;
     36 import java.util.Objects;
     37 
     38 import static android.hardware.camera2.cts.helpers.AssertHelpers.*;
     39 
     40 /**
     41  * Extended tests for static camera characteristics.
     42  */
     43 public class ExtendedCameraCharacteristicsTest extends AndroidTestCase {
     44     private static final String TAG = "ExChrsTest"; // must be short so next line doesn't throw
     45     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
     46 
     47     private static final String PREFIX_ANDROID = "android";
     48     private static final String PREFIX_VENDOR = "com";
     49 
     50     /*
     51      * Constants for static RAW metadata.
     52      */
     53     private static final int MIN_ALLOWABLE_WHITELEVEL = 32; // must have sensor bit depth > 5
     54 
     55     private CameraManager mCameraManager;
     56     private List<CameraCharacteristics> mCharacteristics;
     57     private String[] mIds;
     58     private CameraErrorCollector mCollector;
     59 
     60     private static final Size VGA = new Size(640, 480);
     61 
     62     /*
     63      * HW Levels short hand
     64      */
     65     private static final int LEGACY = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
     66     private static final int LIMITED = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
     67     private static final int FULL = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
     68     private static final int OPT = Integer.MAX_VALUE;  // For keys that are optional on all hardware levels.
     69 
     70     /*
     71      * Capabilities short hand
     72      */
     73     private static final int NONE = -1;
     74     private static final int BC =
     75             CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE;
     76     private static final int MANUAL_SENSOR =
     77             CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR;
     78     private static final int RAW =
     79             CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW;
     80 
     81     @Override
     82     public void setContext(Context context) {
     83         super.setContext(context);
     84         mCameraManager = (CameraManager)context.getSystemService(Context.CAMERA_SERVICE);
     85         assertNotNull("Can't connect to camera manager", mCameraManager);
     86     }
     87 
     88     @Override
     89     protected void setUp() throws Exception {
     90         super.setUp();
     91         mIds = mCameraManager.getCameraIdList();
     92         mCharacteristics = new ArrayList<>();
     93         mCollector = new CameraErrorCollector();
     94         for (int i = 0; i < mIds.length; i++) {
     95             CameraCharacteristics props = mCameraManager.getCameraCharacteristics(mIds[i]);
     96             assertNotNull(String.format("Can't get camera characteristics from: ID %s", mIds[i]),
     97                     props);
     98             mCharacteristics.add(props);
     99         }
    100     }
    101 
    102     @Override
    103     protected void tearDown() throws Exception {
    104         mCharacteristics = null;
    105 
    106         try {
    107             mCollector.verify();
    108         } catch (Throwable e) {
    109             // When new Exception(e) is used, exception info will be printed twice.
    110             throw new Exception(e.getMessage());
    111         } finally {
    112             super.tearDown();
    113         }
    114     }
    115 
    116     /**
    117      * Test that the available stream configurations contain a few required formats and sizes.
    118      */
    119     public void testAvailableStreamConfigs() {
    120         int counter = 0;
    121         for (CameraCharacteristics c : mCharacteristics) {
    122             StreamConfigurationMap config =
    123                     c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
    124             assertNotNull(String.format("No stream configuration map found for: ID %s",
    125                     mIds[counter]), config);
    126             int[] outputFormats = config.getOutputFormats();
    127 
    128             // Check required formats exist (JPEG, and YUV_420_888).
    129             assertArrayContains(
    130                     String.format("No valid YUV_420_888 preview formats found for: ID %s",
    131                             mIds[counter]), outputFormats, ImageFormat.YUV_420_888);
    132             assertArrayContains(String.format("No JPEG image format for: ID %s",
    133                     mIds[counter]), outputFormats, ImageFormat.JPEG);
    134 
    135             Size[] sizes = config.getOutputSizes(ImageFormat.YUV_420_888);
    136             CameraTestUtils.assertArrayNotEmpty(sizes,
    137                     String.format("No sizes for preview format %x for: ID %s",
    138                             ImageFormat.YUV_420_888, mIds[counter]));
    139 
    140             assertArrayContains(String.format(
    141                             "Required VGA size not found for format %x for: ID %s",
    142                             ImageFormat.YUV_420_888, mIds[counter]), sizes, VGA);
    143 
    144             counter++;
    145         }
    146     }
    147 
    148     /**
    149      * Test {@link CameraCharacteristics#getKeys}
    150      */
    151     public void testKeys() {
    152         int counter = 0;
    153         for (CameraCharacteristics c : mCharacteristics) {
    154             mCollector.setCameraId(mIds[counter]);
    155 
    156             if (VERBOSE) {
    157                 Log.v(TAG, "testKeys - testing characteristics for camera " + mIds[counter]);
    158             }
    159 
    160             List<CameraCharacteristics.Key<?>> allKeys = c.getKeys();
    161             assertNotNull("Camera characteristics keys must not be null", allKeys);
    162             assertFalse("Camera characteristics keys must have at least 1 key",
    163                     allKeys.isEmpty());
    164 
    165             for (CameraCharacteristics.Key<?> key : allKeys) {
    166                 assertKeyPrefixValid(key.getName());
    167 
    168                 // All characteristics keys listed must never be null
    169                 mCollector.expectKeyValueNotNull(c, key);
    170 
    171                 // TODO: add a check that key must not be @hide
    172             }
    173 
    174             /*
    175              * List of keys that must be present in camera characteristics (not null).
    176              *
    177              * Keys for LIMITED, FULL devices might be available despite lacking either
    178              * the hardware level or the capability. This is *OK*. This only lists the
    179              * *minimal* requirements for a key to be listed.
    180              *
    181              * LEGACY devices are a bit special since they map to api1 devices, so we know
    182              * for a fact most keys are going to be illegal there so they should never be
    183              * available.
    184              *
    185              * (TODO: Codegen this)
    186              */
    187             {
    188                 //                                           (Key Name)                                     (HW Level)  (Capabilities <Var-Arg>)
    189                 expectKeyAvailable(c, CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES     , LEGACY   ,   BC                   );
    190                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES          , LEGACY   ,   BC                   );
    191                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES                      , LEGACY   ,   BC                   );
    192                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES          , LEGACY   ,   BC                   );
    193                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE                   , LEGACY   ,   BC                   );
    194                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP                    , LEGACY   ,   BC                   );
    195                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES                      , LEGACY   ,   BC                   );
    196                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS                       , LEGACY   ,   BC                   );
    197                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES                   , LEGACY   ,   BC                   );
    198                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES     , LEGACY   ,   BC                   );
    199                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES                     , LEGACY   ,   BC                   );
    200                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AE                          , LEGACY   ,   BC                   );
    201                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AF                          , LEGACY   ,   BC                   );
    202                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AWB                         , LEGACY   ,   BC                   );
    203                 expectKeyAvailable(c, CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES                       , FULL     ,   NONE                 );
    204                 expectKeyAvailable(c, CameraCharacteristics.FLASH_INFO_AVAILABLE                            , LEGACY   ,   BC                   );
    205                 expectKeyAvailable(c, CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES             , OPT      ,   RAW                  );
    206                 expectKeyAvailable(c, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL                   , LEGACY   ,   BC                   );
    207                 expectKeyAvailable(c, CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES                  , LEGACY   ,   BC                   );
    208                 expectKeyAvailable(c, CameraCharacteristics.LENS_FACING                                     , LEGACY   ,   BC                   );
    209                 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES                   , FULL     ,   MANUAL_SENSOR        );
    210                 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES            , FULL     ,   MANUAL_SENSOR        );
    211                 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS               , LEGACY   ,   BC                   );
    212                 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION       , LIMITED  ,   MANUAL_SENSOR        );
    213                 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION            , LIMITED  ,   MANUAL_SENSOR        );
    214                 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE                   , LIMITED  ,   MANUAL_SENSOR        );
    215                 expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE                , LIMITED  ,   NONE                 );
    216                 expectKeyAvailable(c, CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES , LEGACY   ,   BC                   );
    217                 expectKeyAvailable(c, CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES                  , LEGACY   ,   BC                   );
    218                 expectKeyAvailable(c, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC                     , LEGACY   ,   BC                   );
    219                 expectKeyAvailable(c, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING            , LEGACY   ,   BC                   );
    220                 expectKeyAvailable(c, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW                      , LEGACY   ,   BC                   );
    221                 expectKeyAvailable(c, CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT                    , LEGACY   ,   BC                   );
    222                 expectKeyAvailable(c, CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH                      , LEGACY   ,   BC                   );
    223                 expectKeyAvailable(c, CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM               , LEGACY   ,   BC                   );
    224                 expectKeyAvailable(c, CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP                 , LEGACY   ,   BC                   );
    225                 expectKeyAvailable(c, CameraCharacteristics.SCALER_CROPPING_TYPE                            , LEGACY   ,   BC                   );
    226                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES             , LEGACY   ,   NONE                 );
    227                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN                      , FULL     ,   MANUAL_SENSOR, RAW   );
    228                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM1                   , OPT      ,   RAW                  );
    229                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM2                   , OPT      ,   RAW                  );
    230                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_COLOR_TRANSFORM1                         , OPT      ,   RAW                  );
    231                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_COLOR_TRANSFORM2                         , OPT      ,   RAW                  );
    232                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_FORWARD_MATRIX1                          , OPT      ,   RAW                  );
    233                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_FORWARD_MATRIX2                          , OPT      ,   RAW                  );
    234                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE                   , LEGACY   ,   BC, RAW              );
    235                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT            , FULL     ,   RAW                  );
    236                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE                 , FULL     ,   MANUAL_SENSOR        );
    237                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION                  , FULL     ,   MANUAL_SENSOR        );
    238                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE                       , LEGACY   ,   BC                   );
    239                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE                    , LEGACY   ,   BC                   );
    240                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE                   , FULL     ,   MANUAL_SENSOR        );
    241                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL                         , OPT      ,   RAW                  );
    242                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE                    , LEGACY   ,   BC                   );
    243                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY                   , FULL     ,   MANUAL_SENSOR        );
    244                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_ORIENTATION                              , LEGACY   ,   BC                   );
    245                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1                    , OPT      ,   RAW                  );
    246                 expectKeyAvailable(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT2                    , OPT      ,   RAW                  );
    247                 expectKeyAvailable(c, CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES     , LEGACY   ,   BC                   );
    248                 expectKeyAvailable(c, CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES   , OPT      ,   RAW                  );
    249                 expectKeyAvailable(c, CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT                  , LEGACY   ,   BC                   );
    250                 expectKeyAvailable(c, CameraCharacteristics.SYNC_MAX_LATENCY                                , LEGACY   ,   BC                   );
    251                 expectKeyAvailable(c, CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES                , FULL     ,   MANUAL_SENSOR        );
    252                 expectKeyAvailable(c, CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS                        , FULL     ,   MANUAL_SENSOR        );
    253 
    254                 // Future: Use column editors for modifying above, ignore line length to keep 1 key per line
    255 
    256                 // TODO: check that no other 'android' keys are listed in #getKeys if they aren't in the above list
    257             }
    258 
    259             counter++;
    260         }
    261     }
    262 
    263     /**
    264      * Test values for static metadata used by the RAW capability.
    265      */
    266     public void testStaticRawCharacteristics() {
    267         int counter = 0;
    268         for (CameraCharacteristics c : mCharacteristics) {
    269             int[] actualCapabilities = c.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
    270             assertNotNull("android.request.availableCapabilities must never be null");
    271             if (!arrayContains(actualCapabilities,
    272                     CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
    273                 Log.i(TAG, "RAW capability is not supported in camera " + counter++ +
    274                         ". Skip the test.");
    275                 continue;
    276             }
    277 
    278             Integer actualHwLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
    279             if (actualHwLevel != null && actualHwLevel == FULL) {
    280                 mCollector.expectKeyValueContains(c,
    281                         CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,
    282                         CameraCharacteristics.HOT_PIXEL_MODE_FAST);
    283             }
    284             mCollector.expectKeyValueContains(c,
    285                     CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES, false);
    286             mCollector.expectKeyValueGreaterThan(c, CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL,
    287                     MIN_ALLOWABLE_WHITELEVEL);
    288 
    289             mCollector.expectKeyValueIsIn(c,
    290                     CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
    291                     CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB,
    292                     CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG,
    293                     CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG,
    294                     CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR);
    295             // TODO: SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB isn't supported yet.
    296 
    297             mCollector.expectKeyValueInRange(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1,
    298                     CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT,
    299                     CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN);
    300             mCollector.expectKeyValueInRange(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT2,
    301                     (byte) CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT,
    302                     (byte) CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN);
    303 
    304             Rational[] zeroes = new Rational[9];
    305             Arrays.fill(zeroes, Rational.ZERO);
    306 
    307             ColorSpaceTransform zeroed = new ColorSpaceTransform(zeroes);
    308             mCollector.expectNotEquals("Forward Matrix1 should not contain all zeroes.", zeroed,
    309                     c.get(CameraCharacteristics.SENSOR_FORWARD_MATRIX1));
    310             mCollector.expectNotEquals("Forward Matrix2 should not contain all zeroes.", zeroed,
    311                     c.get(CameraCharacteristics.SENSOR_FORWARD_MATRIX2));
    312             mCollector.expectNotEquals("Calibration Transform1 should not contain all zeroes.",
    313                     zeroed, c.get(CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM1));
    314             mCollector.expectNotEquals("Calibration Transform2 should not contain all zeroes.",
    315                     zeroed, c.get(CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM2));
    316             mCollector.expectNotEquals("Color Transform1 should not contain all zeroes.",
    317                     zeroed, c.get(CameraCharacteristics.SENSOR_COLOR_TRANSFORM1));
    318             mCollector.expectNotEquals("Color Transform2 should not contain all zeroes.",
    319                     zeroed, c.get(CameraCharacteristics.SENSOR_COLOR_TRANSFORM2));
    320 
    321             BlackLevelPattern blackLevel = mCollector.expectKeyValueNotNull(c,
    322                     CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN);
    323             if (blackLevel != null) {
    324                 int[] blackLevelPattern = new int[BlackLevelPattern.COUNT];
    325                 blackLevel.copyTo(blackLevelPattern, /*offset*/0);
    326                 Integer whitelevel = c.get(CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL);
    327                 if (whitelevel != null) {
    328                     mCollector.expectValuesInRange("BlackLevelPattern", blackLevelPattern, 0,
    329                             whitelevel);
    330                 } else {
    331                     mCollector.addMessage(
    332                             "No WhiteLevel available, cannot check BlackLevelPattern range.");
    333                 }
    334             }
    335 
    336             // TODO: profileHueSatMap, and profileToneCurve aren't supported yet.
    337             counter++;
    338         }
    339     }
    340 
    341     /**
    342      * Check key is present in characteristics if the hardware level is at least {@code hwLevel};
    343      * check that the key is present if the actual capabilities are one of {@code capabilities}.
    344      *
    345      * @return value of the {@code key} from {@code c}
    346      */
    347     private <T> T expectKeyAvailable(CameraCharacteristics c, CameraCharacteristics.Key<T> key,
    348             int hwLevel, int... capabilities) {
    349 
    350         Integer actualHwLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
    351         assertNotNull("android.info.supportedHardwareLevel must never be null", actualHwLevel);
    352 
    353         int[] actualCapabilities = c.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
    354         assertNotNull("android.request.availableCapabilities must never be null");
    355 
    356         List<Key<?>> allKeys = c.getKeys();
    357 
    358         T value = c.get(key);
    359 
    360         if (compareHardwareLevel(actualHwLevel, hwLevel) >= 0) {
    361             mCollector.expectTrue(
    362                     String.format("Key (%s) must be in characteristics for this hardware level " +
    363                             "(required minimal HW level %s, actual HW level %s)",
    364                             key.getName(), toStringHardwareLevel(hwLevel),
    365                             toStringHardwareLevel(actualHwLevel)),
    366                     value != null);
    367             mCollector.expectTrue(
    368                     String.format("Key (%s) must be in characteristics list of keys for this " +
    369                             "hardware level (required minimal HW level %s, actual HW level %s)",
    370                             key.getName(), toStringHardwareLevel(hwLevel),
    371                             toStringHardwareLevel(actualHwLevel)),
    372                     allKeys.contains(key));
    373         } else if (arrayContainsAnyOf(actualCapabilities, capabilities)) {
    374             mCollector.expectTrue(
    375                     String.format("Key (%s) must be in characteristics for these capabilities " +
    376                             "(required capabilities %s, actual capabilities %s)",
    377                             key.getName(), Arrays.toString(capabilities),
    378                             Arrays.toString(actualCapabilities)),
    379                     value != null);
    380             mCollector.expectTrue(
    381                     String.format("Key (%s) must be in characteristics list of keys for " +
    382                             "these capabilities (required capabilities %s, actual capabilities %s)",
    383                             key.getName(), Arrays.toString(capabilities),
    384                             Arrays.toString(actualCapabilities)),
    385                     allKeys.contains(key));
    386         } else {
    387             if (actualHwLevel == LEGACY && hwLevel != OPT) {
    388                 if (value != null || allKeys.contains(key)) {
    389                     Log.w(TAG, String.format(
    390                             "Key (%s) is not required for LEGACY devices but still appears",
    391                             key.getName()));
    392                 }
    393             }
    394             // OK: Key may or may not be present.
    395         }
    396         return value;
    397     }
    398 
    399     private static boolean arrayContains(int[] arr, int needle) {
    400         if (arr == null) {
    401             return false;
    402         }
    403 
    404         for (int elem : arr) {
    405             if (elem == needle) {
    406                 return true;
    407             }
    408         }
    409 
    410         return false;
    411     }
    412 
    413     private static boolean arrayContainsAnyOf(int[] arr, int[] needles) {
    414         for (int needle : needles) {
    415             if (arrayContains(arr, needle)) {
    416                 return true;
    417             }
    418         }
    419         return false;
    420     }
    421 
    422     /**
    423      * The key name has a prefix of either "android." or "com."; other prefixes are not valid.
    424      */
    425     private static void assertKeyPrefixValid(String keyName) {
    426         assertStartsWithAnyOf(
    427                 "All metadata keys must start with 'android.' (built-in keys) " +
    428                 "or 'com.' (vendor-extended keys)", new String[] {
    429                         PREFIX_ANDROID + ".",
    430                         PREFIX_VENDOR + ".",
    431                 }, keyName);
    432     }
    433 
    434     private static void assertTrueForKey(String msg, CameraCharacteristics.Key<?> key,
    435             boolean actual) {
    436         assertTrue(msg + " (key = '" + key.getName() + "')", actual);
    437     }
    438 
    439     private static <T> void assertOneOf(String msg, T[] expected, T actual) {
    440         for (int i = 0; i < expected.length; ++i) {
    441             if (Objects.equals(expected[i], actual)) {
    442                 return;
    443             }
    444         }
    445 
    446         fail(String.format("%s: (expected one of %s, actual %s)",
    447                 msg, Arrays.toString(expected), actual));
    448     }
    449 
    450     private static <T> void assertStartsWithAnyOf(String msg, String[] expected, String actual) {
    451         for (int i = 0; i < expected.length; ++i) {
    452             if (actual.startsWith(expected[i])) {
    453                 return;
    454             }
    455         }
    456 
    457         fail(String.format("%s: (expected to start with any of %s, but value was %s)",
    458                 msg, Arrays.toString(expected), actual));
    459     }
    460 
    461     /** Return a positive int if left > right, 0 if left==right, negative int if left < right */
    462     private static int compareHardwareLevel(int left, int right) {
    463         return remapHardwareLevel(left) - remapHardwareLevel(right);
    464     }
    465 
    466     /** Remap HW levels worst<->best, 0 = worst, 2 = best */
    467     private static int remapHardwareLevel(int level) {
    468         switch (level) {
    469             case OPT:
    470                 return Integer.MAX_VALUE;
    471             case LEGACY:
    472                 return 0; // lowest
    473             case LIMITED:
    474                 return 1; // second lowest
    475             case FULL:
    476                 return 2; // best
    477         }
    478 
    479         fail("Unknown HW level: " + level);
    480         return -1;
    481     }
    482 
    483     private static String toStringHardwareLevel(int level) {
    484         switch (level) {
    485             case LEGACY:
    486                 return "LEGACY";
    487             case LIMITED:
    488                 return "LIMITED";
    489             case FULL:
    490                 return "FULL";
    491         }
    492 
    493         // unknown
    494         Log.w(TAG, "Unknown hardware level " + level);
    495         return Integer.toString(level);
    496     }
    497 }
    498