1 /*
2  * Copyright (C) 2017 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 com.android.compatibility.common.util;
18 
19 import android.content.Context;
20 import android.content.pm.FeatureInfo;
21 import android.content.pm.PackageManager;
22 import android.content.res.Configuration;
23 import android.os.Build;
24 
25 import androidx.test.InstrumentationRegistry;
26 
27 import java.util.HashSet;
28 import java.util.Set;
29 
30 /**
31  * Device-side utility class for detecting system features
32  */
33 public class FeatureUtil {
34 
35     public static final String ARC_FEATURE = "org.chromium.arc";
36     public static final String ARC_DEVICE_MANAGEMENT_FEATURE = "org.chromium.arc.device_management";
37     public static final String AUTOMOTIVE_FEATURE = "android.hardware.type.automotive";
38     public static final String LEANBACK_FEATURE = "android.software.leanback";
39     public static final String LOW_RAM_FEATURE = "android.hardware.ram.low";
40     public static final String TELEPHONY_FEATURE = "android.hardware.telephony";
41     public static final String TV_FEATURE = "android.hardware.type.television";
42     public static final String WATCH_FEATURE = "android.hardware.type.watch";
43 
44 
45     /** Returns true if the device has a given system feature */
hasSystemFeature(String feature)46     public static boolean hasSystemFeature(String feature) {
47         return getPackageManager().hasSystemFeature(feature);
48     }
49 
50     /** Returns true if the device has any feature in a given collection of system features */
hasAnySystemFeature(String... features)51     public static boolean hasAnySystemFeature(String... features) {
52         PackageManager pm = getPackageManager();
53         for (String feature : features) {
54             if (pm.hasSystemFeature(feature)) {
55                 return true;
56             }
57         }
58         return false;
59     }
60 
61     /** Returns true if the device has all features in a given collection of system features */
hasAllSystemFeatures(String... features)62     public static boolean hasAllSystemFeatures(String... features) {
63         PackageManager pm = getPackageManager();
64         for (String feature : features) {
65             if (!pm.hasSystemFeature(feature)) {
66                 return false;
67             }
68         }
69         return true;
70     }
71 
72     /** Returns all system features of the device */
getAllFeatures()73     public static Set<String> getAllFeatures() {
74         Set<String> allFeatures = new HashSet<String>();
75         for (FeatureInfo fi : getPackageManager().getSystemAvailableFeatures()) {
76             allFeatures.add(fi.name);
77         }
78         return allFeatures;
79     }
80 
81     /** Returns {@code true} if device is an ARC++ device. */
isArc()82     public static boolean isArc() {
83         return hasAnySystemFeature(ARC_FEATURE, ARC_DEVICE_MANAGEMENT_FEATURE);
84     }
85 
86     /** Returns true if the device has feature TV_FEATURE or feature LEANBACK_FEATURE */
isTV()87     public static boolean isTV() {
88         return hasAnySystemFeature(TV_FEATURE, LEANBACK_FEATURE);
89     }
90 
91     /** Returns true if the device has feature WATCH_FEATURE */
isWatch()92     public static boolean isWatch() {
93         return hasSystemFeature(WATCH_FEATURE);
94     }
95 
96     /** Returns true if the device has feature AUTOMOTIVE_FEATURE */
isAutomotive()97     public static boolean isAutomotive() {
98         return hasSystemFeature(AUTOMOTIVE_FEATURE);
99     }
100 
isVrHeadset()101     public static boolean isVrHeadset() {
102         int maskedUiMode = (getConfiguration().uiMode & Configuration.UI_MODE_TYPE_MASK);
103         return (maskedUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET);
104     }
105 
106     /** Returns true if the device is a low ram device:
107      *  1. API level &gt;= O_MR1
108      *  2. device has feature LOW_RAM_FEATURE
109      */
isLowRam()110     public static boolean isLowRam() {
111         return ApiLevelUtil.isAtLeast(Build.VERSION_CODES.O_MR1) &&
112                 hasSystemFeature(LOW_RAM_FEATURE);
113     }
114 
getContext()115     private static Context getContext() {
116         return InstrumentationRegistry.getInstrumentation().getTargetContext();
117     }
118 
getPackageManager()119     private static PackageManager getPackageManager() {
120         return getContext().getPackageManager();
121     }
122 
getConfiguration()123     private static Configuration getConfiguration() {
124         return getContext().getResources().getConfiguration();
125     }
126 
127     /** Returns true if the device has feature TELEPHONY_FEATURE */
hasTelephony()128     public static boolean hasTelephony() {
129         return hasSystemFeature(TELEPHONY_FEATURE);
130     }
131 
132     /** Returns true if the device has feature FEATURE_MICROPHONE */
hasMicrophone()133     public static boolean hasMicrophone() {
134         return hasSystemFeature(getPackageManager().FEATURE_MICROPHONE);
135     }
136 }
137