| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Provides an interface to communicate with the device via the adb command. | 5 """Provides an interface to communicate with the device via the adb command. |
| 6 | 6 |
| 7 Assumes adb binary is currently on system path. | 7 Assumes adb binary is currently on system path. |
| 8 """ | 8 """ |
| 9 | 9 |
| 10 import collections | 10 import collections |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 | 34 |
| 35 # Pattern to search for the next whole line of pexpect output and capture it | 35 # Pattern to search for the next whole line of pexpect output and capture it |
| 36 # into a match group. We can't use ^ and $ for line start end with pexpect, | 36 # into a match group. We can't use ^ and $ for line start end with pexpect, |
| 37 # see http://www.noah.org/python/pexpect/#doc for explanation why. | 37 # see http://www.noah.org/python/pexpect/#doc for explanation why. |
| 38 PEXPECT_LINE_RE = re.compile('\n([^\r]*)\r') | 38 PEXPECT_LINE_RE = re.compile('\n([^\r]*)\r') |
| 39 | 39 |
| 40 # Set the adb shell prompt to be a unique marker that will [hopefully] not | 40 # Set the adb shell prompt to be a unique marker that will [hopefully] not |
| 41 # appear at the start of any line of a command's output. | 41 # appear at the start of any line of a command's output. |
| 42 SHELL_PROMPT = '~+~PQ\x17RS~+~' | 42 SHELL_PROMPT = '~+~PQ\x17RS~+~' |
| 43 | 43 |
| 44 # This only works for single core devices. | |
| 45 SCALING_GOVERNOR = '/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor' | |
| 46 DROP_CACHES = '/proc/sys/vm/drop_caches' | |
| 47 | |
| 48 # Java properties file | 44 # Java properties file |
| 49 LOCAL_PROPERTIES_PATH = '/data/local.prop' | 45 LOCAL_PROPERTIES_PATH = '/data/local.prop' |
| 50 | 46 |
| 51 # Property in /data/local.prop that controls Java assertions. | 47 # Property in /data/local.prop that controls Java assertions. |
| 52 JAVA_ASSERT_PROPERTY = 'dalvik.vm.enableassertions' | 48 JAVA_ASSERT_PROPERTY = 'dalvik.vm.enableassertions' |
| 53 | 49 |
| 54 BOOT_COMPLETE_RE = re.compile( | 50 BOOT_COMPLETE_RE = re.compile( |
| 55 'android.intent.action.MEDIA_MOUNTED path: /\w+/sdcard\d?' | 51 'android.intent.action.MEDIA_MOUNTED path: /\w+/sdcard\d?' |
| 56 '|PowerManagerService(\(\s+\d+\))?: bootCompleted') | 52 '|PowerManagerService(\(\s+\d+\))?: bootCompleted') |
| 57 | 53 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 Args: | 195 Args: |
| 200 device: If given, adb commands are only send to the device of this ID. | 196 device: If given, adb commands are only send to the device of this ID. |
| 201 Otherwise commands are sent to all attached devices. | 197 Otherwise commands are sent to all attached devices. |
| 202 """ | 198 """ |
| 203 | 199 |
| 204 def __init__(self, device=None): | 200 def __init__(self, device=None): |
| 205 self._adb = adb_interface.AdbInterface() | 201 self._adb = adb_interface.AdbInterface() |
| 206 if device: | 202 if device: |
| 207 self._adb.SetTargetSerial(device) | 203 self._adb.SetTargetSerial(device) |
| 208 self._logcat = None | 204 self._logcat = None |
| 209 self._original_governor = None | |
| 210 self._pushed_files = [] | 205 self._pushed_files = [] |
| 211 self._device_utc_offset = self.RunShellCommand('date +%z')[0] | 206 self._device_utc_offset = self.RunShellCommand('date +%z')[0] |
| 212 self._md5sum_path = '' | 207 self._md5sum_path = '' |
| 208 self._external_storage = '' |
| 213 | 209 |
| 214 def Adb(self): | 210 def Adb(self): |
| 215 """Returns our AdbInterface to avoid us wrapping all its methods.""" | 211 """Returns our AdbInterface to avoid us wrapping all its methods.""" |
| 216 return self._adb | 212 return self._adb |
| 217 | 213 |
| 218 def IsRootEnabled(self): | 214 def IsRootEnabled(self): |
| 219 """Checks if root is enabled on the device.""" | 215 """Checks if root is enabled on the device.""" |
| 220 root_test_output = self.RunShellCommand('ls /root') or [''] | 216 root_test_output = self.RunShellCommand('ls /root') or [''] |
| 221 return not 'Permission denied' in root_test_output[0] | 217 return not 'Permission denied' in root_test_output[0] |
| 222 | 218 |
| 223 def GetDeviceYear(self): | 219 def GetDeviceYear(self): |
| 224 """Returns the year information of the date on device.""" | 220 """Returns the year information of the date on device.""" |
| 225 return self.RunShellCommand('date +%Y')[0] | 221 return self.RunShellCommand('date +%Y')[0] |
| 226 | 222 |
| 223 def GetExternalStorage(self): |
| 224 if not self._external_storage: |
| 225 self._external_storage = self.RunShellCommand('echo $EXTERNAL_STORAGE')[0] |
| 226 assert self._external_storage, 'Unable to find $EXTERNAL_STORAGE' |
| 227 return self._external_storage |
| 228 |
| 227 def WaitForDevicePm(self): | 229 def WaitForDevicePm(self): |
| 228 """Blocks until the device's package manager is available. | 230 """Blocks until the device's package manager is available. |
| 229 | 231 |
| 230 To workaround http://b/5201039, we restart the shell and retry if the | 232 To workaround http://b/5201039, we restart the shell and retry if the |
| 231 package manager isn't back after 120 seconds. | 233 package manager isn't back after 120 seconds. |
| 232 | 234 |
| 233 Raises: | 235 Raises: |
| 234 errors.WaitForResponseTimedOutError after max retries reached. | 236 errors.WaitForResponseTimedOutError after max retries reached. |
| 235 """ | 237 """ |
| 236 last_err = None | 238 last_err = None |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 def Install(self, package_file_path, reinstall=False): | 291 def Install(self, package_file_path, reinstall=False): |
| 290 """Installs the specified package to the device. | 292 """Installs the specified package to the device. |
| 291 | 293 |
| 292 Args: | 294 Args: |
| 293 package_file_path: Path to .apk file to install. | 295 package_file_path: Path to .apk file to install. |
| 294 reinstall: Reinstall an existing apk, keeping the data. | 296 reinstall: Reinstall an existing apk, keeping the data. |
| 295 | 297 |
| 296 Returns: | 298 Returns: |
| 297 A status string returned by adb install | 299 A status string returned by adb install |
| 298 """ | 300 """ |
| 299 assert os.path.isfile(package_file_path) | 301 assert os.path.isfile(package_file_path), ('<%s> is not file' % |
| 302 package_file_path) |
| 300 | 303 |
| 301 install_cmd = ['install'] | 304 install_cmd = ['install'] |
| 302 | 305 |
| 303 if reinstall: | 306 if reinstall: |
| 304 install_cmd.append('-r') | 307 install_cmd.append('-r') |
| 305 | 308 |
| 306 install_cmd.append(package_file_path) | 309 install_cmd.append(package_file_path) |
| 307 install_cmd = ' '.join(install_cmd) | 310 install_cmd = ' '.join(install_cmd) |
| 308 | 311 |
| 309 logging.info('>>> $' + install_cmd) | 312 logging.info('>>> $' + install_cmd) |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 if not boot_completed: | 401 if not boot_completed: |
| 399 raise errors.WaitForResponseTimedOutError( | 402 raise errors.WaitForResponseTimedOutError( |
| 400 'sys.boot_completed flag was not set after %s seconds' % wait_time) | 403 'sys.boot_completed flag was not set after %s seconds' % wait_time) |
| 401 | 404 |
| 402 def WaitForSdCardReady(self, timeout_time): | 405 def WaitForSdCardReady(self, timeout_time): |
| 403 """Wait for the SD card ready before pushing data into it.""" | 406 """Wait for the SD card ready before pushing data into it.""" |
| 404 logging.info('Waiting for SD card ready...') | 407 logging.info('Waiting for SD card ready...') |
| 405 sdcard_ready = False | 408 sdcard_ready = False |
| 406 attempts = 0 | 409 attempts = 0 |
| 407 wait_period = 5 | 410 wait_period = 5 |
| 411 external_storage = self.GetExternalStorage() |
| 408 while not sdcard_ready and attempts * wait_period < timeout_time: | 412 while not sdcard_ready and attempts * wait_period < timeout_time: |
| 409 output = self.RunShellCommand('ls /sdcard/') | 413 output = self.RunShellCommand('ls ' + external_storage) |
| 410 if output: | 414 if output: |
| 411 sdcard_ready = True | 415 sdcard_ready = True |
| 412 else: | 416 else: |
| 413 time.sleep(wait_period) | 417 time.sleep(wait_period) |
| 414 attempts += 1 | 418 attempts += 1 |
| 415 if not sdcard_ready: | 419 if not sdcard_ready: |
| 416 raise errors.WaitForResponseTimedOutError( | 420 raise errors.WaitForResponseTimedOutError( |
| 417 'SD card not ready after %s seconds' % timeout_time) | 421 'SD card not ready after %s seconds' % timeout_time) |
| 418 | 422 |
| 419 # It is tempting to turn this function into a generator, however this is not | 423 # It is tempting to turn this function into a generator, however this is not |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 '(?P<user>[^\s]+)\s+' | 610 '(?P<user>[^\s]+)\s+' |
| 607 '(?P<group>[^\s]+)\s+' | 611 '(?P<group>[^\s]+)\s+' |
| 608 '(?P<size>[^\s]+)\s+' | 612 '(?P<size>[^\s]+)\s+' |
| 609 '(?P<date>[^\s]+)\s+' | 613 '(?P<date>[^\s]+)\s+' |
| 610 '(?P<time>[^\s]+)\s+' | 614 '(?P<time>[^\s]+)\s+' |
| 611 '(?P<filename>[^\s]+)$') | 615 '(?P<filename>[^\s]+)$') |
| 612 return _GetFilesFromRecursiveLsOutput( | 616 return _GetFilesFromRecursiveLsOutput( |
| 613 path, self.RunShellCommand('ls -lR %s' % path), re_file, | 617 path, self.RunShellCommand('ls -lR %s' % path), re_file, |
| 614 self._device_utc_offset) | 618 self._device_utc_offset) |
| 615 | 619 |
| 616 def SetupPerformanceTest(self): | |
| 617 """Sets up performance tests.""" | |
| 618 # Disable CPU scaling to reduce noise in tests | |
| 619 if not self._original_governor: | |
| 620 self._original_governor = self.GetFileContents( | |
| 621 SCALING_GOVERNOR, log_result=False) | |
| 622 self.RunShellCommand('echo performance > ' + SCALING_GOVERNOR) | |
| 623 self.DropRamCaches() | |
| 624 | |
| 625 def TearDownPerformanceTest(self): | |
| 626 """Tears down performance tests.""" | |
| 627 if self._original_governor: | |
| 628 self.RunShellCommand('echo %s > %s' % (self._original_governor[0], | |
| 629 SCALING_GOVERNOR)) | |
| 630 self._original_governor = None | |
| 631 | 620 |
| 632 def SetJavaAssertsEnabled(self, enable): | 621 def SetJavaAssertsEnabled(self, enable): |
| 633 """Sets or removes the device java assertions property. | 622 """Sets or removes the device java assertions property. |
| 634 | 623 |
| 635 Args: | 624 Args: |
| 636 enable: If True the property will be set. | 625 enable: If True the property will be set. |
| 637 | 626 |
| 638 Returns: | 627 Returns: |
| 639 True if the file was modified (reboot is required for it to take effect). | 628 True if the file was modified (reboot is required for it to take effect). |
| 640 """ | 629 """ |
| (...skipping 17 matching lines...) Expand all Loading... |
| 658 # Next, check the current runtime value is what we need, and | 647 # Next, check the current runtime value is what we need, and |
| 659 # if not, set it and report that a reboot is required. | 648 # if not, set it and report that a reboot is required. |
| 660 was_set = 'all' in self.RunShellCommand('getprop ' + JAVA_ASSERT_PROPERTY) | 649 was_set = 'all' in self.RunShellCommand('getprop ' + JAVA_ASSERT_PROPERTY) |
| 661 if was_set == enable: | 650 if was_set == enable: |
| 662 return False | 651 return False |
| 663 | 652 |
| 664 self.RunShellCommand('setprop %s "%s"' % (JAVA_ASSERT_PROPERTY, | 653 self.RunShellCommand('setprop %s "%s"' % (JAVA_ASSERT_PROPERTY, |
| 665 enable and 'all' or '')) | 654 enable and 'all' or '')) |
| 666 return True | 655 return True |
| 667 | 656 |
| 668 def DropRamCaches(self): | |
| 669 """Drops the filesystem ram caches for performance testing.""" | |
| 670 self.RunShellCommand('echo 3 > ' + DROP_CACHES) | |
| 671 | 657 |
| 672 def StartMonitoringLogcat(self, clear=True, timeout=10, logfile=None, | 658 def StartMonitoringLogcat(self, clear=True, timeout=10, logfile=None, |
| 673 filters=None): | 659 filters=None): |
| 674 """Starts monitoring the output of logcat, for use with WaitForLogMatch. | 660 """Starts monitoring the output of logcat, for use with WaitForLogMatch. |
| 675 | 661 |
| 676 Args: | 662 Args: |
| 677 clear: If True the existing logcat output will be cleared, to avoiding | 663 clear: If True the existing logcat output will be cleared, to avoiding |
| 678 matching historical output lurking in the log. | 664 matching historical output lurking in the log. |
| 679 timeout: How long WaitForLogMatch will wait for the given match | 665 timeout: How long WaitForLogMatch will wait for the given match |
| 680 filters: A list of logcat filters to be used. | 666 filters: A list of logcat filters to be used. |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1044 ' '.join(['-c %s' % c for c in category]), | 1030 ' '.join(['-c %s' % c for c in category]), |
| 1045 '--throttle %d' % throttle, | 1031 '--throttle %d' % throttle, |
| 1046 '-s %d' % seed, | 1032 '-s %d' % seed, |
| 1047 '-v ' * verbosity, | 1033 '-v ' * verbosity, |
| 1048 '--monitor-native-crashes', | 1034 '--monitor-native-crashes', |
| 1049 '--kill-process-after-error', | 1035 '--kill-process-after-error', |
| 1050 extra_args, | 1036 extra_args, |
| 1051 '%d' % event_count] | 1037 '%d' % event_count] |
| 1052 return self.RunShellCommand(' '.join(cmd), | 1038 return self.RunShellCommand(' '.join(cmd), |
| 1053 timeout_time=event_count*throttle*1.5) | 1039 timeout_time=event_count*throttle*1.5) |
| OLD | NEW |