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 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 elapsed = 0 | 523 elapsed = 0 |
524 wait_period = 0.1 | 524 wait_period = 0.1 |
525 # Note that this doesn't take into account the time spent in ExtractPid(). | 525 # Note that this doesn't take into account the time spent in ExtractPid(). |
526 while self.ExtractPid(process) and elapsed < timeout_sec: | 526 while self.ExtractPid(process) and elapsed < timeout_sec: |
527 time.sleep(wait_period) | 527 time.sleep(wait_period) |
528 elapsed += wait_period | 528 elapsed += wait_period |
529 if elapsed >= timeout_sec: | 529 if elapsed >= timeout_sec: |
530 return 0 | 530 return 0 |
531 return processes_killed | 531 return processes_killed |
532 | 532 |
533 def StartActivity(self, package, activity, wait_for_completion=False, | 533 def _GetActivityCommand(self, package, activity, wait_for_completion, action, |
534 action='android.intent.action.VIEW', | 534 category, data, extras, trace_file_name, force_stop): |
535 category=None, data=None, | 535 """Creates command to start |package|'s activity on the device. |
536 extras=None, trace_file_name=None, | |
537 force_stop=False): | |
538 """Starts |package|'s activity on the device. | |
539 | 536 |
540 Args: | 537 Args - as for StartActivity |
541 package: Name of package to start (e.g. 'com.google.android.apps.chrome'). | 538 |
542 activity: Name of activity (e.g. '.Main' or | 539 Returns: |
543 'com.google.android.apps.chrome.Main'). | 540 the command to run on the target to start the activity |
544 wait_for_completion: wait for the activity to finish launching (-W flag). | |
545 action: string (e.g. "android.intent.action.MAIN"). Default is VIEW. | |
546 category: string (e.g. "android.intent.category.HOME") | |
547 data: Data string to pass to activity (e.g. 'http://www.example.com/'). | |
548 extras: Dict of extras to pass to activity. Values are significant. | |
549 trace_file_name: If used, turns on and saves the trace to this file name. | |
550 force_stop: force stop the target app before starting the activity (-S | |
551 flag). | |
552 """ | 541 """ |
553 cmd = 'am start -a %s' % action | 542 cmd = 'am start -a %s' % action |
554 if force_stop: | 543 if force_stop: |
555 cmd += ' -S' | 544 cmd += ' -S' |
556 if wait_for_completion: | 545 if wait_for_completion: |
557 cmd += ' -W' | 546 cmd += ' -W' |
558 if category: | 547 if category: |
559 cmd += ' -c %s' % category | 548 cmd += ' -c %s' % category |
560 if package and activity: | 549 if package and activity: |
561 cmd += ' -n %s/%s' % (package, activity) | 550 cmd += ' -n %s/%s' % (package, activity) |
562 if data: | 551 if data: |
563 cmd += ' -d "%s"' % data | 552 cmd += ' -d "%s"' % data |
564 if extras: | 553 if extras: |
565 for key in extras: | 554 for key in extras: |
566 value = extras[key] | 555 value = extras[key] |
567 if isinstance(value, str): | 556 if isinstance(value, str): |
568 cmd += ' --es' | 557 cmd += ' --es' |
569 elif isinstance(value, bool): | 558 elif isinstance(value, bool): |
570 cmd += ' --ez' | 559 cmd += ' --ez' |
571 elif isinstance(value, int): | 560 elif isinstance(value, int): |
572 cmd += ' --ei' | 561 cmd += ' --ei' |
573 else: | 562 else: |
574 raise NotImplementedError( | 563 raise NotImplementedError( |
575 'Need to teach StartActivity how to pass %s extras' % type(value)) | 564 'Need to teach StartActivity how to pass %s extras' % type(value)) |
576 cmd += ' %s %s' % (key, value) | 565 cmd += ' %s %s' % (key, value) |
577 if trace_file_name: | 566 if trace_file_name: |
578 cmd += ' --start-profiler ' + trace_file_name | 567 cmd += ' --start-profiler ' + trace_file_name |
| 568 return cmd |
| 569 |
| 570 def StartActivity(self, package, activity, wait_for_completion=False, |
| 571 action='android.intent.action.VIEW', |
| 572 category=None, data=None, |
| 573 extras=None, trace_file_name=None, |
| 574 force_stop=False): |
| 575 """Starts |package|'s activity on the device. |
| 576 |
| 577 Args: |
| 578 package: Name of package to start (e.g. 'com.google.android.apps.chrome'). |
| 579 activity: Name of activity (e.g. '.Main' or |
| 580 'com.google.android.apps.chrome.Main'). |
| 581 wait_for_completion: wait for the activity to finish launching (-W flag). |
| 582 action: string (e.g. "android.intent.action.MAIN"). Default is VIEW. |
| 583 category: string (e.g. "android.intent.category.HOME") |
| 584 data: Data string to pass to activity (e.g. 'http://www.example.com/'). |
| 585 extras: Dict of extras to pass to activity. Values are significant. |
| 586 trace_file_name: If used, turns on and saves the trace to this file name. |
| 587 force_stop: force stop the target app before starting the activity (-S |
| 588 flag). |
| 589 """ |
| 590 cmd = self._GetActivityCommand(package, activity, wait_for_completion, |
| 591 action, category, data, extras, |
| 592 trace_file_name, force_stop) |
579 self.RunShellCommand(cmd) | 593 self.RunShellCommand(cmd) |
580 | 594 |
| 595 def StartActivityTimed(self, package, activity, wait_for_completion=False, |
| 596 action='android.intent.action.VIEW', |
| 597 category=None, data=None, |
| 598 extras=None, trace_file_name=None, |
| 599 force_stop=False): |
| 600 """Starts |package|'s activity on the device, returning the start time |
| 601 |
| 602 Args - as for StartActivity |
| 603 |
| 604 Returns: |
| 605 a timestamp string for the time at which the activity started |
| 606 """ |
| 607 cmd = self._GetActivityCommand(package, activity, wait_for_completion, |
| 608 action, category, data, extras, |
| 609 trace_file_name, force_stop) |
| 610 self.StartMonitoringLogcat() |
| 611 self.RunShellCommand('log starting activity; ' + cmd) |
| 612 activity_started_re = re.compile('.*starting activity.*') |
| 613 m = self.WaitForLogMatch(activity_started_re, None) |
| 614 assert m |
| 615 start_line = m.group(0) |
| 616 return GetLogTimestamp(start_line, self.GetDeviceYear()) |
| 617 |
581 def GoHome(self): | 618 def GoHome(self): |
582 """Tell the device to return to the home screen. Blocks until completion.""" | 619 """Tell the device to return to the home screen. Blocks until completion.""" |
583 self.RunShellCommand('am start -W ' | 620 self.RunShellCommand('am start -W ' |
584 '-a android.intent.action.MAIN -c android.intent.category.HOME') | 621 '-a android.intent.action.MAIN -c android.intent.category.HOME') |
585 | 622 |
586 def CloseApplication(self, package): | 623 def CloseApplication(self, package): |
587 """Attempt to close down the application, using increasing violence. | 624 """Attempt to close down the application, using increasing violence. |
588 | 625 |
589 Args: | 626 Args: |
590 package: Name of the process to kill off, e.g. | 627 package: Name of the process to kill off, e.g. |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 if error_match: | 888 if error_match: |
852 return None | 889 return None |
853 success_match = success_re.search(line) | 890 success_match = success_re.search(line) |
854 if success_match: | 891 if success_match: |
855 return success_match | 892 return success_match |
856 logging.info('<<< Skipped Logcat Line:' + str(line)) | 893 logging.info('<<< Skipped Logcat Line:' + str(line)) |
857 except pexpect.TIMEOUT: | 894 except pexpect.TIMEOUT: |
858 raise pexpect.TIMEOUT( | 895 raise pexpect.TIMEOUT( |
859 'Timeout (%ds) exceeded waiting for pattern "%s" (tip: use -vv ' | 896 'Timeout (%ds) exceeded waiting for pattern "%s" (tip: use -vv ' |
860 'to debug)' % | 897 'to debug)' % |
861 (self._logcat.timeout, success_re.pattern)) | 898 (timeout, success_re.pattern)) |
862 except pexpect.EOF: | 899 except pexpect.EOF: |
863 # It seems that sometimes logcat can end unexpectedly. This seems | 900 # It seems that sometimes logcat can end unexpectedly. This seems |
864 # to happen during Chrome startup after a reboot followed by a cache | 901 # to happen during Chrome startup after a reboot followed by a cache |
865 # clean. I don't understand why this happens, but this code deals with | 902 # clean. I don't understand why this happens, but this code deals with |
866 # getting EOF in logcat. | 903 # getting EOF in logcat. |
867 logging.critical('Found EOF in adb logcat. Restarting...') | 904 logging.critical('Found EOF in adb logcat. Restarting...') |
868 # Rerun spawn with original arguments. Note that self._logcat.args[0] is | 905 # Rerun spawn with original arguments. Note that self._logcat.args[0] is |
869 # the path of adb, so we don't want it in the arguments. | 906 # the path of adb, so we don't want it in the arguments. |
870 self._logcat = pexpect.spawn('adb', | 907 self._logcat = pexpect.spawn('adb', |
871 self._logcat.args[1:], | 908 self._logcat.args[1:], |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1148 """ | 1185 """ |
1149 def __init__(self, output): | 1186 def __init__(self, output): |
1150 self._output = output | 1187 self._output = output |
1151 | 1188 |
1152 def write(self, data): | 1189 def write(self, data): |
1153 data = data.replace('\r\r\n', '\n') | 1190 data = data.replace('\r\r\n', '\n') |
1154 self._output.write(data) | 1191 self._output.write(data) |
1155 | 1192 |
1156 def flush(self): | 1193 def flush(self): |
1157 self._output.flush() | 1194 self._output.flush() |
OLD | NEW |