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