Home | History | Annotate | Download | only in deviceinfo
      1 /*
      2  * Copyright (C) 2015 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 package com.android.compatibility.common.deviceinfo;
     17 
     18 import android.content.pm.FeatureInfo;
     19 import android.content.pm.PackageManager;
     20 import android.os.Build;
     21 
     22 import com.android.compatibility.common.util.DeviceInfoStore;
     23 
     24 import java.lang.reflect.Field;
     25 import java.lang.reflect.InvocationTargetException;
     26 import java.lang.reflect.Method;
     27 import java.util.ArrayList;
     28 import java.util.HashSet;
     29 import java.util.List;
     30 import java.util.Set;
     31 
     32 /**
     33  * Feature device info collector.
     34  */
     35 public final class FeatureDeviceInfo extends DeviceInfo {
     36 
     37     @Override
     38     protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
     39         PackageManager packageManager =
     40                 getInstrumentation().getContext().getPackageManager();
     41         store.startArray("feature");
     42 
     43         List<String> sdkFeatures = getPackageManagerFeatures();
     44 
     45         FeatureInfo[] featureInfos = packageManager.getSystemAvailableFeatures();
     46         if (featureInfos != null) {
     47             for (FeatureInfo featureInfo : featureInfos) {
     48                 if (featureInfo.name != null) {
     49                     // Check if this feature is a "sdk" feature.
     50                     String type = "other";
     51                     if (sdkFeatures.contains(featureInfo.name)) {
     52                         type = "sdk";
     53                         sdkFeatures.remove(featureInfo.name);
     54                     }
     55                     // Add the feature version if avaiable.
     56                     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
     57                         int version = featureInfo.version;
     58                         addFeature(store, featureInfo.name, type, true, version);
     59                     } else {
     60                         addFeature(store, featureInfo.name, type, true);
     61                     }
     62                 }
     63             }
     64         }
     65 
     66         // Store the remaining "sdk" features not avaiable on this device.
     67         for (String featureName : sdkFeatures) {
     68             boolean hasFeature = packageManager.hasSystemFeature(featureName);
     69             addFeature(store, featureName, "sdk", hasFeature);
     70         }
     71 
     72         store.endArray();
     73     }
     74 
     75     /**
     76      * Use reflection to get the features defined by the SDK. If there are
     77      * features that do not fit the convention of starting with "FEATURE_"
     78      * then they will still be shown under the "Other Features" section.
     79      *
     80      * @return list of feature names from sdk
     81      */
     82     private List<String> getPackageManagerFeatures() {
     83         try {
     84             List<String> features = new ArrayList<String>();
     85             Field[] fields = PackageManager.class.getFields();
     86             for (Field field : fields) {
     87                 if (field.getName().startsWith("FEATURE_")) {
     88                     String feature = (String) field.get(null);
     89                     features.add(feature);
     90                 }
     91             }
     92             return features;
     93         } catch (IllegalAccessException illegalAccess) {
     94             throw new RuntimeException(illegalAccess);
     95         }
     96     }
     97 
     98     private void addFeature(
     99             DeviceInfoStore store,
    100             String name,
    101             String type,
    102             boolean available) throws Exception {
    103         store.startGroup();
    104         store.addResult("name", name);
    105         store.addResult("type", type);
    106         store.addResult("available", available);
    107         store.endGroup();
    108     }
    109 
    110     private void addFeature(
    111             DeviceInfoStore store,
    112             String name,
    113             String type,
    114             boolean available,
    115             int version) throws Exception {
    116         store.startGroup();
    117         store.addResult("name", name);
    118         store.addResult("type", type);
    119         store.addResult("available", available);
    120         store.addResult("version", version);
    121         store.endGroup();
    122     }
    123 }
    124