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 |