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