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