1 /* 2 * Copyright (C) 2016 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.IDevice; 19 import com.android.ddmlib.IShellOutputReceiver; 20 import com.android.ddmlib.Log.LogLevel; 21 import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner; 22 import com.android.tradefed.build.IBuildInfo; 23 import com.android.tradefed.command.remote.DeviceDescriptor; 24 import com.android.tradefed.device.ITestDevice.MountPointInfo; 25 import com.android.tradefed.device.ITestDevice.RecoveryMode; 26 import com.android.tradefed.log.ITestLogger; 27 import com.android.tradefed.result.ITestLifeCycleReceiver; 28 import com.android.tradefed.result.InputStreamSource; 29 import com.android.tradefed.targetprep.TargetSetupError; 30 import com.android.tradefed.util.Bugreport; 31 import com.android.tradefed.util.CommandResult; 32 import com.android.tradefed.util.ProcessInfo; 33 import com.android.tradefed.util.TimeUtil; 34 35 import com.google.errorprone.annotations.MustBeClosed; 36 37 import java.io.File; 38 import java.io.InputStream; 39 import java.util.Collection; 40 import java.util.Date; 41 import java.util.List; 42 import java.util.concurrent.TimeUnit; 43 44 /** 45 * Provides an reliable and slightly higher level API to a ddmlib {@link IDevice}. 46 * <p/> 47 * Retries device commands for a configurable amount, and provides a device recovery 48 * interface for devices which are unresponsive. 49 */ 50 public interface INativeDevice { 51 52 /** 53 * Default value when API Level cannot be detected 54 */ 55 public final static int UNKNOWN_API_LEVEL = -1; 56 57 /** 58 * Set the {@link TestDeviceOptions} for the device 59 */ setOptions(TestDeviceOptions options)60 public void setOptions(TestDeviceOptions options); 61 62 /** 63 * Returns a reference to the associated ddmlib {@link IDevice}. 64 * <p/> 65 * A new {@link IDevice} may be allocated by DDMS each time the device disconnects and 66 * reconnects from adb. Thus callers should not keep a reference to the {@link IDevice}, 67 * because that reference may become stale. 68 * 69 * @return the {@link IDevice} 70 */ getIDevice()71 public IDevice getIDevice(); 72 73 /** 74 * Convenience method to get serial number of this device. 75 * 76 * @return the {@link String} serial number 77 */ getSerialNumber()78 public String getSerialNumber(); 79 80 /** 81 * Retrieve the given property value from the device. 82 * 83 * @param name the property name 84 * @return the property value or <code>null</code> if it does not exist 85 * @throws DeviceNotAvailableException 86 */ getProperty(String name)87 public String getProperty(String name) throws DeviceNotAvailableException; 88 89 /** 90 * Convenience method to get the bootloader version of this device. 91 * <p/> 92 * Will attempt to retrieve bootloader version from the device's current state. (ie if device 93 * is in fastboot mode, it will attempt to retrieve version from fastboot) 94 * 95 * @return the {@link String} bootloader version or <code>null</code> if it cannot be found 96 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 97 * recovered. 98 */ getBootloaderVersion()99 public String getBootloaderVersion() throws DeviceNotAvailableException; 100 101 /** 102 * Convenience method to get baseband (radio) version of this device. Getting the radio version 103 * is device specific, so it might not return the correct information for all devices. This 104 * method relies on the gsm.version.baseband propery to return the correct version information. 105 * This is not accurate for some CDMA devices and the version returned here might not match 106 * the version reported from fastboot and might not return the version for the CDMA radio. 107 * TL;DR this method only reports accurate version if the gsm.version.baseband property is the 108 * same as the version returned by <code>fastboot getvar version-baseband</code>. 109 * 110 * @return the {@link String} baseband version or <code>null</code> if it cannot be determined 111 * (device has no radio or version string cannot be read) 112 * @throws DeviceNotAvailableException if the connection with the device is lost and cannot 113 * be recovered. 114 */ getBasebandVersion()115 public String getBasebandVersion() throws DeviceNotAvailableException; 116 117 /** 118 * Convenience method to get the product type of this device. 119 * <p/> 120 * This method will work if device is in either adb or fastboot mode. 121 * 122 * @return the {@link String} product type name. Will not be null 123 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 124 * recovered, or if product type can not be determined 125 */ getProductType()126 public String getProductType() throws DeviceNotAvailableException; 127 128 /** 129 * Convenience method to get the product variant of this device. 130 * <p/> 131 * This method will work if device is in either adb or fastboot mode. 132 * 133 * @return the {@link String} product variant name or <code>null</code> if it cannot be 134 * determined 135 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 136 * recovered. 137 */ getProductVariant()138 public String getProductVariant() throws DeviceNotAvailableException; 139 140 /** 141 * Convenience method to get the product type of this device when its in fastboot mode. 142 * <p/> 143 * This method should only be used if device should be in fastboot. Its a bit safer variant 144 * than the generic {@link #getProductType()} method in this case, because ITestDevice 145 * will know to recover device into fastboot if device is in incorrect state or is 146 * unresponsive. 147 * 148 * @return the {@link String} product type name or <code>null</code> if it cannot be determined 149 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 150 * recovered. 151 */ getFastbootProductType()152 public String getFastbootProductType() throws DeviceNotAvailableException; 153 154 /** 155 * Convenience method to get the product type of this device when its in fastboot mode. 156 * <p/> 157 * This method should only be used if device should be in fastboot. Its a bit safer variant 158 * than the generic {@link #getProductType()} method in this case, because ITestDevice 159 * will know to recover device into fastboot if device is in incorrect state or is 160 * unresponsive. 161 * 162 * @return the {@link String} product type name or <code>null</code> if it cannot be determined 163 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 164 * recovered. 165 */ getFastbootProductVariant()166 public String getFastbootProductVariant() throws DeviceNotAvailableException; 167 168 /** 169 * Retrieve the alias of the build that the device is currently running. 170 * 171 * <p>Build alias is usually a more readable string than build id (typically a number for 172 * Nexus builds). For example, final Android 4.2 release has build alias JDQ39, and build id 173 * 573038 174 * @return the build alias or fall back to build id if it could not be retrieved 175 * @throws DeviceNotAvailableException 176 */ getBuildAlias()177 public String getBuildAlias() throws DeviceNotAvailableException; 178 179 /** 180 * Retrieve the build the device is currently running. 181 * 182 * @return the build id or {@link IBuildInfo#UNKNOWN_BUILD_ID} if it could not be retrieved 183 * @throws DeviceNotAvailableException 184 */ getBuildId()185 public String getBuildId() throws DeviceNotAvailableException; 186 187 /** 188 * Retrieve the build flavor for the device. 189 * 190 * @return the build flavor or null if it could not be retrieved 191 * @throws DeviceNotAvailableException 192 */ getBuildFlavor()193 public String getBuildFlavor() throws DeviceNotAvailableException; 194 195 /** 196 * Executes the given adb shell command, retrying multiple times if command fails. 197 * <p/> 198 * A simpler form of 199 * {@link #executeShellCommand(String, IShellOutputReceiver, long, TimeUnit, int)} with 200 * default values. 201 * 202 * @param command the adb shell command to run 203 * @param receiver the {@link IShellOutputReceiver} to direct shell output to. 204 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 205 * recovered. 206 */ executeShellCommand(String command, IShellOutputReceiver receiver)207 public void executeShellCommand(String command, IShellOutputReceiver receiver) 208 throws DeviceNotAvailableException; 209 210 /** 211 * Executes a adb shell command, with more parameters to control command behavior. 212 * 213 * @see #executeShellCommand(String, IShellOutputReceiver) 214 * @param command the adb shell command to run 215 * @param receiver the {@link IShellOutputReceiver} to direct shell output to. 216 * @param maxTimeToOutputShellResponse the maximum amount of time during which the command is 217 * allowed to not output any response; unit as specified in <code>timeUnit</code> 218 * @param timeUnit unit for <code>maxTimeToOutputShellResponse</code> 219 * @param retryAttempts the maximum number of times to retry command if it fails due to a 220 * exception. DeviceNotResponsiveException will be thrown if <var>retryAttempts</var> 221 * are performed without success. 222 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 223 * recovered. 224 * @see TimeUtil 225 */ executeShellCommand(String command, IShellOutputReceiver receiver, long maxTimeToOutputShellResponse, TimeUnit timeUnit, int retryAttempts)226 public void executeShellCommand(String command, IShellOutputReceiver receiver, 227 long maxTimeToOutputShellResponse, TimeUnit timeUnit, int retryAttempts) 228 throws DeviceNotAvailableException; 229 230 /** 231 * Executes a adb shell command, with more parameters to control command behavior. 232 * 233 * @see #executeShellCommand(String, IShellOutputReceiver) 234 * @param command the adb shell command to run 235 * @param receiver the {@link IShellOutputReceiver} to direct shell output to. 236 * @param maxTimeoutForCommand the maximum timeout for the command to complete; unit as 237 * specified in <code>timeUnit</code> 238 * @param maxTimeToOutputShellResponse the maximum amount of time during which the command is 239 * allowed to not output any response; unit as specified in <code>timeUnit</code> 240 * @param timeUnit unit for <code>maxTimeToOutputShellResponse</code> 241 * @param retryAttempts the maximum number of times to retry command if it fails due to a 242 * exception. DeviceNotResponsiveException will be thrown if <var>retryAttempts</var> are 243 * performed without success. 244 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 245 * recovered. 246 * @see TimeUtil 247 */ executeShellCommand( String command, IShellOutputReceiver receiver, long maxTimeoutForCommand, long maxTimeToOutputShellResponse, TimeUnit timeUnit, int retryAttempts)248 public void executeShellCommand( 249 String command, 250 IShellOutputReceiver receiver, 251 long maxTimeoutForCommand, 252 long maxTimeToOutputShellResponse, 253 TimeUnit timeUnit, 254 int retryAttempts) 255 throws DeviceNotAvailableException; 256 257 /** 258 * Helper method which executes a adb shell command and returns output as a {@link String}. 259 * 260 * @param command the adb shell command to run 261 * @return the shell output 262 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 263 * recovered. 264 */ executeShellCommand(String command)265 public String executeShellCommand(String command) throws DeviceNotAvailableException; 266 267 /** 268 * Helper method which executes a adb shell command and returns the results as a {@link 269 * CommandResult} properly populated with the command status output, stdout and stderr. 270 * 271 * @param command The command that should be run. 272 * @return The result in {@link CommandResult}. 273 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 274 * recovered. 275 */ executeShellV2Command(String command)276 public CommandResult executeShellV2Command(String command) throws DeviceNotAvailableException; 277 278 /** 279 * Executes a adb shell command, with more parameters to control command behavior. 280 * 281 * @see #executeShellV2Command(String) 282 * @param command the adb shell command to run 283 * @param maxTimeoutForCommand the maximum timeout for the command to complete; unit as 284 * specified in <code>timeUnit</code> 285 * @param timeUnit unit for <code>maxTimeToOutputShellResponse</code> 286 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 287 * recovered. 288 * @see TimeUtil 289 */ executeShellV2Command( String command, final long maxTimeoutForCommand, final TimeUnit timeUnit)290 public CommandResult executeShellV2Command( 291 String command, final long maxTimeoutForCommand, final TimeUnit timeUnit) 292 throws DeviceNotAvailableException; 293 294 /** 295 * Executes a adb shell command, with more parameters to control command behavior. 296 * 297 * @see #executeShellV2Command(String) 298 * @param command the adb shell command to run 299 * @param maxTimeoutForCommand the maximum timeout for the command to complete; unit as 300 * specified in <code>timeUnit</code> 301 * @param timeUnit unit for <code>maxTimeToOutputShellResponse</code> 302 * @param retryAttempts the maximum number of times to retry command if it fails due to a 303 * exception. DeviceNotResponsiveException will be thrown if <var>retryAttempts</var> are 304 * performed without success. 305 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 306 * recovered. 307 * @see TimeUtil 308 */ executeShellV2Command( String command, final long maxTimeoutForCommand, final TimeUnit timeUnit, int retryAttempts)309 public CommandResult executeShellV2Command( 310 String command, 311 final long maxTimeoutForCommand, 312 final TimeUnit timeUnit, 313 int retryAttempts) 314 throws DeviceNotAvailableException; 315 316 /** 317 * Helper method which executes a adb command as a system command. 318 * <p/> 319 * {@link #executeShellCommand(String)} should be used instead wherever possible, as that 320 * method provides better failure detection and performance. 321 * 322 * @param commandArgs the adb command and arguments to run 323 * @return the stdout from command. <code>null</code> if command failed to execute. 324 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 325 * recovered. 326 */ executeAdbCommand(String... commandArgs)327 public String executeAdbCommand(String... commandArgs) throws DeviceNotAvailableException; 328 329 /** 330 * Helper method which executes a fastboot command as a system command with a default timeout 331 * of 2 minutes. 332 * <p/> 333 * Expected to be used when device is already in fastboot mode. 334 * 335 * @param commandArgs the fastboot command and arguments to run 336 * @return the CommandResult containing output of command 337 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 338 * recovered. 339 */ executeFastbootCommand(String... commandArgs)340 public CommandResult executeFastbootCommand(String... commandArgs) 341 throws DeviceNotAvailableException; 342 343 /** 344 * Helper method which executes a fastboot command as a system command. 345 * <p/> 346 * Expected to be used when device is already in fastboot mode. 347 * 348 * @param timeout the time in milliseconds before the command expire 349 * @param commandArgs the fastboot command and arguments to run 350 * @return the CommandResult containing output of command 351 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 352 * recovered. 353 */ executeFastbootCommand(long timeout, String... commandArgs)354 public CommandResult executeFastbootCommand(long timeout, String... commandArgs) 355 throws DeviceNotAvailableException; 356 357 /** 358 * Helper method which executes a long running fastboot command as a system command. 359 * <p/> 360 * Identical to {@link #executeFastbootCommand(String...)} except uses a longer timeout. 361 * 362 * @param commandArgs the fastboot command and arguments to run 363 * @return the CommandResult containing output of command 364 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 365 * recovered. 366 */ executeLongFastbootCommand(String... commandArgs)367 public CommandResult executeLongFastbootCommand(String... commandArgs) 368 throws DeviceNotAvailableException; 369 370 /** 371 * Get whether to use fastboot erase or fastboot format to wipe a partition on the device. 372 * 373 * @return {@code true} if fastboot erase will be used or {@code false} if fastboot format will 374 * be used. 375 * @see #fastbootWipePartition(String) 376 */ getUseFastbootErase()377 public boolean getUseFastbootErase(); 378 379 /** 380 * Set whether to use fastboot erase or fastboot format to wipe a partition on the device. 381 * 382 * @param useFastbootErase {@code true} if fastboot erase should be used or {@code false} if 383 * fastboot format should be used. 384 * @see #fastbootWipePartition(String) 385 */ setUseFastbootErase(boolean useFastbootErase)386 public void setUseFastbootErase(boolean useFastbootErase); 387 388 /** 389 * Helper method which wipes a partition for the device. 390 * <p/> 391 * If {@link #getUseFastbootErase()} is {@code true}, then fastboot erase will be used to wipe 392 * the partition. The device must then create a filesystem the next time the device boots. 393 * Otherwise, fastboot format is used which will create a new filesystem on the device. 394 * <p/> 395 * Expected to be used when device is already in fastboot mode. 396 * 397 * @param partition the partition to wipe 398 * @return the CommandResult containing output of command 399 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 400 * recovered. 401 */ fastbootWipePartition(String partition)402 public CommandResult fastbootWipePartition(String partition) throws DeviceNotAvailableException; 403 404 /** 405 * Runs instrumentation tests, and provides device recovery. 406 * 407 * <p>If connection with device is lost before test run completes, and recovery succeeds, all 408 * listeners will be informed of testRunFailed and "false" will be returned. The test command 409 * will not be rerun. It is left to callers to retry if necessary. 410 * 411 * <p>If connection with device is lost before test run completes, and recovery fails, all 412 * listeners will be informed of testRunFailed and DeviceNotAvailableException will be thrown. 413 * 414 * @param runner the {@link IRemoteAndroidTestRunner} which runs the tests 415 * @param listeners the test result listeners 416 * @return <code>true</code> if test command completed. <code>false</code> if it failed to 417 * complete due to device communication exception, but recovery succeeded 418 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 419 * recovered. ie test command failed to complete and recovery failed. 420 */ runInstrumentationTests( IRemoteAndroidTestRunner runner, Collection<ITestLifeCycleReceiver> listeners)421 public boolean runInstrumentationTests( 422 IRemoteAndroidTestRunner runner, Collection<ITestLifeCycleReceiver> listeners) 423 throws DeviceNotAvailableException; 424 425 /** 426 * Convenience method for performing {@link #runInstrumentationTests(IRemoteAndroidTestRunner, 427 * Collection)} with one or more listeners passed as parameters. 428 * 429 * @param runner the {@link IRemoteAndroidTestRunner} which runs the tests 430 * @param listeners the test result listener(s) 431 * @return <code>true</code> if test command completed. <code>false</code> if it failed to 432 * complete, but recovery succeeded 433 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 434 * recovered. ie test command failed to complete and recovery failed. 435 */ runInstrumentationTests( IRemoteAndroidTestRunner runner, ITestLifeCycleReceiver... listeners)436 public boolean runInstrumentationTests( 437 IRemoteAndroidTestRunner runner, ITestLifeCycleReceiver... listeners) 438 throws DeviceNotAvailableException; 439 440 /** 441 * Same as {@link ITestDevice#runInstrumentationTests(IRemoteAndroidTestRunner, Collection)} but 442 * runs the test for the given user. 443 */ runInstrumentationTestsAsUser( IRemoteAndroidTestRunner runner, int userId, Collection<ITestLifeCycleReceiver> listeners)444 public boolean runInstrumentationTestsAsUser( 445 IRemoteAndroidTestRunner runner, 446 int userId, 447 Collection<ITestLifeCycleReceiver> listeners) 448 throws DeviceNotAvailableException; 449 450 /** 451 * Same as {@link ITestDevice#runInstrumentationTests(IRemoteAndroidTestRunner, 452 * ITestLifeCycleReceiver...)} but runs the test for a given user. 453 */ runInstrumentationTestsAsUser( IRemoteAndroidTestRunner runner, int userId, ITestLifeCycleReceiver... listeners)454 public boolean runInstrumentationTestsAsUser( 455 IRemoteAndroidTestRunner runner, int userId, ITestLifeCycleReceiver... listeners) 456 throws DeviceNotAvailableException; 457 458 /** 459 * Check whether platform on device supports runtime permission granting 460 * @return True if runtime permission are supported, false otherwise. 461 * @throws DeviceNotAvailableException 462 */ isRuntimePermissionSupported()463 public boolean isRuntimePermissionSupported() throws DeviceNotAvailableException; 464 465 /** 466 * Retrieves a file off device. 467 * 468 * @param remoteFilePath the absolute path to file on device. 469 * @param localFile the local file to store contents in. If non-empty, contents will be 470 * replaced. 471 * @return <code>true</code> if file was retrieved successfully. <code>false</code> otherwise. 472 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 473 * recovered. 474 */ pullFile(String remoteFilePath, File localFile)475 public boolean pullFile(String remoteFilePath, File localFile) 476 throws DeviceNotAvailableException; 477 478 /** 479 * Retrieves a file off device, stores it in a local temporary {@link File}, and returns that 480 * {@code File}. 481 * 482 * @param remoteFilePath the absolute path to file on device. 483 * @return A {@link File} containing the contents of the device file, or {@code null} if the 484 * copy failed for any reason (including problems with the host filesystem) 485 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 486 * recovered. 487 */ pullFile(String remoteFilePath)488 public File pullFile(String remoteFilePath) throws DeviceNotAvailableException; 489 490 /** 491 * Retrieves a file off device, and returns the contents. 492 * 493 * @param remoteFilePath the absolute path to file on device. 494 * @return A {@link String} containing the contents of the device file, or {@code null} if the 495 * copy failed for any reason (including problems with the host filesystem) 496 */ pullFileContents(String remoteFilePath)497 public String pullFileContents(String remoteFilePath) throws DeviceNotAvailableException; 498 499 /** 500 * A convenience method to retrieve a file from the device's external storage, stores it in a 501 * local temporary {@link File}, and return a reference to that {@code File}. 502 * 503 * @param remoteFilePath the path to file on device, relative to the device's external storage 504 * mountpoint 505 * @return A {@link File} containing the contents of the device file, or {@code null} if the 506 * copy failed for any reason (including problems with the host filesystem) 507 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 508 * recovered. 509 */ pullFileFromExternal(String remoteFilePath)510 public File pullFileFromExternal(String remoteFilePath) throws DeviceNotAvailableException; 511 512 /** 513 * Recursively pull directory contents from device. 514 * 515 * @param deviceFilePath the absolute file path of the remote source 516 * @param localDir the local directory to pull files into 517 * @return <code>true</code> if file was pulled successfully. <code>false</code> otherwise. 518 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 519 * recovered. 520 */ pullDir(String deviceFilePath, File localDir)521 public boolean pullDir(String deviceFilePath, File localDir) 522 throws DeviceNotAvailableException; 523 524 /** 525 * Push a file to device 526 * 527 * @param localFile the local file to push 528 * @param deviceFilePath the remote destination absolute file path 529 * @return <code>true</code> if file was pushed successfully. <code>false</code> otherwise. 530 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 531 * recovered. 532 */ pushFile(File localFile, String deviceFilePath)533 public boolean pushFile(File localFile, String deviceFilePath) 534 throws DeviceNotAvailableException; 535 536 /** 537 * Push file created from a string to device 538 * 539 * @param contents the contents of the file to push 540 * @param deviceFilePath the remote destination absolute file path 541 * @return <code>true</code> if string was pushed successfully. <code>false</code> otherwise. 542 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 543 * recovered. 544 */ pushString(String contents, String deviceFilePath)545 public boolean pushString(String contents, String deviceFilePath) 546 throws DeviceNotAvailableException; 547 548 /** 549 * Recursively push directory contents to device. 550 * 551 * @param localDir the local directory to push 552 * @param deviceFilePath the absolute file path of the remote destination 553 * @return <code>true</code> if file was pushed successfully. <code>false</code> otherwise. 554 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 555 * recovered. 556 */ pushDir(File localDir, String deviceFilePath)557 public boolean pushDir(File localDir, String deviceFilePath) 558 throws DeviceNotAvailableException; 559 560 /** 561 * Incrementally syncs the contents of a local file directory to device. 562 * <p/> 563 * Decides which files to push by comparing timestamps of local files with their remote 564 * equivalents. Only 'newer' or non-existent files will be pushed to device. Thus overhead 565 * should be relatively small if file set on device is already up to date. 566 * <p/> 567 * Hidden files (with names starting with ".") will be ignored. 568 * <p/> 569 * Example usage: syncFiles("/tmp/files", "/sdcard") will created a /sdcard/files directory if 570 * it doesn't already exist, and recursively push the /tmp/files contents to /sdcard/files. 571 * 572 * @param localFileDir the local file directory containing files to recursively push. 573 * @param deviceFilePath the remote destination absolute file path root. All directories in thos 574 * file path must be readable. ie pushing to /data/local/tmp when adb is not root 575 * will fail 576 * @return <code>true</code> if files were synced successfully. <code>false</code> otherwise. 577 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 578 * recovered. 579 */ syncFiles(File localFileDir, String deviceFilePath)580 public boolean syncFiles(File localFileDir, String deviceFilePath) 581 throws DeviceNotAvailableException; 582 583 /** 584 * Helper method to determine if file on device exists. 585 * 586 * @param deviceFilePath the absolute path of file on device to check 587 * @return <code>true</code> if file exists, <code>false</code> otherwise. 588 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 589 * recovered. 590 */ doesFileExist(String deviceFilePath)591 public boolean doesFileExist(String deviceFilePath) throws DeviceNotAvailableException; 592 593 /** 594 * Retrieve a reference to a remote file on device. 595 * 596 * @param path the file path to retrieve. Can be an absolute path or path relative to '/'. (ie 597 * both "/system" and "system" syntax is supported) 598 * @return the {@link IFileEntry} or <code>null</code> if file at given <var>path</var> cannot 599 * be found 600 * @throws DeviceNotAvailableException 601 */ getFileEntry(String path)602 public IFileEntry getFileEntry(String path) throws DeviceNotAvailableException; 603 604 /** 605 * Return True if the path on the device is a directory, false otherwise. 606 * 607 * @throws DeviceNotAvailableException 608 */ isDirectory(String deviceFilePath)609 public boolean isDirectory(String deviceFilePath) throws DeviceNotAvailableException; 610 611 /** 612 * Alternative to using {@link IFileEntry} that sometimes won't work because of permissions. 613 * 614 * @param deviceFilePath is the path on the device where to do the search 615 * @return Array of string containing all the file in a path on the device. 616 * @throws DeviceNotAvailableException 617 */ getChildren(String deviceFilePath)618 public String[] getChildren(String deviceFilePath) throws DeviceNotAvailableException; 619 620 /** 621 * Helper method to determine amount of free space on device external storage. 622 * 623 * @return the amount of free space in KB 624 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 625 * recovered. 626 */ getExternalStoreFreeSpace()627 public long getExternalStoreFreeSpace() throws DeviceNotAvailableException; 628 629 /** 630 * Helper method to determine amount of free space on device partition. 631 * 632 * @return the amount of free space in KB 633 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 634 * recovered. 635 */ getPartitionFreeSpace(String partition)636 public long getPartitionFreeSpace(String partition) throws DeviceNotAvailableException; 637 638 /** 639 * Returns a mount point. 640 * <p/> 641 * Queries the device directly if the cached info in {@link IDevice} is not available. 642 * <p/> 643 * TODO: move this behavior to {@link IDevice#getMountPoint(String)} 644 * 645 * @param mountName the name of the mount point 646 * @return the mount point or <code>null</code> 647 * @see IDevice#getMountPoint(String) 648 */ getMountPoint(String mountName)649 public String getMountPoint(String mountName); 650 651 /** 652 * Returns a parsed version of the information in /proc/mounts on the device 653 * 654 * @return A {@link List} of {@link MountPointInfo} containing the information in "/proc/mounts" 655 */ getMountPointInfo()656 public List<MountPointInfo> getMountPointInfo() throws DeviceNotAvailableException; 657 658 /** 659 * Returns a {@link MountPointInfo} corresponding to the specified mountpoint path, or 660 * <code>null</code> if that path has nothing mounted or otherwise does not appear in 661 * /proc/mounts as a mountpoint. 662 * 663 * @return A {@link List} of {@link MountPointInfo} containing the information in "/proc/mounts" 664 * @see #getMountPointInfo() 665 */ getMountPointInfo(String mountpoint)666 public MountPointInfo getMountPointInfo(String mountpoint) throws DeviceNotAvailableException; 667 668 /** 669 * Start capturing logcat output from device in the background. 670 * <p/> 671 * Will have no effect if logcat output is already being captured. 672 * Data can be later retrieved via getLogcat. 673 * <p/> 674 * When the device is no longer in use, {@link #stopLogcat()} must be called. 675 * <p/> 676 * {@link #startLogcat()} and {@link #stopLogcat()} do not normally need to be called when 677 * within a TF invocation context, as the TF framework will start and stop logcat. 678 */ startLogcat()679 public void startLogcat(); 680 681 /** 682 * Stop capturing logcat output from device, and discard currently saved logcat data. 683 * <p/> 684 * Will have no effect if logcat output is not being captured. 685 */ stopLogcat()686 public void stopLogcat(); 687 688 /** 689 * Deletes any accumulated logcat data. 690 * <p/> 691 * This is useful for cases when you want to ensure {@link ITestDevice#getLogcat()} only returns 692 * log data produced after a certain point (such as after flashing a new device build, etc). 693 */ clearLogcat()694 public void clearLogcat(); 695 696 /** 697 * Grabs a snapshot stream of the logcat data. 698 * 699 * <p>Works in two modes: 700 * <li>If the logcat is currently being captured in the background, will return up to {@link 701 * TestDeviceOptions#getMaxLogcatDataSize()} bytes of the current contents of the background 702 * logcat capture 703 * <li>Otherwise, will return a static dump of the logcat data if device is currently responding 704 */ 705 @MustBeClosed getLogcat()706 public InputStreamSource getLogcat(); 707 708 /** 709 * Grabs a snapshot stream of captured logcat data starting the date provided. The time on the 710 * device should be used {@link #getDeviceDate}. 711 * 712 * <p> 713 * 714 * @param date in millisecond since epoch format of when to start the snapshot until present. 715 * (can be be obtained using 'date +%s') 716 */ 717 @MustBeClosed getLogcatSince(long date)718 public InputStreamSource getLogcatSince(long date); 719 720 /** 721 * Grabs a snapshot stream of the last <code>maxBytes</code> of captured logcat data. 722 * 723 * <p>Useful for cases when you want to capture frequent snapshots of the captured logcat data 724 * without incurring the potentially big disk space penalty of getting the entire {@link 725 * #getLogcat()} snapshot. 726 * 727 * @param maxBytes the maximum amount of data to return. Should be an amount that can 728 * comfortably fit in memory 729 */ 730 @MustBeClosed getLogcat(int maxBytes)731 public InputStreamSource getLogcat(int maxBytes); 732 733 /** 734 * Get a dump of the current logcat for device. Unlike {@link #getLogcat()}, this method will 735 * always return a static dump of the logcat. 736 * 737 * <p>Has the disadvantage that nothing will be returned if device is not reachable. 738 * 739 * @return a {@link InputStreamSource} of the logcat data. An empty stream is returned if fail 740 * to capture logcat data. 741 */ 742 @MustBeClosed getLogcatDump()743 public InputStreamSource getLogcatDump(); 744 745 /** 746 * Perform instructions to configure device for testing that after every boot. 747 * <p/> 748 * Should be called after device is fully booted/available 749 * <p/> 750 * In normal circumstances this method doesn't need to be called explicitly, as 751 * implementations should perform these steps automatically when performing a reboot. 752 * <p/> 753 * Where it may need to be called is when device reboots due to other events (eg when a 754 * fastboot update command has completed) 755 * 756 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 757 * recovered. 758 */ postBootSetup()759 public void postBootSetup() throws DeviceNotAvailableException; 760 761 /** 762 * Reboots the device into bootloader mode. 763 * <p/> 764 * Blocks until device is in bootloader mode. 765 * 766 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 767 * recovered. 768 */ rebootIntoBootloader()769 public void rebootIntoBootloader() throws DeviceNotAvailableException; 770 771 /** 772 * Reboots the device into adb mode. 773 * <p/> 774 * Blocks until device becomes available. 775 * 776 * @throws DeviceNotAvailableException if device is not available after reboot 777 */ reboot()778 public void reboot() throws DeviceNotAvailableException; 779 780 /** 781 * Reboots the device into adb recovery mode. 782 * <p/> 783 * Blocks until device enters recovery 784 * 785 * @throws DeviceNotAvailableException if device is not available after reboot 786 */ rebootIntoRecovery()787 public void rebootIntoRecovery() throws DeviceNotAvailableException; 788 789 /** 790 * An alternate to {@link #reboot()} that only blocks until device is online ie visible to adb. 791 * 792 * @throws DeviceNotAvailableException if device is not available after reboot 793 */ rebootUntilOnline()794 public void rebootUntilOnline() throws DeviceNotAvailableException; 795 796 /** 797 * Issues a command to reboot device and returns on command complete and when device is no 798 * longer visible to adb. 799 * 800 * @throws DeviceNotAvailableException 801 */ nonBlockingReboot()802 public void nonBlockingReboot() throws DeviceNotAvailableException; 803 804 /** 805 * Turns on adb root. If the "enable-root" setting is "false", will log a message and 806 * return without enabling root. 807 * <p/> 808 * Enabling adb root may cause device to disconnect from adb. This method will block until 809 * device is available. 810 * 811 * @return <code>true</code> if successful. 812 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 813 * recovered. 814 */ enableAdbRoot()815 public boolean enableAdbRoot() throws DeviceNotAvailableException; 816 817 /** 818 * Turns off adb root. 819 * <p/> 820 * Disabling adb root may cause device to disconnect from adb. This method will block until 821 * device is available. 822 * 823 * @return <code>true</code> if successful. 824 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 825 * recovered. 826 */ disableAdbRoot()827 public boolean disableAdbRoot() throws DeviceNotAvailableException; 828 829 /** 830 * @return <code>true</code> if device currently has adb root, <code>false</code> otherwise. 831 * 832 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 833 * recovered. 834 */ isAdbRoot()835 public boolean isAdbRoot() throws DeviceNotAvailableException; 836 837 /** 838 * Encrypts the device. 839 * <p/> 840 * Encrypting the device may be done inplace or with a wipe. Inplace encryption will not wipe 841 * any data on the device but normally takes a couple orders of magnitude longer than the wipe. 842 * <p/> 843 * This method will reboot the device if it is not already encrypted and will block until device 844 * is online. Also, it will not decrypt the device after the reboot. Therefore, the device 845 * might not be fully booted and/or ready to be tested when this method returns. 846 * 847 * @param inplace if the encryption process should take inplace and the device should not be 848 * wiped. 849 * @return <code>true</code> if successful. 850 * @throws DeviceNotAvailableException if device is not available after reboot. 851 * @throws UnsupportedOperationException if encryption is not supported on the device. 852 */ encryptDevice(boolean inplace)853 public boolean encryptDevice(boolean inplace) throws DeviceNotAvailableException, 854 UnsupportedOperationException; 855 856 /** 857 * Unencrypts the device. 858 * <p/> 859 * Unencrypting the device may cause device to be wiped and may reboot device. This method will 860 * block until device is available and ready for testing. Requires fastboot inorder to wipe the 861 * userdata partition. 862 * 863 * @return <code>true</code> if successful. 864 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 865 * recovered. 866 * @throws UnsupportedOperationException if encryption is not supported on the device. 867 */ unencryptDevice()868 public boolean unencryptDevice() throws DeviceNotAvailableException, 869 UnsupportedOperationException; 870 871 /** 872 * Unlocks the device if the device is in an encrypted state. 873 * </p> 874 * This method may restart the framework but will not call {@link #postBootSetup()}. Therefore, 875 * the device might not be fully ready to be tested when this method returns. 876 * 877 * @return <code>true</code> if successful or if the device is unencrypted. 878 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 879 * recovered. 880 * @throws UnsupportedOperationException if encryption is not supported on the device. 881 */ unlockDevice()882 public boolean unlockDevice() throws DeviceNotAvailableException, 883 UnsupportedOperationException; 884 885 /** 886 * Returns if the device is encrypted. 887 * 888 * @return <code>true</code> if the device is encrypted. 889 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 890 * recovered. 891 */ isDeviceEncrypted()892 public boolean isDeviceEncrypted() throws DeviceNotAvailableException; 893 894 /** 895 * Returns if encryption is supported on the device. 896 * 897 * @return <code>true</code> if the device supports encryption. 898 * @throws DeviceNotAvailableException 899 */ isEncryptionSupported()900 public boolean isEncryptionSupported() throws DeviceNotAvailableException; 901 902 /** 903 * Waits for the device to be responsive and available for testing. 904 * 905 * @param waitTime the time in ms to wait 906 * @throws DeviceNotAvailableException if device is still unresponsive after waitTime expires. 907 */ waitForDeviceAvailable(final long waitTime)908 public void waitForDeviceAvailable(final long waitTime) throws DeviceNotAvailableException; 909 910 /** 911 * Waits for the device to be responsive and available for testing. Uses default timeout. 912 * 913 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 914 * recovered. 915 */ waitForDeviceAvailable()916 public void waitForDeviceAvailable() throws DeviceNotAvailableException; 917 918 /** 919 * Blocks until device is visible via adb. 920 * <p/> 921 * Note the device may not necessarily be responsive to commands on completion. Use 922 * {@link #waitForDeviceAvailable()} instead. 923 * 924 * @param waitTime the time in ms to wait 925 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 926 * recovered. 927 */ waitForDeviceOnline(final long waitTime)928 public void waitForDeviceOnline(final long waitTime) throws DeviceNotAvailableException; 929 930 /** 931 * Blocks until device is visible via adb. Uses default timeout 932 * <p/> 933 * Note the device may not necessarily be responsive to commands on completion. Use 934 * {@link #waitForDeviceAvailable()} instead. 935 * 936 * @throws DeviceNotAvailableException if connection with device is lost and cannot be 937 * recovered. 938 */ waitForDeviceOnline()939 public void waitForDeviceOnline() throws DeviceNotAvailableException; 940 941 /** 942 * Blocks for the device to be not available ie missing from adb 943 * 944 * @param waitTime the time in ms to wait 945 * @return <code>true</code> if device becomes not available before time expires. 946 * <code>false</code> otherwise 947 */ waitForDeviceNotAvailable(final long waitTime)948 public boolean waitForDeviceNotAvailable(final long waitTime); 949 950 /** 951 * Blocks for the device to be in the 'adb recovery' state (note this is distinct from 952 * {@link IDeviceRecovery}). 953 * 954 * @param waitTime the time in ms to wait 955 * @return <code>true</code> if device boots into recovery before time expires. 956 * <code>false</code> otherwise 957 */ waitForDeviceInRecovery(final long waitTime)958 public boolean waitForDeviceInRecovery(final long waitTime); 959 960 /** 961 * Waits for device to be responsive to a basic adb shell command. 962 * 963 * @param waitTime the time in ms to wait 964 * @return <code>true</code> if device becomes responsive before <var>waitTime</var> elapses. 965 */ waitForDeviceShell(final long waitTime)966 public boolean waitForDeviceShell(final long waitTime); 967 968 /** 969 * Blocks until the device's boot complete flag is set. 970 * 971 * @param timeOut time in msecs to wait for the flag to be set 972 * @return true if device's boot complete flag is set within the timeout 973 * @throws DeviceNotAvailableException 974 */ waitForBootComplete(long timeOut)975 public boolean waitForBootComplete(long timeOut) throws DeviceNotAvailableException; 976 977 /** 978 * Set the {@link IDeviceRecovery} to use for this device. Should be set when device is first 979 * allocated. 980 * 981 * @param recovery the {@link IDeviceRecovery} 982 */ setRecovery(IDeviceRecovery recovery)983 public void setRecovery(IDeviceRecovery recovery); 984 985 /** 986 * Set the current recovery mode to use for the device. 987 * <p/> 988 * Used to control what recovery method to use when a device communication problem is 989 * encountered. Its recommended to only use this method sparingly when needed (for example, 990 * when framework is down, etc 991 * 992 * @param mode whether 'recover till online only' mode should be on or not. 993 */ setRecoveryMode(RecoveryMode mode)994 public void setRecoveryMode(RecoveryMode mode); 995 996 /** 997 * Get the current recovery mode used for the device. 998 * 999 * @return the current recovery mode used for the device. 1000 */ getRecoveryMode()1001 public RecoveryMode getRecoveryMode(); 1002 1003 /** 1004 * Get the device's state. 1005 */ getDeviceState()1006 public TestDeviceState getDeviceState(); 1007 1008 /** 1009 * @return <code>true</code> if device is connected to adb-over-tcp, <code>false</code> 1010 * otherwise. 1011 */ isAdbTcp()1012 public boolean isAdbTcp(); 1013 1014 /** 1015 * Switch device to adb-over-tcp mode. 1016 * 1017 * @return the tcp serial number or <code>null</code> if device could not be switched 1018 * @throws DeviceNotAvailableException 1019 */ switchToAdbTcp()1020 public String switchToAdbTcp() throws DeviceNotAvailableException; 1021 1022 /** 1023 * Switch device to adb over usb mode. 1024 * 1025 * @return <code>true</code> if switch was successful, <code>false</code> otherwise. 1026 * @throws DeviceNotAvailableException 1027 */ switchToAdbUsb()1028 public boolean switchToAdbUsb() throws DeviceNotAvailableException; 1029 1030 /** 1031 * Get the stream of emulator stdout and stderr 1032 * @return emulator output 1033 */ getEmulatorOutput()1034 public InputStreamSource getEmulatorOutput(); 1035 1036 /** 1037 * Close and delete the emulator output. 1038 */ stopEmulatorOutput()1039 public void stopEmulatorOutput(); 1040 1041 /** 1042 * Get the device API Level. Defaults to {@link #UNKNOWN_API_LEVEL}. 1043 * 1044 * @return an integer indicating the API Level of device 1045 * @throws DeviceNotAvailableException 1046 */ getApiLevel()1047 public int getApiLevel() throws DeviceNotAvailableException; 1048 1049 /** 1050 * Helper to get the time difference between the device and a given {@link Date}. Use Epoch time 1051 * internally. 1052 * 1053 * @return the difference in milliseconds 1054 */ getDeviceTimeOffset(Date date)1055 public long getDeviceTimeOffset(Date date) throws DeviceNotAvailableException; 1056 1057 /** 1058 * Sets the date on device 1059 * <p> 1060 * Note: setting date on device requires root 1061 * @param date specify a particular date; will use host date if <code>null</code> 1062 * @throws DeviceNotAvailableException 1063 */ setDate(Date date)1064 public void setDate(Date date) throws DeviceNotAvailableException; 1065 1066 /** 1067 * Return the date of the device in millisecond since epoch. 1068 * 1069 * <p> 1070 * 1071 * @return the date of the device in epoch format. 1072 * @throws DeviceNotAvailableException 1073 */ getDeviceDate()1074 public long getDeviceDate() throws DeviceNotAvailableException; 1075 1076 /** 1077 * Make the system partition on the device writable. May reboot the device. 1078 * @throws DeviceNotAvailableException 1079 */ remountSystemWritable()1080 public void remountSystemWritable() throws DeviceNotAvailableException; 1081 1082 /** 1083 * Returns the key type used to sign the device image 1084 * <p> 1085 * Typically Android devices may be signed with test-keys (like in AOSP) or release-keys 1086 * (controlled by individual device manufacturers) 1087 * @return The signing key if found, null otherwise. 1088 * @throws DeviceNotAvailableException 1089 */ getBuildSigningKeys()1090 public String getBuildSigningKeys() throws DeviceNotAvailableException; 1091 1092 /** 1093 * Retrieves a bugreport from the device. 1094 * <p/> 1095 * The implementation of this is guaranteed to continue to work on a device without an sdcard 1096 * (or where the sdcard is not yet mounted). 1097 * 1098 * @return An {@link InputStreamSource} which will produce the bugreport contents on demand. In 1099 * case of failure, the {@code InputStreamSource} will produce an empty 1100 * {@link InputStream}. 1101 */ getBugreport()1102 public InputStreamSource getBugreport(); 1103 1104 /** 1105 * Retrieves a bugreportz from the device. Zip format bugreport contains the main bugreport 1106 * and other log files that are useful for debugging. 1107 * <p/> 1108 * Only supported for 'adb version' > 1.0.36 1109 * 1110 * @return a {@link InputStreamSource} of the zip file containing the bugreportz, return null 1111 * in case of failure. 1112 */ getBugreportz()1113 public InputStreamSource getBugreportz(); 1114 1115 /** 1116 * Helper method to take a bugreport and log it to the reporters. 1117 * 1118 * @param dataName name under which the bugreport will be reported. 1119 * @param listener an {@link ITestLogger} to log the bugreport. 1120 * @return True if the logging was successful, false otherwise. 1121 */ logBugreport(String dataName, ITestLogger listener)1122 public boolean logBugreport(String dataName, ITestLogger listener); 1123 1124 /** 1125 * Take a bugreport and returns it inside a {@link Bugreport} object to handle it. Return null 1126 * in case of issue. 1127 * </p> 1128 * File referenced in the Bugreport object need to be cleaned via {@link Bugreport#close()}. 1129 */ takeBugreport()1130 public Bugreport takeBugreport(); 1131 1132 /** 1133 * Get the device class. 1134 * 1135 * @return the {@link String} device class. 1136 */ getDeviceClass()1137 public String getDeviceClass(); 1138 1139 /** 1140 * Extra steps for device specific required setup that will be executed on the device prior 1141 * to the invocation flow. 1142 */ preInvocationSetup(IBuildInfo info)1143 public void preInvocationSetup(IBuildInfo info) 1144 throws TargetSetupError, DeviceNotAvailableException; 1145 1146 /** 1147 * Extra steps for device specific required clean up that will be executed after the invocation 1148 * is done. 1149 */ postInvocationTearDown()1150 public void postInvocationTearDown(); 1151 1152 /** 1153 * Return true if the device is headless (no screen), false otherwise. 1154 */ isHeadless()1155 public boolean isHeadless() throws DeviceNotAvailableException; 1156 1157 /** 1158 * Return a {@link DeviceDescriptor} from the device information to get info on it without 1159 * passing the actual device object. 1160 */ getDeviceDescriptor()1161 public DeviceDescriptor getDeviceDescriptor(); 1162 1163 /** 1164 * Helper method runs the "ps" command and returns list of USER, PID and NAME of all the 1165 * processes. 1166 * 1167 * @return List of ProcessInfo objects 1168 */ getProcesses()1169 public List<ProcessInfo> getProcesses() throws DeviceNotAvailableException; 1170 1171 /** 1172 * Helper method runs the "ps" command and returns USER, PID and NAME of the given process name. 1173 * 1174 * @return ProcessInfo of given processName 1175 */ getProcessByName(String processName)1176 public ProcessInfo getProcessByName(String processName) throws DeviceNotAvailableException; 1177 1178 /** Returns the pid of the service or null if something went wrong. */ getProcessPid(String process)1179 public String getProcessPid(String process) throws DeviceNotAvailableException; 1180 1181 /** 1182 * Log a message in the logcat of the device. This is a safe call that will not throw even if 1183 * the logging fails. 1184 * 1185 * @param tag The tag under which we log our message in the logcat. 1186 * @param level The debug level of the message in the logcat. 1187 * @param format The message format. 1188 * @param args the args to be replaced via String.format(). 1189 */ logOnDevice(String tag, LogLevel level, String format, Object... args)1190 public void logOnDevice(String tag, LogLevel level, String format, Object... args); 1191 } 1192