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