• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.app.cts;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22 import static org.junit.Assert.fail;
23 
24 import android.app.ActivityManager;
25 import android.app.Instrumentation;
26 import android.app.WallpaperManager;
27 import android.bluetooth.BluetoothAdapter;
28 import android.content.ActivityNotFoundException;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.content.pm.ConfigurationInfo;
32 import android.content.pm.FeatureInfo;
33 import android.content.pm.PackageManager;
34 import android.content.res.Configuration;
35 import android.hardware.Camera;
36 import android.hardware.Camera.CameraInfo;
37 import android.hardware.Camera.Parameters;
38 import android.hardware.Sensor;
39 import android.hardware.SensorManager;
40 import android.hardware.camera2.CameraCharacteristics;
41 import android.hardware.camera2.CameraManager;
42 import android.hardware.camera2.CameraMetadata;
43 import android.location.LocationManager;
44 import android.net.sip.SipManager;
45 import android.net.wifi.WifiManager;
46 import android.nfc.NfcAdapter;
47 import android.os.Build;
48 import android.telephony.TelephonyManager;
49 
50 import androidx.test.filters.FlakyTest;
51 import androidx.test.platform.app.InstrumentationRegistry;
52 
53 import com.android.compatibility.common.util.CddTest;
54 import com.android.compatibility.common.util.PropertyUtil;
55 import com.android.compatibility.common.util.SystemUtil;
56 
57 import org.junit.Before;
58 import org.junit.Test;
59 import org.junit.runner.RunWith;
60 import org.junit.runners.JUnit4;
61 
62 import java.lang.reflect.Field;
63 import java.util.ArrayList;
64 import java.util.HashSet;
65 import java.util.List;
66 import java.util.Set;
67 
68 /**
69  * Test for checking that the {@link PackageManager} is reporting the correct features.
70  */
71 @RunWith(JUnit4.class)
72 public class SystemFeaturesTest {
73 
74     private Context mContext;
75     private PackageManager mPackageManager;
76     private Set<String> mAvailableFeatures;
77 
78     private ActivityManager mActivityManager;
79     private LocationManager mLocationManager;
80     private SensorManager mSensorManager;
81     private TelephonyManager mTelephonyManager;
82     private WifiManager mWifiManager;
83     private CameraManager mCameraManager;
84 
85     @Before
setUp()86     public void setUp() {
87         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
88         mContext = instrumentation.getTargetContext();
89         mPackageManager = mContext.getPackageManager();
90         mAvailableFeatures = new HashSet<String>();
91         if (mPackageManager.getSystemAvailableFeatures() != null) {
92             for (FeatureInfo feature : mPackageManager.getSystemAvailableFeatures()) {
93                 mAvailableFeatures.add(feature.name);
94             }
95         }
96         mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
97         mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
98         mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
99         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
100         mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
101         mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
102     }
103 
104     /**
105      * Check for features improperly prefixed with "android." that are not defined in
106      * {@link PackageManager}.
107      */
108     @Test
testFeatureNamespaces()109     public void testFeatureNamespaces() throws IllegalArgumentException, IllegalAccessException {
110         Set<String> officialFeatures = getFeatureConstantsNames("FEATURE_");
111         assertFalse(officialFeatures.isEmpty());
112 
113         Set<String> notOfficialFeatures = new HashSet<String>(mAvailableFeatures);
114         notOfficialFeatures.removeAll(officialFeatures);
115 
116         for (String featureName : notOfficialFeatures) {
117             if (featureName != null) {
118                 if (!Build.VERSION.CODENAME.equals("REL") &&
119                     featureName.equals("android.software.preview_sdk")) {
120                     // Skips preview_sdk in non-release build.
121                     continue;
122                 }
123                 assertFalse("Use a different namespace than 'android' for " + featureName,
124                         featureName.startsWith("android"));
125             }
126         }
127     }
128 
129     @Test
testBluetoothFeature()130     public void testBluetoothFeature() {
131         if (BluetoothAdapter.getDefaultAdapter() != null) {
132             assertAvailable(PackageManager.FEATURE_BLUETOOTH);
133         } else {
134             assertNotAvailable(PackageManager.FEATURE_BLUETOOTH);
135         }
136     }
137 
138     @Test
testCameraFeatures()139     public void testCameraFeatures() throws Exception {
140         int numCameras = Camera.getNumberOfCameras();
141         if (numCameras == 0) {
142             assertNotAvailable(PackageManager.FEATURE_CAMERA);
143             assertNotAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
144             assertNotAvailable(PackageManager.FEATURE_CAMERA_FLASH);
145             assertNotAvailable(PackageManager.FEATURE_CAMERA_FRONT);
146             assertNotAvailable(PackageManager.FEATURE_CAMERA_ANY);
147             assertNotAvailable(PackageManager.FEATURE_CAMERA_LEVEL_FULL);
148             assertNotAvailable(PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR);
149             assertNotAvailable(PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING);
150             assertNotAvailable(PackageManager.FEATURE_CAMERA_CAPABILITY_RAW);
151             assertNotAvailable(PackageManager.FEATURE_CAMERA_AR);
152 
153             assertFalse("Devices supporting external cameras must have a representative camera " +
154                     "connected for testing",
155                     mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
156         } else {
157             assertAvailable(PackageManager.FEATURE_CAMERA_ANY);
158             checkFrontCamera();
159             checkRearCamera();
160             checkCamera2Features();
161         }
162     }
163 
164     @CddTest(requirement="7.5.4/C-0-8")
checkCamera2Features()165     private void checkCamera2Features() throws Exception {
166         String[] cameraIds = mCameraManager.getCameraIdList();
167         boolean fullCamera = false;
168         boolean manualSensor = false;
169         boolean manualPostProcessing = false;
170         boolean motionTracking = false;
171         boolean raw = false;
172         boolean hasFlash = false;
173         CameraCharacteristics[] cameraChars = new CameraCharacteristics[cameraIds.length];
174         for (String cameraId : cameraIds) {
175             CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId);
176             Integer hwLevel = chars.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
177             int[] capabilities = chars.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
178             if (hwLevel == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL ||
179                     hwLevel == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_3) {
180                 fullCamera = true;
181             }
182             for (int capability : capabilities) {
183                 switch (capability) {
184                     case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR:
185                         manualSensor = true;
186                         break;
187                     case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING:
188                         manualPostProcessing = true;
189                         break;
190                     case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW:
191                         raw = true;
192                         break;
193                   case CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING:
194                         motionTracking = true;
195                         break;
196                     default:
197                         // Capabilities don't have a matching system feature
198                         break;
199                 }
200             }
201 
202             Boolean flashAvailable = chars.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
203             if (flashAvailable) {
204                 hasFlash = true;
205             }
206         }
207         assertFeature(fullCamera, PackageManager.FEATURE_CAMERA_LEVEL_FULL);
208         assertFeature(manualSensor, PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR);
209         assertFeature(manualPostProcessing,
210                 PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING);
211         assertFeature(raw, PackageManager.FEATURE_CAMERA_CAPABILITY_RAW);
212         if (!motionTracking) {
213           // FEATURE_CAMERA_AR requires the presence of
214           // CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING but
215           // MOTION_TRACKING does not require the presence of FEATURE_CAMERA_AR
216           //
217           // Logic table:
218           //    AR= F   T
219           // MT=F   Y   N
220           //   =T   Y   Y
221           //
222           // So only check the one disallowed condition: No motion tracking and FEATURE_CAMERA_AR is
223           // available
224           assertNotAvailable(PackageManager.FEATURE_CAMERA_AR);
225         }
226         assertFeature(hasFlash, PackageManager.FEATURE_CAMERA_FLASH);
227     }
228 
checkFrontCamera()229     private void checkFrontCamera() {
230         CameraInfo info = new CameraInfo();
231         int numCameras = Camera.getNumberOfCameras();
232         int frontCameraId = -1;
233         for (int i = 0; i < numCameras; i++) {
234             Camera.getCameraInfo(i, info);
235             if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
236                 frontCameraId = i;
237             }
238         }
239 
240         if (frontCameraId > -1) {
241             assertTrue("Device has front-facing camera but does not report either " +
242                     "the FEATURE_CAMERA_FRONT or FEATURE_CAMERA_EXTERNAL feature",
243                     mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) ||
244                     mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
245         } else {
246             assertFalse("Device does not have front-facing camera but reports either " +
247                     "the FEATURE_CAMERA_FRONT or FEATURE_CAMERA_EXTERNAL feature",
248                     mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) ||
249                     mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
250         }
251     }
252 
checkRearCamera()253     private void checkRearCamera() {
254         Camera camera = null;
255         try {
256             camera = Camera.open();
257             if (camera != null) {
258                 assertAvailable(PackageManager.FEATURE_CAMERA);
259 
260                 Camera.Parameters params = camera.getParameters();
261                 if (params.getSupportedFocusModes().contains(Parameters.FOCUS_MODE_AUTO)) {
262                     assertAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
263                 } else {
264                     assertNotAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
265                 }
266 
267                 if (params.getFlashMode() != null) {
268                     assertAvailable(PackageManager.FEATURE_CAMERA_FLASH);
269                 } else {
270                     assertNotAvailable(PackageManager.FEATURE_CAMERA_FLASH);
271                 }
272             } else {
273                 assertNotAvailable(PackageManager.FEATURE_CAMERA);
274                 assertNotAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
275                 assertNotAvailable(PackageManager.FEATURE_CAMERA_FLASH);
276             }
277         } finally {
278             if (camera != null) {
279                 camera.release();
280             }
281         }
282     }
283 
284     @Test
testGamepadFeature()285     public void testGamepadFeature() {
286         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
287             assertAvailable(PackageManager.FEATURE_GAMEPAD);
288         }
289     }
290 
291     @Test
testLiveWallpaperFeature()292     public void testLiveWallpaperFeature() {
293         try {
294             Intent intent = new Intent(WallpaperManager.ACTION_LIVE_WALLPAPER_CHOOSER);
295             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
296             mContext.startActivity(intent);
297             assertAvailable(PackageManager.FEATURE_LIVE_WALLPAPER);
298         } catch (ActivityNotFoundException e) {
299             assertNotAvailable(PackageManager.FEATURE_LIVE_WALLPAPER);
300         }
301     }
302 
303     @Test
testLocationFeatures()304     public void testLocationFeatures() {
305         if (mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
306             assertAvailable(PackageManager.FEATURE_LOCATION);
307             assertAvailable(PackageManager.FEATURE_LOCATION_GPS);
308         } else {
309             assertNotAvailable(PackageManager.FEATURE_LOCATION_GPS);
310         }
311 
312         if (mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
313             assertAvailable(PackageManager.FEATURE_LOCATION);
314             assertAvailable(PackageManager.FEATURE_LOCATION_NETWORK);
315         } else {
316             assertNotAvailable(PackageManager.FEATURE_LOCATION_NETWORK);
317         }
318     }
319 
320     @Test
testLowRamFeature()321     public void testLowRamFeature() {
322         if (mActivityManager.isLowRamDevice()) {
323             assertAvailable(PackageManager.FEATURE_RAM_LOW);
324         } else {
325             assertAvailable(PackageManager.FEATURE_RAM_NORMAL);
326         }
327     }
328 
329     @Test
testNfcFeatures()330     public void testNfcFeatures() {
331         if (NfcAdapter.getDefaultAdapter(mContext) != null) {
332             // Watches MAY support all FEATURE_NFC features when an NfcAdapter is available, but
333             // non-watches MUST support them both.
334             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
335                 assertOneAvailable(PackageManager.FEATURE_NFC,
336                     PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
337             } else {
338                 assertAvailable(PackageManager.FEATURE_NFC);
339                 assertAvailable(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
340             }
341         } else {
342             assertNotAvailable(PackageManager.FEATURE_NFC);
343             assertNotAvailable(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
344         }
345     }
346 
347     @Test
testScreenFeatures()348     public void testScreenFeatures() {
349         assertTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
350                 || mPackageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT));
351     }
352 
353     /**
354      * Check that the sensor features reported by the PackageManager correspond to the sensors
355      * returned by {@link SensorManager#getSensorList(int)}.
356      */
357     @FlakyTest
358     @Test
testSensorFeatures()359     public void testSensorFeatures() throws Exception {
360         Set<String> featuresLeft = getFeatureConstantsNames("FEATURE_SENSOR_");
361 
362         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_ACCELEROMETER,
363                 Sensor.TYPE_ACCELEROMETER);
364         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_BAROMETER,
365                 Sensor.TYPE_PRESSURE);
366         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_COMPASS,
367                 Sensor.TYPE_MAGNETIC_FIELD);
368         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_GYROSCOPE,
369                 Sensor.TYPE_GYROSCOPE);
370         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_LIGHT,
371                 Sensor.TYPE_LIGHT);
372         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_PROXIMITY,
373                 Sensor.TYPE_PROXIMITY);
374         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_STEP_COUNTER,
375                 Sensor.TYPE_STEP_COUNTER);
376         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_STEP_DETECTOR,
377                 Sensor.TYPE_STEP_DETECTOR);
378         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_AMBIENT_TEMPERATURE,
379                 Sensor.TYPE_AMBIENT_TEMPERATURE);
380         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_RELATIVE_HUMIDITY,
381                 Sensor.TYPE_RELATIVE_HUMIDITY);
382         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HINGE_ANGLE,
383                 Sensor.TYPE_HINGE_ANGLE);
384         assertFeatureForSensor(featuresLeft,
385                 PackageManager.FEATURE_SENSOR_ACCELEROMETER_LIMITED_AXES,
386                 Sensor.TYPE_ACCELEROMETER_LIMITED_AXES);
387         assertFeatureForSensor(featuresLeft,
388                 PackageManager.FEATURE_SENSOR_GYROSCOPE_LIMITED_AXES,
389                 Sensor.TYPE_GYROSCOPE_LIMITED_AXES);
390         assertFeatureForSensor(featuresLeft,
391                 PackageManager.FEATURE_SENSOR_ACCELEROMETER_LIMITED_AXES_UNCALIBRATED,
392                 Sensor.TYPE_ACCELEROMETER_LIMITED_AXES_UNCALIBRATED);
393         assertFeatureForSensor(featuresLeft,
394                 PackageManager.FEATURE_SENSOR_GYROSCOPE_LIMITED_AXES_UNCALIBRATED,
395                 Sensor.TYPE_GYROSCOPE_LIMITED_AXES_UNCALIBRATED);
396         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEADING,
397                 Sensor.TYPE_HEADING);
398 
399         // Note that FEATURE_SENSOR_DYNAMIC_HEAD_TRACKER requires dynamic sensor discovery, but
400         // dynamic sensor discovery does not require FEATURE_SENSOR_DYNAMIC_HEAD_TRACKER
401         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_DYNAMIC_HEAD_TRACKER)) {
402             assertTrue("Device declared " + PackageManager.FEATURE_SENSOR_DYNAMIC_HEAD_TRACKER
403                     + " but does not support dynamic sensor discovery",
404                     mSensorManager.isDynamicSensorDiscoverySupported());
405         }
406         featuresLeft.remove(PackageManager.FEATURE_SENSOR_DYNAMIC_HEAD_TRACKER);
407 
408         /*
409          * We have three cases to test for :
410          * Case 1:  Device does not have an HRM
411          * FEATURE_SENSOR_HEART_RATE               false
412          * FEATURE_SENSOR_HEART_RATE_ECG           false
413          * assertFeatureForSensor(TßYPE_HEART_RATE) false
414          *
415          * Case 2:  Device has a PPG HRM
416          * FEATURE_SENSOR_HEART_RATE               true
417          * FEATURE_SENSOR_HEART_RATE_ECG           false
418          * assertFeatureForSensor(TYPE_HEART_RATE) true
419          *
420          * Case 3:  Device has an ECG HRM
421          * FEATURE_SENSOR_HEART_RATE               false
422          * FEATURE_SENSOR_HEART_RATE_ECG           true
423          * assertFeatureForSensor(TYPE_HEART_RATE) true
424          */
425 
426         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_HEART_RATE_ECG)) {
427                 /* Case 3 for FEATURE_SENSOR_HEART_RATE_ECG true case */
428                 assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE_ECG,
429                         Sensor.TYPE_HEART_RATE);
430 
431                 /* Remove HEART_RATE from featuresLeft, no way to test that one */
432                 assertTrue("Features left " + featuresLeft + " to check did not include "
433                         + PackageManager.FEATURE_SENSOR_HEART_RATE,
434                         featuresLeft.remove(PackageManager.FEATURE_SENSOR_HEART_RATE));
435         } else if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_HEART_RATE)) {
436                 /* Case 1 & 2 for FEATURE_SENSOR_HEART_RATE_ECG false case */
437                 assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE_ECG,
438                         Sensor.TYPE_HEART_RATE);
439 
440                 /* Case 1 & 3 for FEATURE_SENSOR_HEART_RATE false case */
441                 assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE,
442                         Sensor.TYPE_HEART_RATE);
443         } else {
444                 /* Case 2 for FEATURE_SENSOR_HEART_RATE true case */
445                 assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE,
446                         Sensor.TYPE_HEART_RATE);
447 
448                 /* Remove HEART_RATE_ECG from featuresLeft, no way to test that one */
449                 assertTrue("Features left " + featuresLeft + " to check did not include "
450                         + PackageManager.FEATURE_SENSOR_HEART_RATE_ECG,
451                         featuresLeft.remove(PackageManager.FEATURE_SENSOR_HEART_RATE_ECG));
452         }
453 
454         assertTrue("Assertions need to be added to this test for " + featuresLeft,
455                 featuresLeft.isEmpty());
456     }
457 
458     /** Get a list of feature constants in PackageManager matching a prefix. */
getFeatureConstantsNames(String prefix)459     private static Set<String> getFeatureConstantsNames(String prefix)
460             throws IllegalArgumentException, IllegalAccessException {
461         Set<String> features = new HashSet<String>();
462         Field[] fields = PackageManager.class.getFields();
463         for (Field field : fields) {
464             if (field.getName().startsWith(prefix)) {
465                 String feature = (String) field.get(null);
466                 features.add(feature);
467             }
468         }
469         return features;
470     }
471 
472     @Test
testSipFeatures()473     public void testSipFeatures() {
474         if (SipManager.newInstance(mContext) != null) {
475             assertAvailable(PackageManager.FEATURE_SIP);
476         } else {
477             assertNotAvailable(PackageManager.FEATURE_SIP);
478             assertNotAvailable(PackageManager.FEATURE_SIP_VOIP);
479         }
480 
481         if (SipManager.isApiSupported(mContext)) {
482             assertAvailable(PackageManager.FEATURE_SIP);
483         } else {
484             assertNotAvailable(PackageManager.FEATURE_SIP);
485             assertNotAvailable(PackageManager.FEATURE_SIP_VOIP);
486         }
487 
488         if (SipManager.isVoipSupported(mContext)) {
489             assertAvailable(PackageManager.FEATURE_SIP);
490             assertAvailable(PackageManager.FEATURE_SIP_VOIP);
491         } else {
492             assertNotAvailable(PackageManager.FEATURE_SIP_VOIP);
493         }
494     }
495 
496     /**
497      * Check that if the PackageManager declares a sensor feature that the device has at least
498      * one sensor that matches that feature. Also check that if a PackageManager does not declare
499      * a sensor that the device also does not have such a sensor.
500      *
501      * @param featuresLeft to check in order to make sure the test covers all sensor features
502      * @param expectedFeature that the PackageManager may report
503      * @param expectedSensorType that that {@link SensorManager#getSensorList(int)} may have
504      */
assertFeatureForSensor(Set<String> featuresLeft, String expectedFeature, int expectedSensorType)505     private void assertFeatureForSensor(Set<String> featuresLeft, String expectedFeature,
506             int expectedSensorType) {
507         assertTrue("Features left " + featuresLeft + " to check did not include "
508                 + expectedFeature, featuresLeft.remove(expectedFeature));
509 
510         boolean hasSensorFeature = mPackageManager.hasSystemFeature(expectedFeature);
511 
512         List<Sensor> sensors = mSensorManager.getSensorList(expectedSensorType);
513         List<String> sensorNames = new ArrayList<String>(sensors.size());
514         for (Sensor sensor : sensors) {
515             sensorNames.add(sensor.getName());
516         }
517         boolean hasSensorType = !sensors.isEmpty();
518 
519         String message = "PackageManager#hasSystemFeature(" + expectedFeature + ") returns "
520                 + hasSensorFeature
521                 + " but SensorManager#getSensorList(" + expectedSensorType + ") shows sensors "
522                 + sensorNames;
523 
524         assertEquals(message, hasSensorFeature, hasSensorType);
525     }
526 
527     /**
528      * Check that the {@link TelephonyManager#getPhoneType()} matches the reported features.
529      */
530     @Test
testTelephonyFeatures()531     public void testTelephonyFeatures() {
532         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) ||
533                 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELECOM)) {
534                 return;
535         }
536 
537         int phoneType = mTelephonyManager.getPhoneType();
538         switch (phoneType) {
539             case TelephonyManager.PHONE_TYPE_GSM:
540                 assertAvailable(PackageManager.FEATURE_TELEPHONY_GSM);
541                 break;
542 
543             case TelephonyManager.PHONE_TYPE_CDMA:
544                 assertAvailable(PackageManager.FEATURE_TELEPHONY_CDMA);
545                 break;
546 
547             case TelephonyManager.PHONE_TYPE_NONE:
548                 fail("FEATURE_TELEPHONY is present; phone type should not be PHONE_TYPE_NONE");
549                 break;
550 
551             default:
552                 throw new IllegalArgumentException("Did you add a new phone type? " + phoneType);
553         }
554     }
555 
556     @Test
testTouchScreenFeatures()557     public void testTouchScreenFeatures() {
558         // If device implementations include a touchscreen (single-touch or better), they:
559         // [C-1-1] MUST report TOUCHSCREEN_FINGER for the Configuration.touchscreen API field.
560         // [C-1-2] MUST report the android.hardware.touchscreen and
561         // android.hardware.faketouch feature flags
562         ConfigurationInfo configInfo = mActivityManager.getDeviceConfigurationInfo();
563         if (configInfo.reqTouchScreen == Configuration.TOUCHSCREEN_NOTOUCH) {
564             // Device does not include a touchscreen
565             assertNotAvailable(PackageManager.FEATURE_TOUCHSCREEN);
566         } else {
567             // Device has a touchscreen
568             assertAvailable(PackageManager.FEATURE_TOUCHSCREEN);
569             assertAvailable(PackageManager.FEATURE_FAKETOUCH);
570         }
571     }
572 
573     @Test
testFakeTouchFeatures()574     public void testFakeTouchFeatures() {
575         // If device implementations declare support for android.hardware.faketouch, they:
576         // [C-1-7] MUST report TOUCHSCREEN_NOTOUCH for the Configuration.touchscreen API field
577         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FAKETOUCH) &&
578                 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
579             // The device *only* supports faketouch, and does not have a touchscreen
580             Configuration configuration = mContext.getResources().getConfiguration();
581             assertEquals(configuration.touchscreen, Configuration.TOUCHSCREEN_NOTOUCH);
582         }
583 
584         // If device implementations declare support for
585         // android.hardware.faketouch.multitouch.distinct, they:
586         // [C-2-1] MUST declare support for android.hardware.faketouch
587         if (mPackageManager.hasSystemFeature(
588                 PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT)) {
589             assertAvailable(PackageManager.FEATURE_FAKETOUCH);
590         }
591 
592         // If device implementations declare support for
593         // android.hardware.faketouch.multitouch.jazzhand, they:
594         // [C-3-1] MUST declare support for android.hardware.faketouch
595         if (mPackageManager.hasSystemFeature(
596                 PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND)) {
597             assertAvailable(PackageManager.FEATURE_FAKETOUCH);
598         }
599     }
600 
601     @Test
testUsbAccessory()602     public void testUsbAccessory() {
603         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) &&
604                 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK) &&
605                 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH) &&
606                 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_EMBEDDED) &&
607                 !isAndroidEmulator() &&
608                 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_PC) &&
609                 mPackageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE) &&
610                 mPackageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
611             // USB accessory mode is only a requirement for devices with USB ports supporting
612             // peripheral mode. As there is no public API to distinguish a device with only host
613             // mode support from having both peripheral and host support, the test may have
614             // false negatives.
615             assertAvailable(PackageManager.FEATURE_USB_ACCESSORY);
616         }
617     }
618 
619     @Test
testWifiFeature()620     public void testWifiFeature() throws Exception {
621         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
622             // no WiFi, skip the test
623             return;
624         }
625         boolean enabled = mWifiManager.isWifiEnabled();
626         try {
627             // assert wifimanager can toggle wifi from current sate
628             SystemUtil.runShellCommand("svc wifi " + (!enabled ? "enable" : "disable"));
629             Thread.sleep(5_000); // wait for the toggle to take effect.
630             assertEquals(!enabled, mWifiManager.isWifiEnabled());
631 
632         } finally {
633             SystemUtil.runShellCommand("svc wifi " + (enabled ? "enable" : "disable"));
634         }
635     }
636 
637     @Test
testAudioOutputFeature()638     public void testAudioOutputFeature() throws Exception {
639         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) ||
640                 mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
641             assertAvailable(PackageManager.FEATURE_AUDIO_OUTPUT);
642         }
643     }
644 
assertAvailable(String feature)645     private void assertAvailable(String feature) {
646         assertTrue("PackageManager#hasSystemFeature should return true for " + feature,
647                 mPackageManager.hasSystemFeature(feature));
648         assertTrue("PackageManager#getSystemAvailableFeatures should have " + feature,
649                 mAvailableFeatures.contains(feature));
650     }
651 
assertNotAvailable(String feature)652     private void assertNotAvailable(String feature) {
653         assertFalse("PackageManager#hasSystemFeature should NOT return true for " + feature,
654                 mPackageManager.hasSystemFeature(feature));
655         assertFalse("PackageManager#getSystemAvailableFeatures should NOT have " + feature,
656                 mAvailableFeatures.contains(feature));
657     }
658 
assertOneAvailable(String feature1, String feature2)659     private void assertOneAvailable(String feature1, String feature2) {
660         if ((mPackageManager.hasSystemFeature(feature1) && mAvailableFeatures.contains(feature1)) ||
661             (mPackageManager.hasSystemFeature(feature2) && mAvailableFeatures.contains(feature2))) {
662             return;
663         } else {
664             fail("Must support at least one of " + feature1 + " or " + feature2);
665         }
666     }
667 
isAndroidEmulator()668     private boolean isAndroidEmulator() {
669         return PropertyUtil.propertyEquals("ro.boot.qemu", "1");
670     }
671 
assertFeature(boolean exist, String feature)672     private void assertFeature(boolean exist, String feature) {
673         if (exist) {
674             assertAvailable(feature);
675         } else {
676             assertNotAvailable(feature);
677         }
678     }
679 }
680