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 385 386 /* 387 * We have three cases to test for : 388 * Case 1: Device does not have an HRM 389 * FEATURE_SENSOR_HEART_RATE false 390 * FEATURE_SENSOR_HEART_RATE_ECG false 391 * assertFeatureForSensor(TYPE_HEART_RATE) false 392 * 393 * Case 2: Device has a PPG HRM 394 * FEATURE_SENSOR_HEART_RATE true 395 * FEATURE_SENSOR_HEART_RATE_ECG false 396 * assertFeatureForSensor(TYPE_HEART_RATE) true 397 * 398 * Case 3: Device has an ECG HRM 399 * FEATURE_SENSOR_HEART_RATE false 400 * FEATURE_SENSOR_HEART_RATE_ECG true 401 * assertFeatureForSensor(TYPE_HEART_RATE) true 402 */ 403 404 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_HEART_RATE_ECG)) { 405 /* Case 3 for FEATURE_SENSOR_HEART_RATE_ECG true case */ 406 assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE_ECG, 407 Sensor.TYPE_HEART_RATE); 408 409 /* Remove HEART_RATE from featuresLeft, no way to test that one */ 410 assertTrue("Features left " + featuresLeft + " to check did not include " 411 + PackageManager.FEATURE_SENSOR_HEART_RATE, 412 featuresLeft.remove(PackageManager.FEATURE_SENSOR_HEART_RATE)); 413 } else if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_HEART_RATE)) { 414 /* Case 1 & 2 for FEATURE_SENSOR_HEART_RATE_ECG false case */ 415 assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE_ECG, 416 Sensor.TYPE_HEART_RATE); 417 418 /* Case 1 & 3 for FEATURE_SENSOR_HEART_RATE false case */ 419 assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE, 420 Sensor.TYPE_HEART_RATE); 421 } else { 422 /* Case 2 for FEATURE_SENSOR_HEART_RATE true case */ 423 assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE, 424 Sensor.TYPE_HEART_RATE); 425 426 /* Remove HEART_RATE_ECG from featuresLeft, no way to test that one */ 427 assertTrue("Features left " + featuresLeft + " to check did not include " 428 + PackageManager.FEATURE_SENSOR_HEART_RATE_ECG, 429 featuresLeft.remove(PackageManager.FEATURE_SENSOR_HEART_RATE_ECG)); 430 } 431 432 assertTrue("Assertions need to be added to this test for " + featuresLeft, 433 featuresLeft.isEmpty()); 434 } 435 436 /** Get a list of feature constants in PackageManager matching a prefix. */ getFeatureConstantsNames(String prefix)437 private static Set<String> getFeatureConstantsNames(String prefix) 438 throws IllegalArgumentException, IllegalAccessException { 439 Set<String> features = new HashSet<String>(); 440 Field[] fields = PackageManager.class.getFields(); 441 for (Field field : fields) { 442 if (field.getName().startsWith(prefix)) { 443 String feature = (String) field.get(null); 444 features.add(feature); 445 } 446 } 447 return features; 448 } 449 450 @Test testSipFeatures()451 public void testSipFeatures() { 452 if (SipManager.newInstance(mContext) != null) { 453 assertAvailable(PackageManager.FEATURE_SIP); 454 } else { 455 assertNotAvailable(PackageManager.FEATURE_SIP); 456 assertNotAvailable(PackageManager.FEATURE_SIP_VOIP); 457 } 458 459 if (SipManager.isApiSupported(mContext)) { 460 assertAvailable(PackageManager.FEATURE_SIP); 461 } else { 462 assertNotAvailable(PackageManager.FEATURE_SIP); 463 assertNotAvailable(PackageManager.FEATURE_SIP_VOIP); 464 } 465 466 if (SipManager.isVoipSupported(mContext)) { 467 assertAvailable(PackageManager.FEATURE_SIP); 468 assertAvailable(PackageManager.FEATURE_SIP_VOIP); 469 } else { 470 assertNotAvailable(PackageManager.FEATURE_SIP_VOIP); 471 } 472 } 473 474 /** 475 * Check that if the PackageManager declares a sensor feature that the device has at least 476 * one sensor that matches that feature. Also check that if a PackageManager does not declare 477 * a sensor that the device also does not have such a sensor. 478 * 479 * @param featuresLeft to check in order to make sure the test covers all sensor features 480 * @param expectedFeature that the PackageManager may report 481 * @param expectedSensorType that that {@link SensorManager#getSensorList(int)} may have 482 */ assertFeatureForSensor(Set<String> featuresLeft, String expectedFeature, int expectedSensorType)483 private void assertFeatureForSensor(Set<String> featuresLeft, String expectedFeature, 484 int expectedSensorType) { 485 assertTrue("Features left " + featuresLeft + " to check did not include " 486 + expectedFeature, featuresLeft.remove(expectedFeature)); 487 488 boolean hasSensorFeature = mPackageManager.hasSystemFeature(expectedFeature); 489 490 List<Sensor> sensors = mSensorManager.getSensorList(expectedSensorType); 491 List<String> sensorNames = new ArrayList<String>(sensors.size()); 492 for (Sensor sensor : sensors) { 493 sensorNames.add(sensor.getName()); 494 } 495 boolean hasSensorType = !sensors.isEmpty(); 496 497 String message = "PackageManager#hasSystemFeature(" + expectedFeature + ") returns " 498 + hasSensorFeature 499 + " but SensorManager#getSensorList(" + expectedSensorType + ") shows sensors " 500 + sensorNames; 501 502 assertEquals(message, hasSensorFeature, hasSensorType); 503 } 504 505 /** 506 * Check that the {@link TelephonyManager#getPhoneType()} matches the reported features. 507 */ 508 @Test testTelephonyFeatures()509 public void testTelephonyFeatures() { 510 if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) || 511 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_CONNECTION_SERVICE)) { 512 return; 513 } 514 515 int phoneType = mTelephonyManager.getPhoneType(); 516 switch (phoneType) { 517 case TelephonyManager.PHONE_TYPE_GSM: 518 assertAvailable(PackageManager.FEATURE_TELEPHONY_GSM); 519 break; 520 521 case TelephonyManager.PHONE_TYPE_CDMA: 522 assertAvailable(PackageManager.FEATURE_TELEPHONY_CDMA); 523 break; 524 525 case TelephonyManager.PHONE_TYPE_NONE: 526 fail("FEATURE_TELEPHONY is present; phone type should not be PHONE_TYPE_NONE"); 527 break; 528 529 default: 530 throw new IllegalArgumentException("Did you add a new phone type? " + phoneType); 531 } 532 } 533 534 @Test testTouchScreenFeatures()535 public void testTouchScreenFeatures() { 536 // If device implementations include a touchscreen (single-touch or better), they: 537 // [C-1-1] MUST report TOUCHSCREEN_FINGER for the Configuration.touchscreen API field. 538 // [C-1-2] MUST report the android.hardware.touchscreen and 539 // android.hardware.faketouch feature flags 540 ConfigurationInfo configInfo = mActivityManager.getDeviceConfigurationInfo(); 541 if (configInfo.reqTouchScreen == Configuration.TOUCHSCREEN_NOTOUCH) { 542 // Device does not include a touchscreen 543 assertNotAvailable(PackageManager.FEATURE_TOUCHSCREEN); 544 } else { 545 // Device has a touchscreen 546 assertAvailable(PackageManager.FEATURE_TOUCHSCREEN); 547 assertAvailable(PackageManager.FEATURE_FAKETOUCH); 548 } 549 } 550 551 @Test testFakeTouchFeatures()552 public void testFakeTouchFeatures() { 553 // If device implementations declare support for android.hardware.faketouch, they: 554 // [C-1-7] MUST report TOUCHSCREEN_NOTOUCH for the Configuration.touchscreen API field 555 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FAKETOUCH) && 556 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) { 557 // The device *only* supports faketouch, and does not have a touchscreen 558 Configuration configuration = mContext.getResources().getConfiguration(); 559 assertEquals(configuration.touchscreen, Configuration.TOUCHSCREEN_NOTOUCH); 560 } 561 562 // If device implementations declare support for 563 // android.hardware.faketouch.multitouch.distinct, they: 564 // [C-2-1] MUST declare support for android.hardware.faketouch 565 if (mPackageManager.hasSystemFeature( 566 PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT)) { 567 assertAvailable(PackageManager.FEATURE_FAKETOUCH); 568 } 569 570 // If device implementations declare support for 571 // android.hardware.faketouch.multitouch.jazzhand, they: 572 // [C-3-1] MUST declare support for android.hardware.faketouch 573 if (mPackageManager.hasSystemFeature( 574 PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND)) { 575 assertAvailable(PackageManager.FEATURE_FAKETOUCH); 576 } 577 } 578 579 @Test testUsbAccessory()580 public void testUsbAccessory() { 581 if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) && 582 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK) && 583 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH) && 584 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_EMBEDDED) && 585 !isAndroidEmulator() && 586 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_PC) && 587 mPackageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE) && 588 mPackageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) { 589 // USB accessory mode is only a requirement for devices with USB ports supporting 590 // peripheral mode. As there is no public API to distinguish a device with only host 591 // mode support from having both peripheral and host support, the test may have 592 // false negatives. 593 assertAvailable(PackageManager.FEATURE_USB_ACCESSORY); 594 } 595 } 596 597 @Test testWifiFeature()598 public void testWifiFeature() throws Exception { 599 if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) { 600 // no WiFi, skip the test 601 return; 602 } 603 boolean enabled = mWifiManager.isWifiEnabled(); 604 try { 605 // assert wifimanager can toggle wifi from current sate 606 SystemUtil.runShellCommand("svc wifi " + (!enabled ? "enable" : "disable")); 607 Thread.sleep(5_000); // wait for the toggle to take effect. 608 assertEquals(!enabled, mWifiManager.isWifiEnabled()); 609 610 } finally { 611 SystemUtil.runShellCommand("svc wifi " + (enabled ? "enable" : "disable")); 612 } 613 } 614 615 @Test testAudioOutputFeature()616 public void testAudioOutputFeature() throws Exception { 617 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) || 618 mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { 619 assertAvailable(PackageManager.FEATURE_AUDIO_OUTPUT); 620 } 621 } 622 assertAvailable(String feature)623 private void assertAvailable(String feature) { 624 assertTrue("PackageManager#hasSystemFeature should return true for " + feature, 625 mPackageManager.hasSystemFeature(feature)); 626 assertTrue("PackageManager#getSystemAvailableFeatures should have " + feature, 627 mAvailableFeatures.contains(feature)); 628 } 629 assertNotAvailable(String feature)630 private void assertNotAvailable(String feature) { 631 assertFalse("PackageManager#hasSystemFeature should NOT return true for " + feature, 632 mPackageManager.hasSystemFeature(feature)); 633 assertFalse("PackageManager#getSystemAvailableFeatures should NOT have " + feature, 634 mAvailableFeatures.contains(feature)); 635 } 636 assertOneAvailable(String feature1, String feature2)637 private void assertOneAvailable(String feature1, String feature2) { 638 if ((mPackageManager.hasSystemFeature(feature1) && mAvailableFeatures.contains(feature1)) || 639 (mPackageManager.hasSystemFeature(feature2) && mAvailableFeatures.contains(feature2))) { 640 return; 641 } else { 642 fail("Must support at least one of " + feature1 + " or " + feature2); 643 } 644 } 645 isAndroidEmulator()646 private boolean isAndroidEmulator() { 647 return PropertyUtil.propertyEquals("ro.boot.qemu", "1"); 648 } 649 assertFeature(boolean exist, String feature)650 private void assertFeature(boolean exist, String feature) { 651 if (exist) { 652 assertAvailable(feature); 653 } else { 654 assertNotAvailable(feature); 655 } 656 } 657 } 658