1 /* 2 * Copyright (C) 2011 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 package com.android.tradefed.device; 17 18 import com.android.ddmlib.Log.LogLevel; 19 import com.android.tradefed.config.Option; 20 import com.android.tradefed.util.ArrayUtil; 21 22 import java.io.File; 23 import java.util.ArrayList; 24 import java.util.Collections; 25 import java.util.HashSet; 26 import java.util.List; 27 import java.util.Set; 28 29 /** 30 * Container for {@link ITestDevice} {@link Option}s 31 */ 32 public class TestDeviceOptions { 33 34 public enum InstanceType { 35 /** A device that we remotely access via ssh and adb connect */ 36 GCE, 37 REMOTE_AVD, 38 /** 39 * A remote device inside an emulator that we access via ssh to the instance hosting the 40 * emulator then adb connect. 41 */ 42 CUTTLEFISH, 43 REMOTE_NESTED_AVD, 44 /** An android emulator. */ 45 EMULATOR, 46 /** Chrome OS VM (betty) */ 47 CHEEPS, 48 } 49 50 public static final int DEFAULT_ADB_PORT = 5555; 51 public static final String INSTANCE_TYPE_OPTION = "instance-type"; 52 53 /** Do not provide a setter method for that Option as it might be misused. */ 54 @Option(name = "enable-root", description = "enable adb root on boot.") 55 private boolean mEnableAdbRoot = true; 56 57 @Option(name = "disable-keyguard", 58 description = "attempt to disable keyguard once boot is complete.") 59 private boolean mDisableKeyguard = true; 60 61 @Option(name = "enable-logcat", description = 62 "Enable background logcat capture when invocation is running.") 63 private boolean mEnableLogcat = true; 64 65 @Option(name = "max-tmp-logcat-file", description = 66 "The maximum size of tmp logcat data to retain, in bytes. " + 67 "Only used if --enable-logcat is set") 68 private long mMaxLogcatDataSize = 20 * 1024 * 1024; 69 70 @Option(name = "logcat-options", description = 71 "Options to be passed down to logcat command, if unspecified, \"-v threadtime\" will " + 72 "be used. Only used if --enable-logcat is set") 73 private String mLogcatOptions = null; 74 75 @Option(name = "fastboot-timeout", description = 76 "time in ms to wait for a device to boot into fastboot.") 77 private int mFastbootTimeout = 1 * 60 * 1000; 78 79 @Option(name = "adb-recovery-timeout", description = 80 "time in ms to wait for a device to boot into recovery.") 81 private int mAdbRecoveryTimeout = 1 * 60 * 1000; 82 83 @Option(name = "reboot-timeout", description = 84 "time in ms to wait for a device to reboot to full system.") 85 private int mRebootTimeout = 2 * 60 * 1000; 86 87 @Option(name = "use-fastboot-erase", description = 88 "use fastboot erase instead of fastboot format to wipe partitions") 89 private boolean mUseFastbootErase = false; 90 91 @Option(name = "unencrypt-reboot-timeout", description = "time in ms to wait for the device to " 92 + "format the filesystem and reboot after unencryption") 93 private int mUnencryptRebootTimeout = 0; 94 95 @Option(name = "online-timeout", description = "default time in ms to wait for the device to " 96 + "be visible on adb.", isTimeVal = true) 97 private long mOnlineTimeout = 1 * 60 * 1000; 98 99 @Option(name = "available-timeout", description = "default time in ms to wait for the device " 100 + "to be available aka fully boot.") 101 private long mAvailableTimeout = 6 * 60 * 1000; 102 103 @Option(name = "conn-check-url", 104 description = "default URL to be used for connectivity checks.") 105 private String mConnCheckUrl = "http://www.google.com"; 106 107 @Option(name = "wifi-attempts", 108 description = "default number of attempts to connect to wifi network.") 109 private int mWifiAttempts = 5; 110 111 @Option(name = "wifi-retry-wait-time", 112 description = "the base wait time in ms between wifi connect retries. " 113 + "The actual wait time would be a multiple of this value.") 114 private int mWifiRetryWaitTime = 60 * 1000; 115 116 @Option( 117 name = "max-wifi-connect-time", 118 isTimeVal = true, 119 description = "the maximum amount of time to attempt to connect to wifi." 120 ) 121 private long mMaxWifiConnectTime = 10 * 60 * 1000; 122 123 @Option(name = "wifi-exponential-retry", 124 description = "Change the wifi connection retry strategy from a linear wait time into" 125 + " a binary exponential back-offs when retrying.") 126 private boolean mWifiExpoRetryEnabled = true; 127 128 @Option(name = "wifiutil-apk-path", description = "path to the wifiutil APK file") 129 private String mWifiUtilAPKPath = null; 130 131 @Option(name = "post-boot-command", 132 description = "shell command to run after reboots during invocation") 133 private List<String> mPostBootCommands = new ArrayList<String>(); 134 135 @Option(name = "disable-reboot", 136 description = "disables device reboots globally, making them no-ops") 137 private boolean mDisableReboot = false; 138 139 @Option(name = "cutoff-battery", description = 140 "the minimum battery level required to continue the invocation. Scale: 0-100") 141 private Integer mCutoffBattery = null; 142 143 @Option( 144 name = "use-content-provider", 145 description = 146 "Allow to disable the use of the content provider at the device level. " 147 + "This results in falling back to standard adb push/pull." 148 ) 149 private boolean mUseContentProvider = true; 150 151 // ====================== Options Related to Virtual Devices ====================== 152 @Option( 153 name = INSTANCE_TYPE_OPTION, 154 description = "The type of virtual device instance to create") 155 private InstanceType mInstanceType = InstanceType.GCE; 156 157 @Option( 158 name = "gce-boot-timeout", 159 description = "timeout to wait in ms for GCE to be online.", 160 isTimeVal = true) 161 private long mGceCmdTimeout = 30 * 60 * 1000; // 30 minutes. 162 163 @Option(name = "gce-driver-path", description = "path of the binary to launch GCE devices") 164 private File mAvdDriverBinary = null; 165 166 @Option( 167 name = "gce-driver-config-path", 168 description = "path of the config to use to launch GCE devices.") 169 private File mAvdConfigFile = null; 170 171 @Option( 172 name = "gce-driver-config-test-resource-name", 173 description = "Test resource name of the config to use to launch GCE devices.") 174 private String mAvdConfigTestResourceName; 175 176 @Option( 177 name = "gce-driver-service-account-json-key-path", 178 description = "path to the service account json key location.") 179 private File mJsonKeyFile = null; 180 181 @Option( 182 name = "gce-private-key-path", 183 description = "path to the ssh key private key location.") 184 private File mSshPrivateKeyPath = new File("~/.ssh/id_rsa"); 185 186 @Option(name = "gce-driver-log-level", description = "Log level for gce driver") 187 private LogLevel mGceDriverLogLevel = LogLevel.DEBUG; 188 189 @Option( 190 name = "gce-driver-param", 191 description = "Additional args to pass to gce driver as parameters." 192 ) 193 private List<String> mGceDriverParams = new ArrayList<>(); 194 195 @Deprecated 196 @Option( 197 name = "gce-driver-build-id-param", 198 description = 199 "The parameter to be paired with " 200 + "build id from build info when passed down to gce driver" 201 ) 202 private String mGceDriverBuildIdParam = "build_id"; 203 204 @Option(name = "gce-account", description = "email account to use with GCE driver.") 205 private String mGceAccount = null; 206 207 @Option( 208 name = "max-gce-attempt", 209 description = "Maximum number of attempts to start Gce before throwing an exception." 210 ) 211 private int mGceMaxAttempt = 1; 212 213 @Option( 214 name = "skip-gce-teardown", 215 description = 216 "Whether or not to skip the GCE tear down. Skipping tear down will " 217 + "result in the instance being left.") 218 private boolean mSkipTearDown = false; 219 220 @Option( 221 name = "wait-gce-teardown", 222 description = "Whether or not to block on gce teardown before proceeding.") 223 private boolean mWaitForGceTearDown = false; 224 225 @Option( 226 name = "instance-user", 227 description = 228 "The account to be used to interact with the " 229 + "outer layer of the GCE VM, e.g. to SSH in") 230 private String mInstanceUser = "root"; 231 232 @Option( 233 name = "remote-adb-port", 234 description = "The port on remote instance where the adb " + "server listens to.") 235 private int mRemoteAdbPort = DEFAULT_ADB_PORT; 236 237 @Option( 238 name = "base-host-image", 239 description = "The base image to be used for the GCE VM to host emulator.") 240 private String mBaseImage = null; 241 242 @Option( 243 name = "remote-fetch-file-pattern", 244 description = 245 "Only for remote VM devices. Allows to specify patterns to fetch file on the " 246 + "remote VM via scp. Pattern must follow the scp notations." 247 ) 248 private Set<String> mRemoteFetchFilePattern = new HashSet<>(); 249 250 // END ====================== Options Related to Virtual Devices ====================== 251 252 /** Check whether adb root should be enabled on boot for this device */ isEnableAdbRoot()253 public boolean isEnableAdbRoot() { 254 return mEnableAdbRoot; 255 } 256 257 /** 258 * Check whether or not we should attempt to disable the keyguard once boot has completed 259 */ isDisableKeyguard()260 public boolean isDisableKeyguard() { 261 return mDisableKeyguard; 262 } 263 264 /** 265 * Set whether or not we should attempt to disable the keyguard once boot has completed 266 */ setDisableKeyguard(boolean disableKeyguard)267 public void setDisableKeyguard(boolean disableKeyguard) { 268 mDisableKeyguard = disableKeyguard; 269 } 270 271 /** 272 * Get the approximate maximum size of a tmp logcat data to retain, in bytes. 273 */ getMaxLogcatDataSize()274 public long getMaxLogcatDataSize() { 275 return mMaxLogcatDataSize; 276 } 277 278 /** 279 * Set the approximate maximum size of a tmp logcat to retain, in bytes 280 */ setMaxLogcatDataSize(long maxLogcatDataSize)281 public void setMaxLogcatDataSize(long maxLogcatDataSize) { 282 mMaxLogcatDataSize = maxLogcatDataSize; 283 } 284 285 /** 286 * @return the timeout to boot into fastboot mode in msecs. 287 */ getFastbootTimeout()288 public int getFastbootTimeout() { 289 return mFastbootTimeout; 290 } 291 292 /** 293 * @param fastbootTimeout the timout in msecs to boot into fastboot mode. 294 */ setFastbootTimeout(int fastbootTimeout)295 public void setFastbootTimeout(int fastbootTimeout) { 296 mFastbootTimeout = fastbootTimeout; 297 } 298 299 /** 300 * @return the timeout in msecs to boot into recovery mode. 301 */ getAdbRecoveryTimeout()302 public int getAdbRecoveryTimeout() { 303 return mAdbRecoveryTimeout; 304 } 305 306 /** 307 * @param adbRecoveryTimeout the timeout in msecs to boot into recovery mode. 308 */ setAdbRecoveryTimeout(int adbRecoveryTimeout)309 public void setAdbRecoveryTimeout(int adbRecoveryTimeout) { 310 mAdbRecoveryTimeout = adbRecoveryTimeout; 311 } 312 313 /** 314 * @return the timeout in msecs for the full system boot. 315 */ getRebootTimeout()316 public int getRebootTimeout() { 317 return mRebootTimeout; 318 } 319 320 /** 321 * @param rebootTimeout the timeout in msecs for the system to fully boot. 322 */ setRebootTimeout(int rebootTimeout)323 public void setRebootTimeout(int rebootTimeout) { 324 mRebootTimeout = rebootTimeout; 325 } 326 327 /** 328 * @return whether to use fastboot erase instead of fastboot format to wipe partitions. 329 */ getUseFastbootErase()330 public boolean getUseFastbootErase() { 331 return mUseFastbootErase; 332 } 333 334 /** 335 * @param useFastbootErase whether to use fastboot erase instead of fastboot format to wipe 336 * partitions. 337 */ setUseFastbootErase(boolean useFastbootErase)338 public void setUseFastbootErase(boolean useFastbootErase) { 339 mUseFastbootErase = useFastbootErase; 340 } 341 342 /** 343 * @return the timeout in msecs for the filesystem to be formatted and the device to reboot 344 * after unencryption. 345 */ getUnencryptRebootTimeout()346 public int getUnencryptRebootTimeout() { 347 return mUnencryptRebootTimeout; 348 } 349 350 /** 351 * @param unencryptRebootTimeout the timeout in msecs for the filesystem to be formatted and 352 * the device to reboot after unencryption. 353 */ setUnencryptRebootTimeout(int unencryptRebootTimeout)354 public void setUnencryptRebootTimeout(int unencryptRebootTimeout) { 355 mUnencryptRebootTimeout = unencryptRebootTimeout; 356 } 357 358 /** 359 * @return the default time in ms to to wait for a device to be online. 360 */ getOnlineTimeout()361 public long getOnlineTimeout() { 362 return mOnlineTimeout; 363 } 364 setOnlineTimeout(long onlineTimeout)365 public void setOnlineTimeout(long onlineTimeout) { 366 mOnlineTimeout = onlineTimeout; 367 } 368 369 /** 370 * @return the default time in ms to to wait for a device to be available. 371 */ getAvailableTimeout()372 public long getAvailableTimeout() { 373 return mAvailableTimeout; 374 } 375 376 /** 377 * @return the default URL to be used for connectivity tests. 378 */ getConnCheckUrl()379 public String getConnCheckUrl() { 380 return mConnCheckUrl; 381 } 382 setConnCheckUrl(String url)383 public void setConnCheckUrl(String url) { 384 mConnCheckUrl = url; 385 } 386 387 /** 388 * @return true if background logcat capture is enabled 389 */ isLogcatCaptureEnabled()390 public boolean isLogcatCaptureEnabled() { 391 return mEnableLogcat; 392 } 393 394 /** 395 * @return the default number of attempts to connect to wifi network. 396 */ getWifiAttempts()397 public int getWifiAttempts() { 398 return mWifiAttempts; 399 } 400 setWifiAttempts(int wifiAttempts)401 public void setWifiAttempts(int wifiAttempts) { 402 mWifiAttempts = wifiAttempts; 403 } 404 405 /** 406 * @return the base wait time between wifi connect retries. 407 */ getWifiRetryWaitTime()408 public int getWifiRetryWaitTime() { 409 return mWifiRetryWaitTime; 410 } 411 412 /** @return the maximum time to attempt to connect to wifi. */ getMaxWifiConnectTime()413 public long getMaxWifiConnectTime() { 414 return mMaxWifiConnectTime; 415 } 416 417 /** 418 * @return a list of shell commands to run after reboots. 419 */ getPostBootCommands()420 public List<String> getPostBootCommands() { 421 return mPostBootCommands; 422 } 423 424 /** 425 * @return the minimum battery level to continue the invocation. 426 */ getCutoffBattery()427 public Integer getCutoffBattery() { 428 return mCutoffBattery; 429 } 430 431 /** 432 * set the minimum battery level to continue the invocation. 433 */ setCutoffBattery(int cutoffBattery)434 public void setCutoffBattery(int cutoffBattery) { 435 if (cutoffBattery < 0 || cutoffBattery > 100) { 436 // Prevent impossible value. 437 throw new RuntimeException(String.format("Battery cutoff wasn't changed," 438 + "the value %s isn't within possible range (0-100).", cutoffBattery)); 439 } 440 mCutoffBattery = cutoffBattery; 441 } 442 443 /** 444 * @return the configured logcat options 445 */ getLogcatOptions()446 public String getLogcatOptions() { 447 return mLogcatOptions; 448 } 449 450 /** 451 * Set the options to be passed down to logcat 452 */ setLogcatOptions(String logcatOptions)453 public void setLogcatOptions(String logcatOptions) { 454 mLogcatOptions = logcatOptions; 455 } 456 457 /** 458 * @return if device reboot should be disabled 459 */ shouldDisableReboot()460 public boolean shouldDisableReboot() { 461 return mDisableReboot; 462 } 463 464 /** 465 * @return if the exponential retry strategy should be used. 466 */ isWifiExpoRetryEnabled()467 public boolean isWifiExpoRetryEnabled() { 468 return mWifiExpoRetryEnabled; 469 } 470 471 /** @return the wifiutil apk path */ getWifiUtilAPKPath()472 public String getWifiUtilAPKPath() { 473 return mWifiUtilAPKPath; 474 } 475 476 /** Returns the instance type of virtual device that should be created */ getInstanceType()477 public InstanceType getInstanceType() { 478 return mInstanceType; 479 } 480 481 /** Returns whether or not the Tradefed content provider can be used to push/pull files. */ shouldUseContentProvider()482 public boolean shouldUseContentProvider() { 483 return mUseContentProvider; 484 } 485 486 // =========================== Getter and Setter for Virtual Devices 487 /** Return the Gce Avd timeout for the instance to come online. */ getGceCmdTimeout()488 public long getGceCmdTimeout() { 489 return mGceCmdTimeout; 490 } 491 492 /** Set the Gce Avd timeout for the instance to come online. */ setGceCmdTimeout(long gceCmdTimeout)493 public void setGceCmdTimeout(long gceCmdTimeout) { 494 mGceCmdTimeout = gceCmdTimeout; 495 } 496 497 /** Return the path to the binary to start the Gce Avd instance. */ getAvdDriverBinary()498 public File getAvdDriverBinary() { 499 return mAvdDriverBinary; 500 } 501 502 /** Set the path to the binary to start the Gce Avd instance. */ setAvdDriverBinary(File avdDriverBinary)503 public void setAvdDriverBinary(File avdDriverBinary) { 504 mAvdDriverBinary = avdDriverBinary; 505 } 506 507 /** Return the Gce Avd config file to start the instance. */ getAvdConfigFile()508 public File getAvdConfigFile() { 509 return mAvdConfigFile; 510 } 511 512 /** Set the Gce Avd config file to start the instance. */ setAvdConfigFile(File avdConfigFile)513 public void setAvdConfigFile(File avdConfigFile) { 514 mAvdConfigFile = avdConfigFile; 515 } 516 517 /** Return the Gce Avd config test resource name to start the instance. */ getAvdConfigTestResourceName()518 public String getAvdConfigTestResourceName() { 519 return mAvdConfigTestResourceName; 520 } 521 522 /** @return the service account json key file. */ getSerivceAccountJsonKeyFile()523 public File getSerivceAccountJsonKeyFile() { 524 return mJsonKeyFile; 525 } 526 527 /** 528 * Set the service account json key file. 529 * 530 * @param jsonKeyFile the key file. 531 */ setServiceAccountJsonKeyFile(File jsonKeyFile)532 public void setServiceAccountJsonKeyFile(File jsonKeyFile) { 533 mJsonKeyFile = jsonKeyFile; 534 } 535 536 /** Return the path of the ssh key to use for operations with the Gce Avd instance. */ getSshPrivateKeyPath()537 public File getSshPrivateKeyPath() { 538 return mSshPrivateKeyPath; 539 } 540 541 /** Set the path of the ssh key to use for operations with the Gce Avd instance. */ setSshPrivateKeyPath(File sshPrivateKeyPath)542 public void setSshPrivateKeyPath(File sshPrivateKeyPath) { 543 mSshPrivateKeyPath = sshPrivateKeyPath; 544 } 545 546 /** Return the log level of the Gce Avd driver. */ getGceDriverLogLevel()547 public LogLevel getGceDriverLogLevel() { 548 return mGceDriverLogLevel; 549 } 550 551 /** Set the log level of the Gce Avd driver. */ setGceDriverLogLevel(LogLevel mGceDriverLogLevel)552 public void setGceDriverLogLevel(LogLevel mGceDriverLogLevel) { 553 this.mGceDriverLogLevel = mGceDriverLogLevel; 554 } 555 556 /** Return the additional GCE driver parameters provided via option */ getGceDriverParams()557 public List<String> getGceDriverParams() { 558 return mGceDriverParams; 559 } 560 561 /** Set the GCE driver parameter that should be paired with the build id from build info */ setGceDriverBuildIdParam(String gceDriverBuildIdParam)562 public void setGceDriverBuildIdParam(String gceDriverBuildIdParam) { 563 mGceDriverBuildIdParam = gceDriverBuildIdParam; 564 } 565 566 /** Return the GCE driver parameter that should be paired with the build id from build info */ getGceDriverBuildIdParam()567 public String getGceDriverBuildIdParam() { 568 return mGceDriverBuildIdParam; 569 } 570 571 /** Return the gce email account to use with the driver */ getGceAccount()572 public String getGceAccount() { 573 return mGceAccount; 574 } 575 576 /** Return the max number of attempts to start a gce device */ getGceMaxAttempt()577 public int getGceMaxAttempt() { 578 if (mGceMaxAttempt < 1) { 579 throw new RuntimeException("--max-gce-attempt cannot be bellow 1 attempt."); 580 } 581 return mGceMaxAttempt; 582 } 583 584 /** Set the max number of attempts to start a gce device */ setGceMaxAttempt(int gceMaxAttempt)585 public void setGceMaxAttempt(int gceMaxAttempt) { 586 mGceMaxAttempt = gceMaxAttempt; 587 } 588 589 /** Returns true if GCE tear down should be skipped. False otherwise. */ shouldSkipTearDown()590 public boolean shouldSkipTearDown() { 591 return mSkipTearDown; 592 } 593 594 /** Returns true if we should block on GCE tear down completion before proceeding. */ waitForGceTearDown()595 public boolean waitForGceTearDown() { 596 return mWaitForGceTearDown; 597 } 598 599 /** Returns the instance type of GCE virtual device that should be created */ getInstanceUser()600 public String getInstanceUser() { 601 return mInstanceUser; 602 } 603 604 /** Returns the remote port in instance that the adb server listens to */ getRemoteAdbPort()605 public int getRemoteAdbPort() { 606 return mRemoteAdbPort; 607 } 608 609 /** Returns the base image name to be used for the current instance */ getBaseImage()610 public String getBaseImage() { 611 return mBaseImage; 612 } 613 614 /** Returns the list of pattern to attempt to fetch via scp. */ getRemoteFetchFilePattern()615 public Set<String> getRemoteFetchFilePattern() { 616 return mRemoteFetchFilePattern; 617 } 618 getCreateCommandByInstanceType(InstanceType type)619 public static String getCreateCommandByInstanceType(InstanceType type) { 620 switch (type) { 621 case CHEEPS: 622 case GCE: 623 case REMOTE_AVD: 624 return "create"; 625 case CUTTLEFISH: 626 case REMOTE_NESTED_AVD: 627 return "create_cf"; 628 case EMULATOR: 629 return "create_gf"; 630 } 631 throw new RuntimeException("Unexpected InstanceType: " + type); 632 } 633 getExtraParamsByInstanceType(InstanceType type, String baseImage)634 public static List<String> getExtraParamsByInstanceType(InstanceType type, String baseImage) { 635 if (InstanceType.EMULATOR.equals(type)) { 636 // TODO(b/119440413) remove when base image can be passed via extra gce driver params 637 List<String> params = ArrayUtil.list(); 638 if (baseImage != null) { 639 params.add("--base_image"); 640 params.add(baseImage); 641 } 642 return params; 643 } 644 return Collections.emptyList(); 645 } 646 } 647