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 com.android.tradefed.targetprep; 18 19 import static com.android.tradefed.targetprep.VisibleBackgroundUserPreparer.INVALID_DISPLAY; 20 21 import com.android.ddmlib.IDevice; 22 import com.android.tradefed.config.Option; 23 import com.android.tradefed.config.OptionClass; 24 import com.android.tradefed.dependencies.ExternalDependency; 25 import com.android.tradefed.dependencies.IExternalDependency; 26 import com.android.tradefed.dependencies.connectivity.BluetoothDependency; 27 import com.android.tradefed.dependencies.connectivity.EthernetDependency; 28 import com.android.tradefed.dependencies.connectivity.NetworkDependency; 29 import com.android.tradefed.dependencies.connectivity.TelephonyDependency; 30 import com.android.tradefed.device.DeviceNotAvailableException; 31 import com.android.tradefed.device.ITestDevice; 32 import com.android.tradefed.device.LocalAndroidVirtualDevice; 33 import com.android.tradefed.device.StubDevice; 34 import com.android.tradefed.device.TestDevice; 35 import com.android.tradefed.device.TestDeviceState; 36 import com.android.tradefed.device.cloud.NestedRemoteDevice; 37 import com.android.tradefed.device.cloud.RemoteAndroidVirtualDevice; 38 import com.android.tradefed.invoker.TestInformation; 39 import com.android.tradefed.invoker.logger.InvocationMetricLogger; 40 import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey; 41 import com.android.tradefed.invoker.tracing.CloseableTraceScope; 42 import com.android.tradefed.log.LogUtil.CLog; 43 import com.android.tradefed.result.error.DeviceErrorIdentifier; 44 import com.android.tradefed.result.error.InfraErrorIdentifier; 45 import com.android.tradefed.util.BinaryState; 46 import com.android.tradefed.util.CommandResult; 47 import com.android.tradefed.util.CommandStatus; 48 import com.android.tradefed.util.MultiMap; 49 import com.android.tradefed.util.RunUtil; 50 import com.android.tradefed.util.executor.ParallelDeviceExecutor; 51 52 import com.google.common.annotations.VisibleForTesting; 53 import com.google.common.base.Strings; 54 55 import java.io.File; 56 import java.util.ArrayList; 57 import java.util.Collection; 58 import java.util.HashMap; 59 import java.util.LinkedHashMap; 60 import java.util.LinkedHashSet; 61 import java.util.List; 62 import java.util.Map; 63 import java.util.Set; 64 import java.util.TimeZone; 65 import java.util.concurrent.Callable; 66 import java.util.concurrent.TimeUnit; 67 68 /** 69 * A {@link ITargetPreparer} that configures a device for testing based on provided {@link Option}s. 70 * 71 * <p>Requires a device where 'adb root' is possible, typically a userdebug build type. 72 * 73 * <p>Should be performed <strong>after</strong> a new build is flashed. 74 * 75 * <p><strong>Note:</strong> this preparer is meant for continuous testing labs and assumes that the 76 * device under test will be flashed and wiped before the next run. As such, it does minimal clean 77 * up during teardown and should not be used in a test module. 78 */ 79 @OptionClass(alias = "device-setup") 80 public class DeviceSetup extends BaseTargetPreparer implements IExternalDependency { 81 82 // Networking 83 @Option(name = "airplane-mode", 84 description = "Turn airplane mode on or off") 85 protected BinaryState mAirplaneMode = BinaryState.IGNORE; 86 // ON: settings put global airplane_mode_on 1 87 // am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true 88 // OFF: settings put global airplane_mode_on 0 89 // am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false 90 91 @Option(name = "data", description = "Turn mobile data on or off") 92 protected BinaryState mData = BinaryState.IGNORE; 93 // ON: settings put global mobile_data 1 94 // svc data enable 95 // OFF: settings put global mobile_data 0 96 // svc data disable 97 98 @Option(name = "cell", description = "Turn cellular radio on or off") 99 protected BinaryState mCell = BinaryState.IGNORE; 100 // ON: settings put global cell_on 1 101 // OFF: settings put global cell_on 0 102 103 @Option(name = "cell-auto-setting", description = "Turn wear cellular mediator on or off") 104 protected BinaryState mCellAutoSetting = BinaryState.IGNORE; 105 // ON: settings put global clockwork_cell_auto_setting 1 106 // OFF: settings put global clockwork_cell_auto_setting 0 107 108 @Option(name = "wifi", description = "Turn wifi on or off") 109 protected BinaryState mWifi = BinaryState.IGNORE; 110 // ON: settings put global wifi_on 1 111 // svc wifi enable 112 // OFF: settings put global wifi_off 0 113 // svc wifi disable 114 115 @Option( 116 name = "skip-wifi-connection", 117 description = "Whether or not to completely skip connecting to wifi.") 118 private boolean mSkipWifi = false; 119 120 @Option(name = "wifi-network", 121 description = "The SSID of the network to connect to. Will only attempt to " + 122 "connect to a network if set") 123 protected String mWifiSsid = null; 124 125 @Option(name = "wifi-psk", 126 description = "The passphrase used to connect to a secured network") 127 protected String mWifiPsk = null; 128 129 @Option(name = "wifi-ssid-to-psk", description = "A map of wifi SSIDs to passwords.") 130 protected Map<String, String> mWifiSsidToPsk = new LinkedHashMap<>(); 131 132 @Option(name = "wifi-watchdog", 133 description = "Turn wifi watchdog on or off") 134 protected BinaryState mWifiWatchdog = BinaryState.IGNORE; 135 // ON: settings put global wifi_watchdog 1 136 // OFF: settings put global wifi_watchdog 0 137 138 @Option(name = "disable-cw-wifi-mediator", description = "Turn wifi mediator on or off") 139 protected BinaryState mDisableCwWifiMediator = BinaryState.IGNORE; 140 // ON: settings put global cw_disable_wifimediator 1 141 // OFF: settings put global cw_disable_wifimediator 0 142 143 @Option( 144 name = "wifi-scan-always-enabled", 145 description = "Turn wifi scan always enabled on or off" 146 ) 147 protected BinaryState mWifiScanAlwaysEnabled = BinaryState.IGNORE; 148 // ON: settings put global wifi_scan_always_enabled 1 149 // OFF: settings put global wifi_scan_always_enabled 0 150 151 @Option(name = "ethernet", 152 description = "Turn ethernet on or off") 153 protected BinaryState mEthernet = BinaryState.IGNORE; 154 // ON: ifconfig eth0 up 155 // OFF: ifconfig eth0 down 156 157 @Option(name = "bluetooth", 158 description = "Turn bluetooth on or off") 159 protected BinaryState mBluetooth = BinaryState.IGNORE; 160 // ON: svc bluetooth enable 161 // OFF: svc bluetooth disable 162 163 @Option(name = "nfc", 164 description = "Turn nfc on or off") 165 protected BinaryState mNfc = BinaryState.IGNORE; 166 // ON: svc nfc enable 167 // OFF: svc nfc disable 168 169 // Screen 170 @Option(name = "screen-adaptive-brightness", 171 description = "Turn screen adaptive brightness on or off") 172 protected BinaryState mScreenAdaptiveBrightness = BinaryState.IGNORE; 173 // ON: settings put system screen_brightness_mode 1 174 // OFF: settings put system screen_brightness_mode 0 175 176 @Option(name = "screen-brightness", 177 description = "Set the screen brightness. This is uncalibrated from product to product") 178 protected Integer mScreenBrightness = null; 179 // settings put system screen_brightness $N 180 181 @Option(name = "screen-always-on", 182 description = "Turn 'screen always on' on or off. If ON, then screen-timeout-secs " + 183 "must be unset. Will only work when the device is plugged in") 184 protected BinaryState mScreenAlwaysOn = BinaryState.ON; 185 // ON: svc power stayon true 186 // OFF: svc power stayon false 187 188 @Option(name = "screen-timeout-secs", 189 description = "Set the screen timeout in seconds. If set, then screen-always-on must " + 190 "be OFF or DEFAULT") 191 protected Long mScreenTimeoutSecs = null; 192 // settings put system screen_off_timeout $(N * 1000) 193 194 @Option(name = "screen-ambient-mode", 195 description = "Turn screen ambient mode on or off") 196 protected BinaryState mScreenAmbientMode = BinaryState.IGNORE; 197 // ON: settings put secure doze_enabled 1 198 // OFF: settings put secure doze_enabled 0 199 200 @Option(name = "wake-gesture", 201 description = "Turn wake gesture on or off") 202 protected BinaryState mWakeGesture = BinaryState.IGNORE; 203 // ON: settings put secure wake_gesture_enabled 1 204 // OFF: settings put secure wake_gesture_enabled 0 205 206 @Option(name = "screen-saver", 207 description = "Turn screen saver on or off") 208 protected BinaryState mScreenSaver = BinaryState.IGNORE; 209 // ON: settings put secure screensaver_enabled 1 210 // OFF: settings put secure screensaver_enabled 0 211 212 @Option(name = "notification-led", 213 description = "Turn the notification led on or off") 214 protected BinaryState mNotificationLed = BinaryState.IGNORE; 215 // ON: settings put system notification_light_pulse 1 216 // OFF: settings put system notification_light_pulse 0 217 218 @Option(name = "install-non-market-apps", 219 description = "Allow or prevent non-market app to initiate an apk install request") 220 protected BinaryState mInstallNonMarketApps = BinaryState.IGNORE; 221 // ON: settings put secure install_non_market_apps 1 222 // OFF: settings put secure install_non_market_apps 0 223 224 // Media 225 @Option(name = "trigger-media-mounted", 226 description = "Trigger a MEDIA_MOUNTED broadcast") 227 protected boolean mTriggerMediaMounted = false; 228 // am broadcast -a android.intent.action.MEDIA_MOUNTED -d file://${EXTERNAL_STORAGE} 229 // --receiver-include-background 230 231 // Location 232 @Option(name = "location-gps", description = "Turn the GPS location on or off") 233 protected BinaryState mLocationGps = BinaryState.IGNORE; 234 // ON: settings put secure location_providers_allowed +gps 235 // OFF: settings put secure location_providers_allowed -gps 236 237 @Option(name = "location-network", 238 description = "Turn the network location on or off") 239 protected BinaryState mLocationNetwork = BinaryState.IGNORE; 240 // ON: settings put secure location_providers_allowed +network 241 // OFF: settings put secure location_providers_allowed -network 242 243 // Sensor 244 @Option(name = "auto-rotate", 245 description = "Turn auto rotate on or off") 246 protected BinaryState mAutoRotate = BinaryState.IGNORE; 247 // ON: settings put system accelerometer_rotation 1 248 // OFF: settings put system accelerometer_rotation 0 249 250 // Power 251 @Option(name = "battery-saver-mode", 252 description = "Turn battery saver mode manually on or off. If OFF but battery is " + 253 "less battery-saver-trigger, the device will still go into battery saver mode") 254 protected BinaryState mBatterySaver = BinaryState.IGNORE; 255 // ON: dumpsys battery set usb 0 256 // settings put global low_power 1 257 // OFF: settings put global low_power 0 258 259 @Option(name = "battery-saver-trigger", 260 description = "Set the battery saver trigger level. Should be [1-99] to enable, or " + 261 "0 to disable automatic battery saver mode") 262 protected Integer mBatterySaverTrigger = null; 263 // settings put global low_power_trigger_level $N 264 265 @Option(name = "enable-full-battery-stats-history", 266 description = "Enable full history for batterystats. This option is only " + 267 "applicable for L+") 268 protected boolean mEnableFullBatteryStatsHistory = false; 269 // dumpsys batterystats --enable full-history 270 271 @Option(name = "disable-doze", 272 description = "Disable device from going into doze mode. This option is only " + 273 "applicable for M+") 274 protected boolean mDisableDoze = false; 275 // dumpsys deviceidle disable 276 277 // Time 278 @Option(name = "auto-update-time", 279 description = "Turn auto update time on or off") 280 protected BinaryState mAutoUpdateTime = BinaryState.IGNORE; 281 // ON: settings put global auto_time 1 282 // OFF: settings put global auto_time 0 283 284 @Option(name = "auto-update-timezone", description = "Turn auto update timezone on or off") 285 protected BinaryState mAutoUpdateTimezone = BinaryState.IGNORE; 286 // ON: settings put global auto_timezone 1 287 // OFF: settings put global auto_timezone 0 288 289 @Option( 290 name = "set-timezone", 291 description = 292 "Set timezone property by TZ name " 293 + "(http://en.wikipedia.org/wiki/List_of_tz_database_time_zones)") 294 protected String mTimezone = null; 295 296 @Option(name = "sync-timezone-with-host", 297 description = 298 "Turn on or off that make the time zone of device sync with host") 299 protected BinaryState mSyncTimezoneWithHost = BinaryState.IGNORE; 300 // ON: settings put global sync_timezone 1 301 // OFF: settings put global sync_timezone 0 302 303 // Calling 304 @Option(name = "disable-dialing", 305 description = "Disable dialing") 306 protected boolean mDisableDialing = true; 307 // setprop ro.telephony.disable-call true" 308 309 @Option(name = "default-sim-data", 310 description = "Set the default sim card slot for data. Leave unset for single SIM " + 311 "devices") 312 protected Integer mDefaultSimData = null; 313 // settings put global multi_sim_data_call $N 314 315 @Option(name = "default-sim-voice", 316 description = "Set the default sim card slot for voice calls. Leave unset for single " + 317 "SIM devices") 318 protected Integer mDefaultSimVoice = null; 319 // settings put global multi_sim_voice_call $N 320 321 @Option(name = "default-sim-sms", 322 description = "Set the default sim card slot for SMS. Leave unset for single SIM " + 323 "devices") 324 protected Integer mDefaultSimSms = null; 325 // settings put global multi_sim_sms $N 326 327 // Audio 328 private static final boolean DEFAULT_DISABLE_AUDIO = true; 329 @Option(name = "disable-audio", 330 description = "Disable the audio") 331 protected boolean mDisableAudio = DEFAULT_DISABLE_AUDIO; 332 // setprop ro.audio.silent 1" 333 334 @Option(name = "force-skip-system-props", 335 description = "Force setup to not modify any device system properties. All other " + 336 "system property options will be ignored") 337 protected boolean mForceSkipSystemProps = false; 338 339 @Option( 340 name = "force-root-setup", 341 description = 342 "Force switching to root before the setup.Root should only be need for system" 343 + " props, but adding this flag while transitioning in case someone reports" 344 + " issues.") 345 private boolean mForceRoot = false; 346 347 @Option(name = "force-skip-settings", 348 description = "Force setup to not modify any device settings. All other setting " + 349 "options will be ignored.") 350 protected boolean mForceSkipSettings = false; 351 352 @Option(name = "force-skip-run-commands", 353 description = "Force setup to not run any additional commands. All other commands " + 354 "will be ignored.") 355 protected boolean mForceSkipRunCommands = false; 356 357 @Option(name = "set-test-harness", 358 description = "Set the read-only test harness flag on boot") 359 protected boolean mSetTestHarness = true; 360 // setprop ro.monkey 1 361 // setprop ro.test_harness 1 362 // setprop persist.sys.test_harness 1 363 364 @Option(name = "hide-error-dialogs", description = "Turn on or off the error dialogs.") 365 protected BinaryState mHideErrorDialogs = BinaryState.ON; 366 // ON: settings put global hide_error_dialogs 1 367 // OFF: settings put global hide_error_dialogs 0 368 369 @Option( 370 name = "disable-dalvik-verifier", 371 description = 372 "Disable the dalvik verifier on device. Allows package-private " 373 + "framework tests to run.") 374 protected boolean mDisableDalvikVerifier = false; 375 // setprop dalvik.vm.dexopt-flags v=n 376 377 @Option(name = "set-property", 378 description = "Set the specified property on boot. Option may be repeated but only " + 379 "the last value for a given key will be set.") 380 protected Map<String, String> mSetProps = new HashMap<>(); 381 382 @Option( 383 name = "restore-properties", 384 description = 385 "Restore previous /data/local.prop on tear down, restoring any properties" 386 + " DeviceSetup changed by modifying /data/local.prop.") 387 protected boolean mRestoreProperties = false; 388 389 protected File mPreviousProperties; 390 391 @Option(name = "set-system-setting", 392 description = "Change a system (non-secure) setting. Option may be repeated and all " + 393 "key/value pairs will be set in order.") 394 // Use a Multimap since it is possible for a setting to have multiple values for the same key 395 protected MultiMap<String, String> mSystemSettings = new MultiMap<>(); 396 397 @Option(name = "set-secure-setting", 398 description = "Change a secure setting. Option may be repeated and all key/value " + 399 "pairs will be set in order.") 400 // Use a Multimap since it is possible for a setting to have multiple values for the same key 401 protected MultiMap<String, String> mSecureSettings = new MultiMap<>(); 402 403 @Option(name = "set-global-setting", 404 description = "Change a global setting. Option may be repeated and all key/value " + 405 "pairs will be set in order.") 406 // Use a Multimap since it is possible for a setting to have multiple values for the same key 407 protected MultiMap<String, String> mGlobalSettings = new MultiMap<>(); 408 409 @Option( 410 name = "restore-settings", 411 description = "Restore settings modified by this preparer on tear down." 412 ) 413 protected boolean mRestoreSettings = false; 414 415 @Option( 416 name = "optimized-non-persistent-setup", 417 description = "Feature to evaluate a faster non-persistent props setup.") 418 private boolean mOptimizeNonPersistentSetup = true; 419 420 @Option( 421 name = "delay-reboot", 422 description = 423 "Should reboot be needed in the setup, delay it because we know it will occur" 424 + " later.") 425 private boolean mDelayReboot = false; 426 427 @Option( 428 name = "dismiss-setup-wizard", 429 description = "Attempt to dismiss the setup wizard if present.") 430 private boolean mDismissSetupWizard = true; 431 432 @Option( 433 name = "dismiss-setup-wizard-timeout", 434 description = "Set the timeout for dismissing setup wizard in milli seconds.") 435 private Long mDismissSetupWizardTimeout = 60 * 1000L; 436 437 @Option( 438 name = "dismiss-setup-wizard-retry-count", 439 description = "Number of times to retry to dismiss setup wizard.") 440 private int mDismissSetupWizardRetry = 2; 441 442 @Option( 443 name = "check-launcher-package-name", 444 description = "Check the launcher package name to verify setup wizard is dismissed.") 445 private boolean mCheckLauncherPackageName = true; 446 447 private Map<String, String> mPreviousSystemSettings = new HashMap<>(); 448 private Map<String, String> mPreviousSecureSettings = new HashMap<>(); 449 private Map<String, String> mPreviousGlobalSettings = new HashMap<>(); 450 451 protected List<String> mRunCommandBeforeSettings = new ArrayList<>(); 452 453 @Option(name = "run-command", 454 description = "Run an adb shell command. Option may be repeated") 455 protected List<String> mRunCommandAfterSettings = new ArrayList<>(); 456 457 @Option(name = "disconnect-wifi-after-test", 458 description = "Disconnect from wifi network after test completes.") 459 private boolean mDisconnectWifiAfterTest = true; 460 461 private static final long DEFAULT_MIN_EXTERNAL_STORAGE_KB = 500; 462 @Option(name = "min-external-storage-kb", 463 description="The minimum amount of free space in KB that must be present on device's " + 464 "external storage.") 465 protected long mMinExternalStorageKb = DEFAULT_MIN_EXTERNAL_STORAGE_KB; 466 467 @Option(name = "local-data-path", 468 description = "Optional local file path of test data to sync to device's external " + 469 "storage. Use --remote-data-path to set remote location.") 470 protected File mLocalDataFile = null; 471 472 @Option(name = "remote-data-path", 473 description = "Optional file path on device's external storage to sync test data. " + 474 "Must be used with --local-data-path.") 475 protected String mRemoteDataPath = null; 476 477 @Option( 478 name = "optimized-property-setting", 479 description = 480 "If a property is already set to the desired value, don't reboot the device") 481 protected boolean mOptimizedPropertySetting = true; 482 483 // Deprecated options follow 484 /** 485 * @deprecated use min-external-storage-kb instead. 486 */ 487 @Option(name = "min-external-store-space", 488 description = "deprecated, use option min-external-storage-kb. The minimum amount of " + 489 "free space in KB that must be present on device's external storage.") 490 @Deprecated 491 private long mDeprecatedMinExternalStoreSpace = DEFAULT_MIN_EXTERNAL_STORAGE_KB; 492 493 /** 494 * @deprecated use option disable-audio instead. 495 */ 496 @Option(name = "audio-silent", 497 description = "deprecated, use option disable-audio. set ro.audio.silent on boot.") 498 @Deprecated 499 private boolean mDeprecatedSetAudioSilent = DEFAULT_DISABLE_AUDIO; 500 501 /** 502 * @deprecated use option set-property instead. 503 */ 504 @Option(name = "setprop", 505 description = "deprecated, use option set-property. set the specified property on " + 506 "boot. Format: --setprop key=value. May be repeated.") 507 @Deprecated 508 private Collection<String> mDeprecatedSetProps = new ArrayList<String>(); 509 510 @Option( 511 name = "skip-virtual-device-teardown", 512 description = "Whether or not to skip the teardown if it's a virtual device.") 513 private boolean mSkipVirtualDeviceTeardown = true; 514 515 @Option( 516 name = "disable-device-config-sync", 517 description = "Disable syncing device config with remote configuration server.") 518 private boolean mDisableDeviceConfigSync = false; 519 // device_config set_sync_disabled_for_tests persistent 520 521 @Option( 522 name = "disable-ramdump", 523 description = "Will set the flag to disable ramdump on the device.") 524 private boolean mDisableRamdump = false; 525 526 @Option(name = "parallelize-core-setup") 527 private boolean mParallelCoreSetup = false; 528 529 @Option(name = "dismiss-keyguard-via-wm", description = "Flag to dismiss keyguard via wm") 530 private boolean mDismissViaWm = false; 531 532 private static final String PERSIST_PREFIX = "persist."; 533 private static final String MEMTAG_BOOTCTL = "arm64.memtag.bootctl"; 534 535 @Option( 536 name = "enable-testing-secondary-user-on-secondary-display", 537 description = "Enable testing secondary user on secondary display") 538 private boolean mEnableTestingSecondaryUserOnSecondaryDisplay = false; 539 540 private int mTestRunningDisplayId; 541 542 private static final List<String> PROPERTIES_NEEDING_REBOOT = 543 List.of( 544 // MEMTAG_BOOTCTL stores a value in the misc partition that gets applied on 545 // reboot. 546 MEMTAG_BOOTCTL, 547 // Zygote caches the value of this property because it's expected to reboot the 548 // system whenever this property changes. 549 "persist.debug.dalvik.vm.jdwp.enabled"); 550 getDevice(TestInformation testInfo)551 public ITestDevice getDevice(TestInformation testInfo) { 552 return testInfo.getDevice(); 553 } 554 555 /** {@inheritDoc} */ 556 @Override setUp(TestInformation testInfo)557 public void setUp(TestInformation testInfo) 558 throws DeviceNotAvailableException, BuildError, TargetSetupError { 559 ITestDevice device = getDevice(testInfo); 560 CLog.i("Performing setup on %s", device.getSerialNumber()); 561 562 mTestRunningDisplayId = INVALID_DISPLAY; 563 // When testing with a visible background user, 564 // it is necessary to use the displayId being tested. 565 if (mEnableTestingSecondaryUserOnSecondaryDisplay 566 && device.isVisibleBackgroundUsersSupported()) { 567 int testRunningUserId = UserHelper.getRunTestsAsUser(testInfo); 568 CommandResult displayIdByUser = device.executeShellV2Command( 569 "cmd car_service get-display-by-user " + testRunningUserId); 570 if (CommandStatus.SUCCESS.equals(displayIdByUser.getStatus()) 571 && !Strings.isNullOrEmpty(displayIdByUser.getStdout())) { 572 try { 573 mTestRunningDisplayId = Integer.parseInt(displayIdByUser.getStdout().trim()); 574 CLog.d("Running test on displayId: %d", mTestRunningDisplayId); 575 } catch (Exception e) { 576 CLog.e("Failed to parse the displayId due to " + e); 577 } 578 } 579 } 580 581 if (mForceRoot && device.getOptions().isEnableAdbRoot()) { 582 if (!device.enableAdbRoot()) { 583 throw new TargetSetupError( 584 String.format("Failed to enable adb root on %s", device.getSerialNumber()), 585 device.getDeviceDescriptor(), 586 DeviceErrorIdentifier.DEVICE_UNEXPECTED_RESPONSE); 587 } 588 } 589 590 // Convert deprecated options into current options 591 processDeprecatedOptions(device); 592 // Convert options into settings and run commands 593 processOptions(device); 594 // Change system props (will reboot device) 595 changeSystemProps(device); 596 // Run commands designated to be run before changing settings 597 runCommands(device, mRunCommandBeforeSettings); 598 List<Callable<Boolean>> callableTasks = new ArrayList<>(); 599 600 callableTasks.add( 601 () -> { 602 // Handle screen always on setting 603 handleScreenAlwaysOnSetting(device); 604 return true; 605 }); 606 callableTasks.add( 607 () -> { 608 // Change settings 609 changeSettings(device); 610 return true; 611 }); 612 callableTasks.add( 613 () -> { 614 // Connect wifi after settings since this may take a while 615 connectWifi(device); 616 return true; 617 }); 618 callableTasks.add( 619 () -> { 620 // Sync data after settings since this may take a while 621 syncTestData(device); 622 return true; 623 }); 624 callableTasks.add( 625 () -> { 626 // Throw an error if there is not enough storage space 627 checkExternalStoreSpace(device); 628 return true; 629 }); 630 if (mDismissSetupWizard) { 631 callableTasks.add( 632 () -> { 633 dismissSetupWizard(device); 634 return true; 635 }); 636 } 637 if (mParallelCoreSetup) { 638 ParallelDeviceExecutor<Boolean> executor = 639 new ParallelDeviceExecutor<Boolean>(callableTasks.size()); 640 executor.invokeAll(callableTasks, 5, TimeUnit.MINUTES); 641 if (executor.hasErrors()) { 642 List<Throwable> errors = executor.getErrors(); 643 // TODO: Handle throwing multi-exceptions, right now throw the first one. 644 for (Throwable error : errors) { 645 if (error instanceof TargetSetupError) { 646 throw (TargetSetupError) error; 647 } 648 if (error instanceof BuildError) { 649 throw (BuildError) error; 650 } 651 if (error instanceof DeviceNotAvailableException) { 652 throw (DeviceNotAvailableException) error; 653 } 654 throw new RuntimeException(error); 655 } 656 } 657 } else { 658 // Handle screen always on setting 659 handleScreenAlwaysOnSetting(device); 660 // Change settings 661 changeSettings(device); 662 // Connect wifi after settings since this may take a while 663 connectWifi(device); 664 // Sync data after settings since this may take a while 665 syncTestData(device); 666 // Throw an error if there is not enough storage space 667 checkExternalStoreSpace(device); 668 if (mDismissSetupWizard) { 669 dismissSetupWizard(device); 670 } 671 } 672 // Run commands designated to be run after changing settings 673 runCommands(device, mRunCommandAfterSettings); 674 675 device.clearErrorDialogs(); 676 } 677 678 /** {@inheritDoc} */ 679 @Override tearDown(TestInformation testInfo, Throwable e)680 public void tearDown(TestInformation testInfo, Throwable e) throws DeviceNotAvailableException { 681 ITestDevice device = testInfo.getDevice(); 682 // ignore tearDown if it's a stub device, since there is no real device to clean. 683 if (device.getIDevice() instanceof StubDevice) { 684 return; 685 } 686 if (device instanceof RemoteAndroidVirtualDevice && mSkipVirtualDeviceTeardown) { 687 CLog.d("Skipping teardown on virtual device that will be deleted."); 688 return; 689 } 690 if (e instanceof DeviceFailedToBootError) { 691 CLog.d("boot failure: skipping teardown"); 692 return; 693 } 694 if (e instanceof DeviceNotAvailableException) { 695 CLog.d("device not available: skipping teardown"); 696 return; 697 } 698 if (!TestDeviceState.ONLINE.equals(device.getDeviceState())) { 699 CLog.d("device offline: skipping teardown"); 700 return; 701 } 702 CLog.i("Performing teardown on %s", device.getSerialNumber()); 703 704 // Only try to disconnect if wifi ssid is set since isWifiEnabled() is a heavy operation 705 // which should be avoided when possible 706 boolean wifiSet = mWifiSsid != null || !mWifiSsidToPsk.isEmpty(); 707 if (mDisconnectWifiAfterTest && wifiSet && device.isWifiEnabled()) { 708 boolean result = device.disconnectFromWifi(); 709 if (result) { 710 CLog.i("Successfully disconnected from wifi network on %s", 711 device.getSerialNumber()); 712 } else { 713 CLog.w("Failed to disconnect from wifi network on %s", device.getSerialNumber()); 714 } 715 } 716 717 if (mRestoreProperties) { 718 if (mPreviousProperties != null) { 719 device.pushFile(mPreviousProperties, "/data/local.prop"); 720 } else { 721 device.deleteFile("/data/local.prop"); 722 } 723 device.reboot(); 724 } 725 726 if (mRestoreSettings) { 727 for (Map.Entry<String, String> entry : mPreviousSystemSettings.entrySet()) { 728 device.setSetting("system", entry.getKey(), entry.getValue()); 729 } 730 for (Map.Entry<String, String> entry : mPreviousGlobalSettings.entrySet()) { 731 device.setSetting("global", entry.getKey(), entry.getValue()); 732 } 733 for (Map.Entry<String, String> entry : mPreviousSecureSettings.entrySet()) { 734 device.setSetting("secure", entry.getKey(), entry.getValue()); 735 } 736 } 737 } 738 739 /** 740 * Processes the deprecated options converting them into the currently used options. 741 * <p> 742 * This method should be run before any other processing methods. Will throw a 743 * {@link TargetSetupError} if the deprecated option overrides a specified non-deprecated 744 * option. 745 * </p> 746 * @throws TargetSetupError if there is a conflict 747 */ processDeprecatedOptions(ITestDevice device)748 public void processDeprecatedOptions(ITestDevice device) throws TargetSetupError { 749 if (mDeprecatedMinExternalStoreSpace != DEFAULT_MIN_EXTERNAL_STORAGE_KB) { 750 if (mMinExternalStorageKb != DEFAULT_MIN_EXTERNAL_STORAGE_KB) { 751 throw new TargetSetupError("Deprecated option min-external-store-space conflicts " + 752 "with option min-external-storage-kb", device.getDeviceDescriptor()); 753 } 754 mMinExternalStorageKb = mDeprecatedMinExternalStoreSpace; 755 } 756 757 if (mDeprecatedSetAudioSilent != DEFAULT_DISABLE_AUDIO) { 758 if (mDisableAudio != DEFAULT_DISABLE_AUDIO) { 759 throw new TargetSetupError("Deprecated option audio-silent conflicts with " + 760 "option disable-audio", device.getDeviceDescriptor()); 761 } 762 mDisableAudio = mDeprecatedSetAudioSilent; 763 } 764 765 if (!mDeprecatedSetProps.isEmpty()) { 766 if (!mSetProps.isEmpty()) { 767 throw new TargetSetupError("Deprecated option setprop conflicts with option " + 768 "set-property ", device.getDeviceDescriptor()); 769 } 770 for (String prop : mDeprecatedSetProps) { 771 String[] parts = prop.split("=", 2); 772 String key = parts[0].trim(); 773 String value = parts.length == 2 ? parts[1].trim() : ""; 774 mSetProps.put(key, value); 775 } 776 } 777 } 778 779 /** 780 * Process all the {@link Option}s and turn them into system props, settings, or run commands. 781 * Does not run any commands on the device at this time. 782 * <p> 783 * Exposed so that children classes may override this. 784 * </p> 785 * 786 * @param device The {@link ITestDevice} 787 * @throws DeviceNotAvailableException if the device is not available 788 * @throws TargetSetupError if the {@link Option}s conflict 789 */ processOptions(ITestDevice device)790 public void processOptions(ITestDevice device) throws DeviceNotAvailableException, 791 TargetSetupError { 792 setSettingForBinaryState(mData, mGlobalSettings, "mobile_data", "1", "0"); 793 setCommandForBinaryState( 794 mData, mRunCommandAfterSettings, "svc data enable", "svc data disable"); 795 796 setSettingForBinaryState(mCell, mGlobalSettings, "cell_on", "1", "0"); 797 setSettingForBinaryState( 798 mCellAutoSetting, mGlobalSettings, "clockwork_cell_auto_setting", "1", "0"); 799 800 setSettingForBinaryState(mWifi, mGlobalSettings, "wifi_on", "1", "0"); 801 setCommandForBinaryState( 802 mWifi, mRunCommandAfterSettings, "svc wifi enable", "svc wifi disable"); 803 804 setSettingForBinaryState(mWifiWatchdog, mGlobalSettings, "wifi_watchdog", "1", "0"); 805 setSettingForBinaryState( 806 mDisableCwWifiMediator, mGlobalSettings, "cw_disable_wifimediator", "1", "0"); 807 808 setSettingForBinaryState(mWifiScanAlwaysEnabled, mGlobalSettings, 809 "wifi_scan_always_enabled", "1", "0"); 810 811 setCommandForBinaryState(mEthernet, mRunCommandAfterSettings, 812 "ifconfig eth0 up", "ifconfig eth0 down"); 813 814 setCommandForBinaryState( 815 mBluetooth, 816 mRunCommandAfterSettings, 817 "cmd bluetooth_manager enable && cmd bluetooth_manager wait-for-state:STATE_ON", 818 "cmd bluetooth_manager disable && cmd bluetooth_manager wait-for-state:STATE_OFF"); 819 820 setCommandForBinaryState(mNfc, mRunCommandAfterSettings, 821 "svc nfc enable", "svc nfc disable"); 822 823 if (mScreenBrightness != null && BinaryState.ON.equals(mScreenAdaptiveBrightness)) { 824 throw new TargetSetupError("Option screen-brightness cannot be set when " + 825 "screen-adaptive-brightness is set to ON", device.getDeviceDescriptor()); 826 } 827 828 setSettingForBinaryState(mScreenAdaptiveBrightness, mSystemSettings, 829 "screen_brightness_mode", "1", "0"); 830 831 if (mScreenBrightness != null) { 832 mSystemSettings.put("screen_brightness", Integer.toString(mScreenBrightness)); 833 } 834 835 if (mScreenTimeoutSecs != null) { 836 mSystemSettings.put("screen_off_timeout", Long.toString(mScreenTimeoutSecs * 1000)); 837 } 838 839 setSettingForBinaryState(mScreenAmbientMode, mSecureSettings, "doze_enabled", "1", "0"); 840 841 setSettingForBinaryState(mWakeGesture, mSecureSettings, "wake_gesture_enabled", "1", "0"); 842 843 setSettingForBinaryState(mScreenSaver, mSecureSettings, "screensaver_enabled", "1", "0"); 844 845 setSettingForBinaryState(mNotificationLed, mSystemSettings, 846 "notification_light_pulse", "1", "0"); 847 848 setSettingForBinaryState(mInstallNonMarketApps, mSecureSettings, 849 "install_non_market_apps", "1", "0"); 850 851 if (mTriggerMediaMounted) { 852 mRunCommandAfterSettings.add( 853 "am broadcast -a android.intent.action.MEDIA_MOUNTED -d " 854 + "file://${EXTERNAL_STORAGE} --receiver-include-background"); 855 } 856 857 setSettingForBinaryState(mLocationGps, mSecureSettings, 858 "location_providers_allowed", "+gps", "-gps"); 859 860 setSettingForBinaryState(mLocationNetwork, mSecureSettings, 861 "location_providers_allowed", "+network", "-network"); 862 863 setSettingForBinaryState(mAutoRotate, mSystemSettings, "accelerometer_rotation", "1", "0"); 864 865 if (device.getApiLevel() < 22) { 866 setCommandForBinaryState(mBatterySaver, mRunCommandBeforeSettings, 867 "dumpsys battery set usb 0", null); 868 } else { 869 setCommandForBinaryState(mBatterySaver, mRunCommandBeforeSettings, 870 "dumpsys battery unplug", null); 871 } 872 setSettingForBinaryState(mBatterySaver, mGlobalSettings, "low_power", "1", "0"); 873 874 if (mBatterySaverTrigger != null) { 875 mGlobalSettings.put("low_power_trigger_level", Integer.toString(mBatterySaverTrigger)); 876 } 877 878 if (mEnableFullBatteryStatsHistory) { 879 mRunCommandAfterSettings.add("dumpsys batterystats --enable full-history"); 880 } 881 882 if (mDisableDoze) { 883 mRunCommandAfterSettings.add("dumpsys deviceidle disable"); 884 } 885 886 setSettingForBinaryState(mAutoUpdateTime, mGlobalSettings, "auto_time", "1", "0"); 887 888 setSettingForBinaryState(mAutoUpdateTimezone, mGlobalSettings, "auto_timezone", "1", "0"); 889 890 if (BinaryState.ON.equals(mSyncTimezoneWithHost)) { 891 if (mTimezone != null) { 892 throw new TargetSetupError("Option set-timezone cannot be set when " + 893 "sync-timezone-with-host is set to ON", 894 device.getDeviceDescriptor(), 895 InfraErrorIdentifier.OPTION_CONFIGURATION_ERROR); 896 } else { 897 mTimezone = TimeZone.getDefault().getID(); 898 } 899 } 900 901 setSettingForBinaryState( 902 mHideErrorDialogs, mGlobalSettings, "hide_error_dialogs", "1", "0"); 903 904 if (mTimezone != null) { 905 CLog.i("The actual timezone we set here is %s", mTimezone); 906 mSetProps.put("persist.sys.timezone", mTimezone); 907 } 908 909 if (mDisableDialing) { 910 mSetProps.put("ro.telephony.disable-call", "true"); 911 } 912 913 if (mDefaultSimData != null) { 914 mGlobalSettings.put("multi_sim_data_call", Integer.toString(mDefaultSimData)); 915 } 916 917 if (mDefaultSimVoice != null) { 918 mGlobalSettings.put("multi_sim_voice_call", Integer.toString(mDefaultSimVoice)); 919 } 920 921 if (mDefaultSimSms != null) { 922 mGlobalSettings.put("multi_sim_sms", Integer.toString(mDefaultSimSms)); 923 } 924 925 if (mDisableAudio) { 926 mSetProps.put("ro.audio.silent", "1"); 927 } 928 929 if (mSetTestHarness) { 930 // set both ro.monkey, ro.test_harness, persist.sys.test_harness, for compatibility with 931 // older platforms 932 mSetProps.put("ro.monkey", "1"); 933 mSetProps.put("ro.test_harness", "1"); 934 mSetProps.put("persist.sys.test_harness", "1"); 935 } 936 937 if (mDisableDalvikVerifier) { 938 mSetProps.put("dalvik.vm.dexopt-flags", "v=n"); 939 } 940 941 if (mDisableDeviceConfigSync) { 942 mRunCommandBeforeSettings.add("device_config set_sync_disabled_for_tests persistent"); 943 } 944 } 945 946 /** 947 * Change the system properties on the device. 948 * 949 * @param device The {@link ITestDevice} 950 * @throws DeviceNotAvailableException if the device is not available 951 * @throws TargetSetupError if there was a failure setting the system properties 952 */ changeSystemProps(ITestDevice device)953 private void changeSystemProps(ITestDevice device) throws DeviceNotAvailableException, 954 TargetSetupError { 955 if (mForceSkipSystemProps) { 956 CLog.d("Skipping system props due to force-skip-system-props"); 957 return; 958 } 959 960 if (mSetProps.size() > 0 && !device.enableAdbRoot()) { 961 throw new TargetSetupError( 962 String.format( 963 "Cannot set system props %s on %s without adb root. Setting " 964 + "'force-skip-system-props' or 'enable-root' to avoid error", 965 mSetProps.toString(), device.getSerialNumber()), 966 device.getDeviceDescriptor(), 967 InfraErrorIdentifier.OPTION_CONFIGURATION_ERROR); 968 } 969 970 boolean needsReboot = false; 971 // Set persistent props and build a map of all the nonpersistent ones 972 Map<String, String> nonpersistentProps = new HashMap<String, String>(); 973 for (Map.Entry<String, String> prop : mSetProps.entrySet()) { 974 // MEMTAG_BOOTCTL is essentially a persist property. It triggers an action that 975 // stores the value in the misc partition, and gets applied and restored on 976 // reboot. 977 boolean isPersistProperty = 978 prop.getKey().startsWith(PERSIST_PREFIX) 979 || prop.getKey().equals(MEMTAG_BOOTCTL); 980 981 if (isPersistProperty || mOptimizeNonPersistentSetup) { 982 device.setProperty(prop.getKey(), prop.getValue()); 983 } 984 985 if (!isPersistProperty) { 986 nonpersistentProps.put(prop.getKey(), prop.getValue()); 987 } 988 989 if (PROPERTIES_NEEDING_REBOOT.contains(prop.getKey())) { 990 needsReboot = true; 991 } 992 } 993 994 // If the reboot optimization is enabled, only set nonpersistent props if 995 // there are changed values from what the device is running. 996 boolean shouldSetProps = true; 997 if (!mOptimizeNonPersistentSetup 998 && mOptimizedPropertySetting 999 && !nonpersistentProps.isEmpty()) { 1000 boolean allPropsAlreadySet = true; 1001 for (Map.Entry<String, String> prop : nonpersistentProps.entrySet()) { 1002 if (!prop.getValue().equals(device.getProperty(prop.getKey()))) { 1003 allPropsAlreadySet = false; 1004 break; 1005 } 1006 } 1007 if (allPropsAlreadySet) { 1008 shouldSetProps = false; 1009 CLog.i( 1010 "All properties appear to already be set to desired values, skipping" 1011 + " set stage"); 1012 } 1013 } 1014 1015 // Set the nonpersistent properties if needed. 1016 if (!nonpersistentProps.isEmpty() && shouldSetProps) { 1017 StringBuilder sb = new StringBuilder(); 1018 for (Map.Entry<String, String> prop : nonpersistentProps.entrySet()) { 1019 sb.append(String.format("%s=%s\n", prop.getKey(), prop.getValue())); 1020 } 1021 1022 if (mRestoreProperties) { 1023 mPreviousProperties = device.pullFile("/data/local.prop"); 1024 } 1025 CLog.d("Pushing the following properties to /data/local.prop:\n%s", sb.toString()); 1026 boolean result = device.pushString(sb.toString(), "/data/local.prop"); 1027 if (!result) { 1028 throw new TargetSetupError( 1029 String.format( 1030 "Failed to push /data/local.prop to %s", device.getSerialNumber()), 1031 device.getDeviceDescriptor(), 1032 DeviceErrorIdentifier.FAIL_PUSH_FILE); 1033 } 1034 // Set reasonable permissions for /data/local.prop 1035 device.executeShellCommand("chmod 644 /data/local.prop"); 1036 1037 if (mDisableRamdump) { 1038 device.rebootIntoBootloader(); 1039 CLog.i("Disabling ramdump."); 1040 CommandResult resultRampdump = 1041 device.executeFastbootCommand("oem", "ramdump", "disable"); 1042 if (!CommandStatus.SUCCESS.equals(resultRampdump.getStatus())) { 1043 CLog.w( 1044 "Failed to run ramdump disable: status: %s\nstdout: %s\nstderr: %s", 1045 resultRampdump.getStatus(), 1046 resultRampdump.getStdout(), 1047 resultRampdump.getStderr()); 1048 } 1049 } 1050 if (!mOptimizeNonPersistentSetup) { 1051 // non-persistent properties do not trigger a reboot in this 1052 // new setup, if not explicitly set. 1053 needsReboot = true; 1054 } 1055 } 1056 1057 if (needsReboot) { 1058 if (mDelayReboot) { 1059 CLog.i("Delay the reboot to later in the setup."); 1060 } else { 1061 CLog.i("Rebooting %s due to system property change", device.getSerialNumber()); 1062 device.reboot(); 1063 } 1064 } 1065 1066 // Log nonpersistent device properties (that change/lose values after reboot). 1067 String deviceType = device.getClass().getTypeName(); 1068 for (Map.Entry<String, String> prop : mSetProps.entrySet()) { 1069 String expected = prop.getValue(); 1070 String actual = device.getProperty(prop.getKey()); 1071 if ((expected != null && !expected.equals(actual)) 1072 || (expected == null && actual != null)) { 1073 String entry = 1074 String.format("%s-%s(%s:%s)", deviceType, prop.getKey(), expected, actual); 1075 InvocationMetricLogger.addInvocationMetrics( 1076 InvocationMetricKey.NONPERSISTENT_DEVICE_PROPERTIES, entry); 1077 } else { 1078 String entry = String.format("%s-%s(%s)", deviceType, prop.getKey(), actual); 1079 InvocationMetricLogger.addInvocationMetrics( 1080 InvocationMetricKey.PERSISTENT_DEVICE_PROPERTIES, entry); 1081 } 1082 } 1083 } 1084 getInputKeyEventCommand(int keycode)1085 private String getInputKeyEventCommand(int keycode) { 1086 String inputKeyEventCommand = "input keyevent " + keycode; 1087 if (mTestRunningDisplayId != INVALID_DISPLAY) { 1088 inputKeyEventCommand = "input -d " + mTestRunningDisplayId + " keyevent " + keycode; 1089 } 1090 return inputKeyEventCommand; 1091 } 1092 1093 /** 1094 * Handles screen always on settings. 1095 * <p> 1096 * This is done in a dedicated function because special handling is required in case of setting 1097 * screen to always on. 1098 * @throws DeviceNotAvailableException 1099 */ handleScreenAlwaysOnSetting(ITestDevice device)1100 private void handleScreenAlwaysOnSetting(ITestDevice device) 1101 throws DeviceNotAvailableException { 1102 String cmd = "svc power stayon %s"; 1103 switch (mScreenAlwaysOn) { 1104 case ON: 1105 try (CloseableTraceScope ignored = 1106 new CloseableTraceScope(InvocationMetricKey.screen_on_setup.toString())) { 1107 CLog.d("Setting screen always on to true"); 1108 String cmdStayOn = String.format(cmd, "true"); 1109 CommandResult stayOn = device.executeShellV2Command(cmdStayOn); 1110 CLog.d("%s output: %s", cmdStayOn, stayOn); 1111 if (mDismissViaWm) { 1112 CommandResult res = 1113 device.executeShellV2Command( 1114 "wm dismiss-keyguard", 30000L, TimeUnit.MILLISECONDS, 0); 1115 CLog.d("Output of dismiss-keyguard: %s", res); 1116 } else { 1117 // send MENU press in case keyguard needs to be dismissed again 1118 CommandResult inputKey = 1119 device.executeShellV2Command(getInputKeyEventCommand(82)); 1120 CLog.d("Output of input keyevent 82: %s", inputKey); 1121 } 1122 // send HOME press in case keyguard was already dismissed, so we bring device 1123 // back 1124 // to home screen 1125 // No need for this on Wear OS, since that causes the launcher to show 1126 // instead of the home screen 1127 if ((device instanceof TestDevice) 1128 && !device.hasFeature("android.hardware.type.watch")) { 1129 CommandResult inputKey = 1130 device.executeShellV2Command(getInputKeyEventCommand(3)); 1131 CLog.d("Output of input keyevent 3: %s", inputKey); 1132 } 1133 break; 1134 } 1135 case OFF: 1136 CLog.d("Setting screen always on to false"); 1137 device.executeShellCommand(String.format(cmd, "false")); 1138 break; 1139 case IGNORE: 1140 break; 1141 } 1142 } 1143 1144 /** 1145 * Change the settings on the device. 1146 * <p> 1147 * Exposed so children classes may override. 1148 * </p> 1149 * 1150 * @param device The {@link ITestDevice} 1151 * @throws DeviceNotAvailableException if the device is not available 1152 * @throws TargetSetupError if there was a failure setting the settings 1153 */ changeSettings(ITestDevice device)1154 public void changeSettings(ITestDevice device) throws DeviceNotAvailableException, 1155 TargetSetupError { 1156 if (mForceSkipSettings) { 1157 CLog.d("Skipping settings due to force-skip-setttings"); 1158 return; 1159 } 1160 1161 if (mSystemSettings.isEmpty() && mSecureSettings.isEmpty() && mGlobalSettings.isEmpty() && 1162 BinaryState.IGNORE.equals(mAirplaneMode)) { 1163 CLog.d("No settings to change"); 1164 return; 1165 } 1166 1167 if (device.getApiLevel() < 22) { 1168 throw new TargetSetupError(String.format("Changing setting not supported on %s, " + 1169 "must be API 22+", device.getSerialNumber()), device.getDeviceDescriptor()); 1170 } 1171 1172 // Special case airplane mode since it needs to be set before other connectivity settings 1173 // For example, it is possible to enable airplane mode and then turn wifi on 1174 String command = "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state %s"; 1175 switch (mAirplaneMode) { 1176 case ON: 1177 CLog.d("Changing global setting airplane_mode_on to 1"); 1178 device.setSetting("global", "airplane_mode_on", "1"); 1179 if (!mForceSkipRunCommands) { 1180 device.executeShellCommand(String.format(command, "true")); 1181 } 1182 break; 1183 case OFF: 1184 CLog.d("Changing global setting airplane_mode_on to 0"); 1185 device.setSetting("global", "airplane_mode_on", "0"); 1186 if (!mForceSkipRunCommands) { 1187 device.executeShellCommand(String.format(command, "false")); 1188 } 1189 break; 1190 case IGNORE: 1191 // No-op 1192 break; 1193 } 1194 1195 for (String key : mSystemSettings.keySet()) { 1196 for (String value : mSystemSettings.get(key)) { 1197 if (mRestoreSettings) { 1198 String previousSetting = device.getSetting("system", key); 1199 mPreviousSystemSettings.put(key, previousSetting); 1200 } 1201 CLog.d("Changing system setting %s to %s", key, value); 1202 device.setSetting("system", key, value); 1203 } 1204 } 1205 for (String key : mSecureSettings.keySet()) { 1206 for (String value : mSecureSettings.get(key)) { 1207 if (mRestoreSettings) { 1208 String previousSetting = device.getSetting("secure", key); 1209 mPreviousSecureSettings.put(key, previousSetting); 1210 } 1211 CLog.d("Changing secure setting %s to %s", key, value); 1212 device.setSetting("secure", key, value); 1213 } 1214 } 1215 1216 for (String key : mGlobalSettings.keySet()) { 1217 for (String value : mGlobalSettings.get(key)) { 1218 if (mRestoreSettings) { 1219 String previousSetting = device.getSetting("global", key); 1220 mPreviousGlobalSettings.put(key, previousSetting); 1221 } 1222 CLog.d("Changing global setting %s to %s", key, value); 1223 device.setSetting("global", key, value); 1224 } 1225 } 1226 } 1227 1228 /** 1229 * Execute additional commands on the device. 1230 * 1231 * @param device The {@link ITestDevice} 1232 * @param commands The list of commands to run 1233 * @throws DeviceNotAvailableException if the device is not available 1234 * @throws TargetSetupError if there was a failure setting the settings 1235 */ runCommands(ITestDevice device, List<String> commands)1236 private void runCommands(ITestDevice device, List<String> commands) 1237 throws DeviceNotAvailableException, TargetSetupError { 1238 if (mForceSkipRunCommands) { 1239 CLog.d("Skipping run commands due to force-skip-run-commands"); 1240 return; 1241 } 1242 1243 for (String command : commands) { 1244 device.executeShellCommand(command); 1245 } 1246 } 1247 1248 /** 1249 * Connects device to Wifi if SSID is specified. 1250 * 1251 * @param device The {@link ITestDevice} 1252 * @throws DeviceNotAvailableException if the device is not available 1253 * @throws TargetSetupError if there was a failure setting the settings 1254 */ connectWifi(ITestDevice device)1255 private void connectWifi(ITestDevice device) throws DeviceNotAvailableException, 1256 TargetSetupError { 1257 if (mForceSkipRunCommands) { 1258 CLog.d("Skipping connect wifi due to force-skip-run-commands"); 1259 return; 1260 } 1261 if ((mWifiSsid == null || mWifiSsid.isEmpty()) && mWifiSsidToPsk.isEmpty()) { 1262 return; 1263 } 1264 if (mSkipWifi) { 1265 CLog.d("Skipping wifi connection due to skip-wifi-connection"); 1266 return; 1267 } 1268 1269 if (mWifiSsid != null) { 1270 mWifiSsidToPsk.put(mWifiSsid, mWifiPsk); 1271 } 1272 if (device.connectToWifiNetwork(mWifiSsidToPsk)) { 1273 return; 1274 } 1275 1276 if (mWifiSsid != null || !mWifiSsidToPsk.isEmpty()) { 1277 String network = (mWifiSsid == null) ? mWifiSsidToPsk.toString() : mWifiSsid; 1278 InfraErrorIdentifier errorIdentifier = InfraErrorIdentifier.WIFI_FAILED_CONNECT; 1279 if (device instanceof RemoteAndroidVirtualDevice 1280 || device instanceof NestedRemoteDevice 1281 || device instanceof LocalAndroidVirtualDevice) { 1282 // Error identifier for virtual devices. 1283 errorIdentifier = InfraErrorIdentifier.VIRTUAL_WIFI_FAILED_CONNECT; 1284 } 1285 throw new TargetSetupError( 1286 String.format( 1287 "Failed to connect to wifi network %s on %s", 1288 network, device.getSerialNumber()), 1289 device.getDeviceDescriptor(), 1290 errorIdentifier); 1291 } 1292 } 1293 1294 /** 1295 * Syncs a set of test data files, specified via local-data-path, to devices external storage. 1296 * 1297 * @param device The {@link ITestDevice} 1298 * @throws DeviceNotAvailableException if the device is not available 1299 * @throws TargetSetupError if data fails to sync 1300 */ syncTestData(ITestDevice device)1301 private void syncTestData(ITestDevice device) throws DeviceNotAvailableException, 1302 TargetSetupError { 1303 if (mLocalDataFile == null) { 1304 return; 1305 } 1306 1307 if (!mLocalDataFile.exists() || !mLocalDataFile.isDirectory()) { 1308 throw new TargetSetupError(String.format( 1309 "local-data-path %s is not a directory", mLocalDataFile.getAbsolutePath()), 1310 device.getDeviceDescriptor()); 1311 } 1312 String fullRemotePath = device.getIDevice().getMountPoint(IDevice.MNT_EXTERNAL_STORAGE); 1313 if (fullRemotePath == null) { 1314 throw new TargetSetupError(String.format( 1315 "failed to get external storage path on device %s", device.getSerialNumber()), 1316 device.getDeviceDescriptor()); 1317 } 1318 if (mRemoteDataPath != null) { 1319 fullRemotePath = String.format("%s/%s", fullRemotePath, mRemoteDataPath); 1320 } 1321 boolean result = device.syncFiles(mLocalDataFile, fullRemotePath); 1322 if (!result) { 1323 // TODO: get exact error code and respond accordingly 1324 throw new TargetSetupError(String.format( 1325 "failed to sync test data from local-data-path %s to %s on device %s", 1326 mLocalDataFile.getAbsolutePath(), fullRemotePath, device.getSerialNumber()), 1327 device.getDeviceDescriptor()); 1328 } 1329 } 1330 1331 /** 1332 * Check that device external store has the required space 1333 * 1334 * @param device The {@link ITestDevice} 1335 * @throws DeviceNotAvailableException if the device is not available or if the device does not 1336 * have the required space 1337 */ checkExternalStoreSpace(ITestDevice device)1338 private void checkExternalStoreSpace(ITestDevice device) throws DeviceNotAvailableException { 1339 if (mMinExternalStorageKb <= 0) { 1340 return; 1341 } 1342 if (!(device instanceof TestDevice)) { 1343 // TODO: instead check that sdcard exists 1344 return; 1345 } 1346 // Wait for device available to ensure the mounting of sdcard 1347 device.waitForDeviceAvailable(); 1348 long freeSpace = device.getExternalStoreFreeSpace(); 1349 if (freeSpace < mMinExternalStorageKb) { 1350 throw new DeviceNotAvailableException( 1351 String.format( 1352 "External store free space %dK is less than required %dK for device %s", 1353 freeSpace, mMinExternalStorageKb, device.getSerialNumber()), 1354 device.getSerialNumber(), 1355 DeviceErrorIdentifier.DEVICE_UNEXPECTED_RESPONSE); 1356 } 1357 } 1358 dismissSetupWizard(ITestDevice device)1359 private void dismissSetupWizard(ITestDevice device) throws DeviceNotAvailableException { 1360 for (int i = 0; i < mDismissSetupWizardRetry; i++) { 1361 CommandResult cmd1 = 1362 device.executeShellV2Command( 1363 "am start -a com.android.setupwizard.FOUR_CORNER_EXIT"); // Android 1364 // UDC+ 1365 CommandResult cmd2 = 1366 device.executeShellV2Command( 1367 "am start -a com.android.setupwizard.EXIT"); // Android L - T 1368 // if either of the command is successful, count it as success. Otherwise, retry. 1369 if (CommandStatus.SUCCESS.equals(cmd1.getStatus()) 1370 || CommandStatus.SUCCESS.equals(cmd2.getStatus())) { 1371 break; 1372 } 1373 } 1374 // verify setup wizard is dismissed 1375 CLog.d("Waiting %d ms for setup wizard to be dismissed.", mDismissSetupWizardTimeout); 1376 boolean dismissed = false; 1377 long startTime = System.currentTimeMillis(); 1378 while (System.currentTimeMillis() - startTime < mDismissSetupWizardTimeout) { 1379 // check the current focus 1380 CommandResult dumpsysCmdOut = 1381 device.executeShellV2Command("dumpsys window displays | grep mCurrentFocus"); 1382 if (CommandStatus.SUCCESS.equals(dumpsysCmdOut.getStatus()) 1383 && !dumpsysCmdOut.getStdout().contains("setupwizard")) { 1384 if (mCheckLauncherPackageName) { 1385 // Additionally check the launcher package name 1386 CommandResult pkgCmdOut = 1387 device.executeShellV2Command( 1388 "cmd package resolve-activity" 1389 + " -c android.intent.category.HOME" 1390 + " -a android.intent.action.MAIN"); 1391 if (CommandStatus.SUCCESS.equals(pkgCmdOut.getStatus()) 1392 && !pkgCmdOut 1393 .getStdout() 1394 .contains("packageName=com.google.android.setupwizard")) { 1395 CLog.d("Setup wizard is dismissed."); 1396 dismissed = true; 1397 break; 1398 } else { 1399 // abort the check if package service is unavailable 1400 if (dumpsysCmdOut.getStderr() != null 1401 && dumpsysCmdOut 1402 .getStderr() 1403 .contains("Can't find service: package")) { 1404 CLog.d( 1405 "package service is not available. Skip checking setup wizard" 1406 + " dismissal."); 1407 break; 1408 } 1409 // Log the package cmd output for debugging purpose 1410 CLog.d("Package cmd output: %s", pkgCmdOut.getStdout()); 1411 CLog.d("Package cmd stderr: %s", pkgCmdOut.getStderr()); 1412 } 1413 } else { 1414 CLog.d("Setup wizard is dismissed."); 1415 dismissed = true; 1416 break; 1417 } 1418 } else { 1419 // abort the check if window service is unavailable 1420 if (dumpsysCmdOut.getStderr() != null 1421 && dumpsysCmdOut.getStderr().contains("Can't find service: window")) { 1422 CLog.d("window service is not available. Skip checking setupwizard dismissal."); 1423 break; 1424 } 1425 // Log the dumpsys cmd output for debugging purpose 1426 CLog.d("Dumpsys cmd output: %s", dumpsysCmdOut.getStdout()); 1427 CLog.d("Dumpsys cmd stderr: %s", dumpsysCmdOut.getStderr()); 1428 } 1429 RunUtil.getDefault().sleep(2 * 1000); 1430 } 1431 if (!dismissed) { 1432 CLog.w( 1433 "Setup wizard was not dismissed within the timeout limit: %d ms.", 1434 mDismissSetupWizardTimeout); 1435 } 1436 } 1437 1438 /** 1439 * Helper method to add an ON/OFF setting to a setting map. 1440 * 1441 * @param state The {@link BinaryState} 1442 * @param settingsMap The {@link MultiMap} used to store the settings. 1443 * @param setting The setting key 1444 * @param onValue The value if ON 1445 * @param offValue The value if OFF 1446 */ setSettingForBinaryState(BinaryState state, MultiMap<String, String> settingsMap, String setting, String onValue, String offValue)1447 public static void setSettingForBinaryState(BinaryState state, 1448 MultiMap<String, String> settingsMap, String setting, String onValue, String offValue) { 1449 switch (state) { 1450 case ON: 1451 settingsMap.put(setting, onValue); 1452 break; 1453 case OFF: 1454 settingsMap.put(setting, offValue); 1455 break; 1456 case IGNORE: 1457 // Do nothing 1458 break; 1459 } 1460 } 1461 1462 /** 1463 * Helper method to add an ON/OFF run command to be executed on the device. 1464 * 1465 * @param state The {@link BinaryState} 1466 * @param commands The list of commands to add the on or off command to. 1467 * @param onCommand The command to run if ON. Ignored if the command is {@code null} 1468 * @param offCommand The command to run if OFF. Ignored if the command is {@code null} 1469 */ setCommandForBinaryState(BinaryState state, List<String> commands, String onCommand, String offCommand)1470 public static void setCommandForBinaryState(BinaryState state, List<String> commands, 1471 String onCommand, String offCommand) { 1472 switch (state) { 1473 case ON: 1474 if (onCommand != null) { 1475 commands.add(onCommand); 1476 } 1477 break; 1478 case OFF: 1479 if (offCommand != null) { 1480 commands.add(offCommand); 1481 } 1482 break; 1483 case IGNORE: 1484 // Do nothing 1485 break; 1486 } 1487 } 1488 1489 /** Exposed for unit testing */ setForceSkipSystemProps(boolean force)1490 protected void setForceSkipSystemProps(boolean force) { 1491 mForceSkipSystemProps = force; 1492 } 1493 setForceRootSetup(boolean force)1494 protected void setForceRootSetup(boolean force) { 1495 mForceRoot = force; 1496 } 1497 isForceSkipSystemProps()1498 public boolean isForceSkipSystemProps() { 1499 return mForceSkipSystemProps; 1500 } 1501 1502 /** 1503 * Exposed for unit testing 1504 */ setAirplaneMode(BinaryState airplaneMode)1505 protected void setAirplaneMode(BinaryState airplaneMode) { 1506 mAirplaneMode = airplaneMode; 1507 } 1508 1509 /* Exposed for unit testing */ 1510 @VisibleForTesting setData(BinaryState data)1511 protected void setData(BinaryState data) { 1512 mData = data; 1513 } 1514 1515 /* Exposed for unit testing */ 1516 @VisibleForTesting setCell(BinaryState cell)1517 protected void setCell(BinaryState cell) { 1518 mCell = cell; 1519 } 1520 1521 /* Exposed for unit testing */ 1522 @VisibleForTesting setCellAutoSetting(BinaryState cellAutoSetting)1523 protected void setCellAutoSetting(BinaryState cellAutoSetting) { 1524 mCellAutoSetting = cellAutoSetting; 1525 } 1526 1527 /** 1528 * Exposed for unit testing 1529 */ setWifi(BinaryState wifi)1530 protected void setWifi(BinaryState wifi) { 1531 mWifi = wifi; 1532 } 1533 1534 /** 1535 * Exposed for unit testing 1536 */ setWifiNetwork(String wifiNetwork)1537 protected void setWifiNetwork(String wifiNetwork) { 1538 mWifiSsid = wifiNetwork; 1539 } 1540 1541 /* Exposed for unit testing */ 1542 @VisibleForTesting setWifiPsk(String wifiPsk)1543 protected void setWifiPsk(String wifiPsk) { 1544 mWifiPsk = wifiPsk; 1545 } 1546 1547 /* Exposed for unit testing */ 1548 @VisibleForTesting setWifiSsidToPsk(Map<String, String> wifiSssidToPsk)1549 protected void setWifiSsidToPsk(Map<String, String> wifiSssidToPsk) { 1550 mWifiSsidToPsk = wifiSssidToPsk; 1551 } 1552 1553 /** 1554 * Exposed for unit testing 1555 */ setWifiWatchdog(BinaryState wifiWatchdog)1556 protected void setWifiWatchdog(BinaryState wifiWatchdog) { 1557 mWifiWatchdog = wifiWatchdog; 1558 } 1559 1560 /* Exposed for unit testing */ 1561 @VisibleForTesting setDisableCwWifiMediator(BinaryState disableCwWifiMediator)1562 protected void setDisableCwWifiMediator(BinaryState disableCwWifiMediator) { 1563 mDisableCwWifiMediator = disableCwWifiMediator; 1564 } 1565 1566 /** 1567 * Exposed for unit testing 1568 */ setWifiScanAlwaysEnabled(BinaryState wifiScanAlwaysEnabled)1569 protected void setWifiScanAlwaysEnabled(BinaryState wifiScanAlwaysEnabled) { 1570 mWifiScanAlwaysEnabled = wifiScanAlwaysEnabled; 1571 } 1572 1573 /** 1574 * Exposed for unit testing 1575 */ setEthernet(BinaryState ethernet)1576 protected void setEthernet(BinaryState ethernet) { 1577 mEthernet = ethernet; 1578 } 1579 1580 /** 1581 * Exposed for unit testing 1582 */ setBluetooth(BinaryState bluetooth)1583 protected void setBluetooth(BinaryState bluetooth) { 1584 mBluetooth = bluetooth; 1585 } 1586 1587 /** 1588 * Exposed for unit testing 1589 */ setNfc(BinaryState nfc)1590 protected void setNfc(BinaryState nfc) { 1591 mNfc = nfc; 1592 } 1593 1594 /** 1595 * Exposed for unit testing 1596 */ setScreenAdaptiveBrightness(BinaryState screenAdaptiveBrightness)1597 protected void setScreenAdaptiveBrightness(BinaryState screenAdaptiveBrightness) { 1598 mScreenAdaptiveBrightness = screenAdaptiveBrightness; 1599 } 1600 1601 /** 1602 * Exposed for unit testing 1603 */ setScreenBrightness(Integer screenBrightness)1604 protected void setScreenBrightness(Integer screenBrightness) { 1605 mScreenBrightness = screenBrightness; 1606 } 1607 1608 /** 1609 * Exposed for unit testing 1610 */ setScreenAlwaysOn(BinaryState screenAlwaysOn)1611 protected void setScreenAlwaysOn(BinaryState screenAlwaysOn) { 1612 mScreenAlwaysOn = screenAlwaysOn; 1613 } 1614 1615 /** 1616 * Exposed for unit testing 1617 */ setScreenTimeoutSecs(Long screenTimeoutSecs)1618 protected void setScreenTimeoutSecs(Long screenTimeoutSecs) { 1619 mScreenTimeoutSecs = screenTimeoutSecs; 1620 } 1621 1622 /** 1623 * Exposed for unit testing 1624 */ setScreenAmbientMode(BinaryState screenAmbientMode)1625 protected void setScreenAmbientMode(BinaryState screenAmbientMode) { 1626 mScreenAmbientMode = screenAmbientMode; 1627 } 1628 1629 /** 1630 * Exposed for unit testing 1631 */ setWakeGesture(BinaryState wakeGesture)1632 protected void setWakeGesture(BinaryState wakeGesture) { 1633 mWakeGesture = wakeGesture; 1634 } 1635 1636 /** 1637 * Exposed for unit testing 1638 */ setScreenSaver(BinaryState screenSaver)1639 protected void setScreenSaver(BinaryState screenSaver) { 1640 mScreenSaver = screenSaver; 1641 } 1642 1643 /** 1644 * Exposed for unit testing 1645 */ setNotificationLed(BinaryState notificationLed)1646 protected void setNotificationLed(BinaryState notificationLed) { 1647 mNotificationLed = notificationLed; 1648 } 1649 1650 /** 1651 * Exposed for unit testing 1652 */ setInstallNonMarketApps(BinaryState installNonMarketApps)1653 protected void setInstallNonMarketApps(BinaryState installNonMarketApps) { 1654 mInstallNonMarketApps = installNonMarketApps; 1655 } 1656 1657 /** 1658 * Exposed for unit testing 1659 */ setTriggerMediaMounted(boolean triggerMediaMounted)1660 protected void setTriggerMediaMounted(boolean triggerMediaMounted) { 1661 mTriggerMediaMounted = triggerMediaMounted; 1662 } 1663 1664 /** 1665 * Exposed for unit testing 1666 */ setLocationGps(BinaryState locationGps)1667 protected void setLocationGps(BinaryState locationGps) { 1668 mLocationGps = locationGps; 1669 } 1670 1671 /** 1672 * Exposed for unit testing 1673 */ setLocationNetwork(BinaryState locationNetwork)1674 protected void setLocationNetwork(BinaryState locationNetwork) { 1675 mLocationNetwork = locationNetwork; 1676 } 1677 1678 /** 1679 * Exposed for unit testing 1680 */ setAutoRotate(BinaryState autoRotate)1681 protected void setAutoRotate(BinaryState autoRotate) { 1682 mAutoRotate = autoRotate; 1683 } 1684 1685 /** 1686 * Exposed for unit testing 1687 */ setBatterySaver(BinaryState batterySaver)1688 protected void setBatterySaver(BinaryState batterySaver) { 1689 mBatterySaver = batterySaver; 1690 } 1691 1692 /** 1693 * Exposed for unit testing 1694 */ setBatterySaverTrigger(Integer batterySaverTrigger)1695 protected void setBatterySaverTrigger(Integer batterySaverTrigger) { 1696 mBatterySaverTrigger = batterySaverTrigger; 1697 } 1698 1699 /** 1700 * Exposed for unit testing 1701 */ setEnableFullBatteryStatsHistory(boolean enableFullBatteryStatsHistory)1702 protected void setEnableFullBatteryStatsHistory(boolean enableFullBatteryStatsHistory) { 1703 mEnableFullBatteryStatsHistory = enableFullBatteryStatsHistory; 1704 } 1705 1706 /** 1707 * Exposed for unit testing 1708 */ setDisableDoze(boolean disableDoze)1709 protected void setDisableDoze(boolean disableDoze) { 1710 mDisableDoze = disableDoze; 1711 } 1712 1713 /** 1714 * Exposed for unit testing 1715 */ setAutoUpdateTime(BinaryState autoUpdateTime)1716 protected void setAutoUpdateTime(BinaryState autoUpdateTime) { 1717 mAutoUpdateTime = autoUpdateTime; 1718 } 1719 1720 /** 1721 * Exposed for unit testing 1722 */ setAutoUpdateTimezone(BinaryState autoUpdateTimezone)1723 protected void setAutoUpdateTimezone(BinaryState autoUpdateTimezone) { 1724 mAutoUpdateTimezone = autoUpdateTimezone; 1725 } 1726 1727 /** 1728 * Exposed for unit testing 1729 */ setTimezone(String timezone)1730 protected void setTimezone(String timezone) { 1731 mTimezone = timezone; 1732 } 1733 1734 /** 1735 * Exposed for unit testing 1736 */ setDisableDialing(boolean disableDialing)1737 protected void setDisableDialing(boolean disableDialing) { 1738 mDisableDialing = disableDialing; 1739 } 1740 1741 /** 1742 * Exposed for unit testing 1743 */ setDefaultSimData(Integer defaultSimData)1744 protected void setDefaultSimData(Integer defaultSimData) { 1745 mDefaultSimData = defaultSimData; 1746 } 1747 1748 /** 1749 * Exposed for unit testing 1750 */ setDefaultSimVoice(Integer defaultSimVoice)1751 protected void setDefaultSimVoice(Integer defaultSimVoice) { 1752 mDefaultSimVoice = defaultSimVoice; 1753 } 1754 1755 /** 1756 * Exposed for unit testing 1757 */ setDefaultSimSms(Integer defaultSimSms)1758 protected void setDefaultSimSms(Integer defaultSimSms) { 1759 mDefaultSimSms = defaultSimSms; 1760 } 1761 1762 /** 1763 * Exposed for unit testing 1764 */ setDisableAudio(boolean disable)1765 protected void setDisableAudio(boolean disable) { 1766 mDisableAudio = disable; 1767 } 1768 1769 /** 1770 * Exposed for unit testing 1771 */ setTestHarness(boolean setTestHarness)1772 protected void setTestHarness(boolean setTestHarness) { 1773 mSetTestHarness = setTestHarness; 1774 } 1775 1776 /** 1777 * Exposed for unit testing 1778 */ setDisableDalvikVerifier(boolean disableDalvikVerifier)1779 protected void setDisableDalvikVerifier(boolean disableDalvikVerifier) { 1780 mDisableDalvikVerifier = disableDalvikVerifier; 1781 } 1782 1783 /** 1784 * Exposed for unit testing 1785 */ setLocalDataPath(File path)1786 protected void setLocalDataPath(File path) { 1787 mLocalDataFile = path; 1788 } 1789 1790 /** 1791 * Exposed for unit testing 1792 */ setMinExternalStorageKb(long storageKb)1793 protected void setMinExternalStorageKb(long storageKb) { 1794 mMinExternalStorageKb = storageKb; 1795 } 1796 1797 /** 1798 * Exposed for unit testing 1799 */ setProperty(String key, String value)1800 protected void setProperty(String key, String value) { 1801 mSetProps.put(key, value); 1802 } 1803 1804 /** Exposed for unit testing */ setGlobalSetting(String key, String value)1805 public void setGlobalSetting(String key, String value) { 1806 mGlobalSettings.put(key, value); 1807 } 1808 1809 /** Exposed for unit testing */ setSecureSetting(String key, String value)1810 public void setSecureSetting(String key, String value) { 1811 mSecureSettings.put(key, value); 1812 } 1813 1814 /** Exposed for unit testing */ setSystemSetting(String key, String value)1815 public void setSystemSetting(String key, String value) { 1816 mSystemSettings.put(key, value); 1817 } 1818 1819 /** Exposed for unit testing */ setRestoreProperties(boolean restoreProperties)1820 protected void setRestoreProperties(boolean restoreProperties) { 1821 mRestoreProperties = restoreProperties; 1822 } 1823 1824 /** Exposed for unit testing */ setRestoreSettings(boolean restoreSettings)1825 protected void setRestoreSettings(boolean restoreSettings) { 1826 mRestoreSettings = restoreSettings; 1827 } 1828 1829 /** 1830 * Exposed for unit testing 1831 * @deprecated use {@link #setMinExternalStorageKb(long)} instead. 1832 */ 1833 @Deprecated setDeprecatedMinExternalStoreSpace(long storeSpace)1834 protected void setDeprecatedMinExternalStoreSpace(long storeSpace) { 1835 mDeprecatedMinExternalStoreSpace = storeSpace; 1836 } 1837 1838 /** 1839 * Exposed for unit testing 1840 * @deprecated use {@link #setDisableAudio(boolean)} instead. 1841 */ 1842 @Deprecated setDeprecatedAudioSilent(boolean silent)1843 protected void setDeprecatedAudioSilent(boolean silent) { 1844 mDeprecatedSetAudioSilent = silent; 1845 } 1846 1847 /** 1848 * Exposed for unit testing 1849 * @deprecated use {@link #setProperty(String, String)} instead. 1850 */ 1851 @Deprecated setDeprecatedSetProp(String prop)1852 protected void setDeprecatedSetProp(String prop) { 1853 mDeprecatedSetProps.add(prop); 1854 } 1855 1856 @Override getDependencies()1857 public Set<ExternalDependency> getDependencies() { 1858 Set<ExternalDependency> externalDependencies = new LinkedHashSet<>(); 1859 // check if we need mobile data 1860 if (BinaryState.ON.equals(mData)) { 1861 externalDependencies.add(new TelephonyDependency()); 1862 } 1863 // check if we need wifi 1864 if (!mSkipWifi && !(Strings.isNullOrEmpty(mWifiSsid) && mWifiSsidToPsk.isEmpty())) { 1865 externalDependencies.add(new NetworkDependency()); 1866 } 1867 // check if we need ethernet 1868 if (BinaryState.ON.equals(mEthernet)) { 1869 externalDependencies.add(new EthernetDependency()); 1870 } 1871 // check if we need bluetooth 1872 if (BinaryState.ON.equals(mBluetooth)) { 1873 externalDependencies.add(new BluetoothDependency()); 1874 } 1875 // check if we need location-network 1876 if (BinaryState.ON.equals(mLocationNetwork)) { 1877 externalDependencies.add(new NetworkDependency()); 1878 } 1879 return externalDependencies; 1880 } 1881 } 1882