OLD | NEW |
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 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 a variety of device interactions based on adb. | 5 """Provides a variety of device interactions based on adb. |
6 | 6 |
7 Eventually, this will be based on adb_wrapper. | 7 Eventually, this will be based on adb_wrapper. |
8 """ | 8 """ |
9 # pylint: disable=W0613 | 9 # pylint: disable=W0613 |
10 | 10 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 Args: | 102 Args: |
103 timeout: timeout in seconds | 103 timeout: timeout in seconds |
104 retries: number of retries | 104 retries: number of retries |
105 | 105 |
106 Returns: | 106 Returns: |
107 True if the device is online, False otherwise. | 107 True if the device is online, False otherwise. |
108 | 108 |
109 Raises: | 109 Raises: |
110 CommandTimeoutError on timeout. | 110 CommandTimeoutError on timeout. |
111 """ | 111 """ |
112 return self.adb.GetState() == 'device' | 112 try: |
| 113 return self.adb.GetState() == 'device' |
| 114 except device_errors.BaseError as exc: |
| 115 logging.info('Failed to get state: %s', exc) |
| 116 return False |
113 | 117 |
114 @decorators.WithTimeoutAndRetriesFromInstance() | 118 @decorators.WithTimeoutAndRetriesFromInstance() |
115 def HasRoot(self, timeout=None, retries=None): | 119 def HasRoot(self, timeout=None, retries=None): |
116 """Checks whether or not adbd has root privileges. | 120 """Checks whether or not adbd has root privileges. |
117 | 121 |
118 Args: | 122 Args: |
119 timeout: timeout in seconds | 123 timeout: timeout in seconds |
120 retries: number of retries | 124 retries: number of retries |
121 | 125 |
122 Returns: | 126 Returns: |
123 True if adbd has root privileges, False otherwise. | 127 True if adbd has root privileges, False otherwise. |
124 | 128 |
125 Raises: | 129 Raises: |
126 CommandTimeoutError on timeout. | 130 CommandTimeoutError on timeout. |
127 DeviceUnreachableError on missing device. | 131 DeviceUnreachableError on missing device. |
128 """ | 132 """ |
129 return self._HasRootImpl() | |
130 | |
131 def _HasRootImpl(self): | |
132 try: | 133 try: |
133 self._RunShellCommandImpl('ls /root', check_return=True) | 134 self.RunShellCommand('ls /root', check_return=True) |
134 return True | 135 return True |
135 except device_errors.AdbShellCommandFailedError: | 136 except device_errors.AdbShellCommandFailedError: |
136 return False | 137 return False |
137 | 138 |
| 139 def NeedsSU(self, timeout=None, retries=None): |
| 140 """Checks whether 'su' is needed to access protected resources. |
| 141 |
| 142 Args: |
| 143 timeout: timeout in seconds |
| 144 retries: number of retries |
| 145 |
| 146 Returns: |
| 147 True if 'su' is available on the device and is needed to to access |
| 148 protected resources; False otherwise if either 'su' is not available |
| 149 (e.g. because the device has a user build), or not needed (because adbd |
| 150 already has root privileges). |
| 151 |
| 152 Raises: |
| 153 CommandTimeoutError on timeout. |
| 154 DeviceUnreachableError on missing device. |
| 155 """ |
| 156 if 'needs_su' not in self._cache: |
| 157 try: |
| 158 self.RunShellCommand('su -c ls /root && ! ls /root', check_return=True, |
| 159 timeout=timeout, retries=retries) |
| 160 self._cache['needs_su'] = True |
| 161 except device_errors.AdbShellCommandFailedError: |
| 162 self._cache['needs_su'] = False |
| 163 return self._cache['needs_su'] |
| 164 |
| 165 |
138 @decorators.WithTimeoutAndRetriesFromInstance() | 166 @decorators.WithTimeoutAndRetriesFromInstance() |
139 def EnableRoot(self, timeout=None, retries=None): | 167 def EnableRoot(self, timeout=None, retries=None): |
140 """Restarts adbd with root privileges. | 168 """Restarts adbd with root privileges. |
141 | 169 |
142 Args: | 170 Args: |
143 timeout: timeout in seconds | 171 timeout: timeout in seconds |
144 retries: number of retries | 172 retries: number of retries |
145 | 173 |
146 Raises: | 174 Raises: |
147 CommandFailedError if root could not be enabled. | 175 CommandFailedError if root could not be enabled. |
148 CommandTimeoutError on timeout. | 176 CommandTimeoutError on timeout. |
149 """ | 177 """ |
| 178 if 'needs_su' in self._cache: |
| 179 del self._cache['needs_su'] |
150 if not self.old_interface.EnableAdbRoot(): | 180 if not self.old_interface.EnableAdbRoot(): |
151 raise device_errors.CommandFailedError( | 181 raise device_errors.CommandFailedError( |
152 'Could not enable root.', device=str(self)) | 182 'Could not enable root.', device=str(self)) |
153 | 183 |
154 @decorators.WithTimeoutAndRetriesFromInstance() | 184 @decorators.WithTimeoutAndRetriesFromInstance() |
155 def IsUserBuild(self, timeout=None, retries=None): | 185 def IsUserBuild(self, timeout=None, retries=None): |
156 """Checks whether or not the device is running a user build. | 186 """Checks whether or not the device is running a user build. |
157 | 187 |
158 Args: | 188 Args: |
159 timeout: timeout in seconds | 189 timeout: timeout in seconds |
(...skipping 24 matching lines...) Expand all Loading... |
184 CommandFailedError if the external storage path could not be determined. | 214 CommandFailedError if the external storage path could not be determined. |
185 CommandTimeoutError on timeout. | 215 CommandTimeoutError on timeout. |
186 DeviceUnreachableError on missing device. | 216 DeviceUnreachableError on missing device. |
187 """ | 217 """ |
188 return self._GetExternalStoragePathImpl() | 218 return self._GetExternalStoragePathImpl() |
189 | 219 |
190 def _GetExternalStoragePathImpl(self): | 220 def _GetExternalStoragePathImpl(self): |
191 if 'external_storage' in self._cache: | 221 if 'external_storage' in self._cache: |
192 return self._cache['external_storage'] | 222 return self._cache['external_storage'] |
193 | 223 |
194 value = self._RunShellCommandImpl('echo $EXTERNAL_STORAGE', | 224 value = self.RunShellCommand('echo $EXTERNAL_STORAGE', |
195 single_line=True, | 225 single_line=True, |
196 check_return=True) | 226 check_return=True) |
197 if not value: | 227 if not value: |
198 raise device_errors.CommandFailedError('$EXTERNAL_STORAGE is not set', | 228 raise device_errors.CommandFailedError('$EXTERNAL_STORAGE is not set', |
199 str(self)) | 229 str(self)) |
200 self._cache['external_storage'] = value | 230 self._cache['external_storage'] = value |
201 return value | 231 return value |
202 | 232 |
203 @decorators.WithTimeoutAndRetriesFromInstance() | 233 @decorators.WithTimeoutAndRetriesFromInstance() |
204 def GetApplicationPath(self, package, timeout=None, retries=None): | 234 def GetApplicationPath(self, package, timeout=None, retries=None): |
205 """Get the path of the installed apk on the device for the given package. | 235 """Get the path of the installed apk on the device for the given package. |
206 | 236 |
(...skipping 24 matching lines...) Expand all Loading... |
231 wifi: A boolean indicating if we should wait for wifi to come up or not. | 261 wifi: A boolean indicating if we should wait for wifi to come up or not. |
232 timeout: timeout in seconds | 262 timeout: timeout in seconds |
233 retries: number of retries | 263 retries: number of retries |
234 | 264 |
235 Raises: | 265 Raises: |
236 CommandFailedError on failure. | 266 CommandFailedError on failure. |
237 CommandTimeoutError if one of the component waits times out. | 267 CommandTimeoutError if one of the component waits times out. |
238 DeviceUnreachableError if the device becomes unresponsive. | 268 DeviceUnreachableError if the device becomes unresponsive. |
239 """ | 269 """ |
240 def sd_card_ready(): | 270 def sd_card_ready(): |
241 return self.RunShellCommand(['ls', self.GetExternalStoragePath()], | 271 try: |
242 single_line=True, check_return=True) | 272 self.RunShellCommand(['test', '-d', self.GetExternalStoragePath()], |
| 273 check_return=True) |
| 274 return True |
| 275 except device_errors.AdbShellCommandFailedError: |
| 276 return False |
243 | 277 |
244 def pm_ready(): | 278 def pm_ready(): |
245 try: | 279 try: |
246 return self.GetApplicationPath('android') | 280 return self.GetApplicationPath('android') |
247 except device_errors.CommandFailedError: | 281 except device_errors.CommandFailedError: |
248 return False | 282 return False |
249 | 283 |
250 def boot_completed(): | 284 def boot_completed(): |
251 return self.GetProp('sys.boot_completed') == '1' | 285 return self.GetProp('sys.boot_completed') == '1' |
252 | 286 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 (with the optional newline at the end stripped). | 416 (with the optional newline at the end stripped). |
383 | 417 |
384 Raises: | 418 Raises: |
385 AdbShellCommandFailedError if check_return is True and the exit code of | 419 AdbShellCommandFailedError if check_return is True and the exit code of |
386 the command run on the device is non-zero. | 420 the command run on the device is non-zero. |
387 CommandFailedError if single_line is True but the output contains two or | 421 CommandFailedError if single_line is True but the output contains two or |
388 more lines. | 422 more lines. |
389 CommandTimeoutError on timeout. | 423 CommandTimeoutError on timeout. |
390 DeviceUnreachableError on missing device. | 424 DeviceUnreachableError on missing device. |
391 """ | 425 """ |
392 return self._RunShellCommandImpl(cmd, check_return=check_return, cwd=cwd, | |
393 env=env, as_root=as_root, single_line=single_line, timeout=timeout) | |
394 | |
395 def _RunShellCommandImpl(self, cmd, check_return=False, cwd=None, env=None, | |
396 as_root=False, single_line=False, timeout=None): | |
397 def env_quote(key, value): | 426 def env_quote(key, value): |
398 if not DeviceUtils._VALID_SHELL_VARIABLE.match(key): | 427 if not DeviceUtils._VALID_SHELL_VARIABLE.match(key): |
399 raise KeyError('Invalid shell variable name %r' % key) | 428 raise KeyError('Invalid shell variable name %r' % key) |
400 # using double quotes here to allow interpolation of shell variables | 429 # using double quotes here to allow interpolation of shell variables |
401 return '%s=%s' % (key, cmd_helper.DoubleQuote(value)) | 430 return '%s=%s' % (key, cmd_helper.DoubleQuote(value)) |
402 | 431 |
403 if not isinstance(cmd, basestring): | 432 if not isinstance(cmd, basestring): |
404 cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd) | 433 cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd) |
405 if as_root and not self._HasRootImpl(): | 434 if as_root and self.NeedsSU(): |
406 cmd = 'su -c %s' % cmd | 435 cmd = 'su -c %s' % cmd |
407 if env: | 436 if env: |
408 env = ' '.join(env_quote(k, v) for k, v in env.iteritems()) | 437 env = ' '.join(env_quote(k, v) for k, v in env.iteritems()) |
409 cmd = '%s %s' % (env, cmd) | 438 cmd = '%s %s' % (env, cmd) |
410 if cwd: | 439 if cwd: |
411 cmd = 'cd %s && %s' % (cmd_helper.SingleQuote(cwd), cmd) | 440 cmd = 'cd %s && %s' % (cmd_helper.SingleQuote(cwd), cmd) |
412 if timeout is None: | 441 if timeout is None: |
413 timeout = self._default_timeout | 442 timeout = self._default_timeout |
414 | 443 |
415 try: | 444 try: |
416 # TODO(perezju) still need to make sure that we call a version of | 445 output = self.adb.Shell(cmd, expect_rc=0) |
417 # adb.Shell without a timeout-and-retries wrapper. | |
418 output = self.adb.Shell(cmd, expect_rc=0, timeout=timeout, retries=0) | |
419 except device_errors.AdbShellCommandFailedError as e: | 446 except device_errors.AdbShellCommandFailedError as e: |
420 if check_return: | 447 if check_return: |
421 raise | 448 raise |
422 else: | 449 else: |
423 output = e.output | 450 output = e.output |
424 | 451 |
425 output = output.splitlines() | 452 output = output.splitlines() |
426 if single_line: | 453 if single_line: |
427 if not output: | 454 if not output: |
428 return '' | 455 return '' |
(...skipping 25 matching lines...) Expand all Loading... |
454 CommandFailedError if no process was killed. | 481 CommandFailedError if no process was killed. |
455 CommandTimeoutError on timeout. | 482 CommandTimeoutError on timeout. |
456 DeviceUnreachableError on missing device. | 483 DeviceUnreachableError on missing device. |
457 """ | 484 """ |
458 pids = self._GetPidsImpl(process_name) | 485 pids = self._GetPidsImpl(process_name) |
459 if not pids: | 486 if not pids: |
460 raise device_errors.CommandFailedError( | 487 raise device_errors.CommandFailedError( |
461 'No process "%s"' % process_name, device=str(self)) | 488 'No process "%s"' % process_name, device=str(self)) |
462 | 489 |
463 cmd = ['kill', '-%d' % signum] + pids.values() | 490 cmd = ['kill', '-%d' % signum] + pids.values() |
464 self._RunShellCommandImpl(cmd, as_root=as_root, check_return=True) | 491 self.RunShellCommand(cmd, as_root=as_root, check_return=True) |
465 | 492 |
466 if blocking: | 493 if blocking: |
467 wait_period = 0.1 | 494 wait_period = 0.1 |
468 while self._GetPidsImpl(process_name): | 495 while self._GetPidsImpl(process_name): |
469 time.sleep(wait_period) | 496 time.sleep(wait_period) |
470 | 497 |
471 return len(pids) | 498 return len(pids) |
472 | 499 |
473 @decorators.WithTimeoutAndRetriesFromInstance() | 500 @decorators.WithTimeoutAndRetriesFromInstance() |
474 def StartActivity(self, intent, blocking=False, trace_file_name=None, | 501 def StartActivity(self, intent, blocking=False, trace_file_name=None, |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 | 632 |
606 Raises: | 633 Raises: |
607 CommandFailedError on failure. | 634 CommandFailedError on failure. |
608 CommandTimeoutError on timeout. | 635 CommandTimeoutError on timeout. |
609 DeviceUnreachableError on missing device. | 636 DeviceUnreachableError on missing device. |
610 """ | 637 """ |
611 | 638 |
612 files = [] | 639 files = [] |
613 for h, d in host_device_tuples: | 640 for h, d in host_device_tuples: |
614 if os.path.isdir(h): | 641 if os.path.isdir(h): |
615 self._RunShellCommandImpl(['mkdir', '-p', d], check_return=True) | 642 self.RunShellCommand(['mkdir', '-p', d], check_return=True) |
616 files += self._GetChangedFilesImpl(h, d) | 643 files += self._GetChangedFilesImpl(h, d) |
617 | 644 |
618 if not files: | 645 if not files: |
619 return | 646 return |
620 | 647 |
621 size = sum(host_utils.GetRecursiveDiskUsage(h) for h, _ in files) | 648 size = sum(host_utils.GetRecursiveDiskUsage(h) for h, _ in files) |
622 file_count = len(files) | 649 file_count = len(files) |
623 dir_size = sum(host_utils.GetRecursiveDiskUsage(h) | 650 dir_size = sum(host_utils.GetRecursiveDiskUsage(h) |
624 for h, _ in host_device_tuples) | 651 for h, _ in host_device_tuples) |
625 dir_file_count = 0 | 652 dir_file_count = 0 |
(...skipping 11 matching lines...) Expand all Loading... |
637 | 664 |
638 self._InstallCommands() | 665 self._InstallCommands() |
639 | 666 |
640 if dir_push_duration < push_duration and ( | 667 if dir_push_duration < push_duration and ( |
641 dir_push_duration < zip_duration or not self._commands_installed): | 668 dir_push_duration < zip_duration or not self._commands_installed): |
642 self._PushChangedFilesIndividually(host_device_tuples) | 669 self._PushChangedFilesIndividually(host_device_tuples) |
643 elif push_duration < zip_duration or not self._commands_installed: | 670 elif push_duration < zip_duration or not self._commands_installed: |
644 self._PushChangedFilesIndividually(files) | 671 self._PushChangedFilesIndividually(files) |
645 else: | 672 else: |
646 self._PushChangedFilesZipped(files) | 673 self._PushChangedFilesZipped(files) |
647 self._RunShellCommandImpl( | 674 self.RunShellCommand( |
648 ['chmod', '-R', '777'] + [d for _, d in host_device_tuples], | 675 ['chmod', '-R', '777'] + [d for _, d in host_device_tuples], |
649 as_root=True, check_return=True) | 676 as_root=True, check_return=True) |
650 | 677 |
651 def _GetChangedFilesImpl(self, host_path, device_path): | 678 def _GetChangedFilesImpl(self, host_path, device_path): |
652 real_host_path = os.path.realpath(host_path) | 679 real_host_path = os.path.realpath(host_path) |
653 try: | 680 try: |
654 real_device_path = self._RunShellCommandImpl( | 681 real_device_path = self.RunShellCommand( |
655 ['realpath', device_path], single_line=True, check_return=True) | 682 ['realpath', device_path], single_line=True, check_return=True) |
656 except device_errors.CommandFailedError: | 683 except device_errors.CommandFailedError: |
657 real_device_path = None | 684 real_device_path = None |
658 if not real_device_path: | 685 if not real_device_path: |
659 return [(host_path, device_path)] | 686 return [(host_path, device_path)] |
660 | 687 |
661 # TODO(jbudorick): Move the md5 logic up into DeviceUtils or base | 688 # TODO(jbudorick): Move the md5 logic up into DeviceUtils or base |
662 # this function on mtime. | 689 # this function on mtime. |
663 # pylint: disable=W0212 | 690 # pylint: disable=W0212 |
664 host_hash_tuples, device_hash_tuples = self.old_interface._RunMd5Sum( | 691 host_hash_tuples, device_hash_tuples = self.old_interface._RunMd5Sum( |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 with tempfile.NamedTemporaryFile(suffix='.zip') as zip_file: | 764 with tempfile.NamedTemporaryFile(suffix='.zip') as zip_file: |
738 zip_proc = multiprocessing.Process( | 765 zip_proc = multiprocessing.Process( |
739 target=DeviceUtils._CreateDeviceZip, | 766 target=DeviceUtils._CreateDeviceZip, |
740 args=(zip_file.name, files)) | 767 args=(zip_file.name, files)) |
741 zip_proc.start() | 768 zip_proc.start() |
742 zip_proc.join() | 769 zip_proc.join() |
743 | 770 |
744 zip_on_device = '%s/tmp.zip' % self._GetExternalStoragePathImpl() | 771 zip_on_device = '%s/tmp.zip' % self._GetExternalStoragePathImpl() |
745 try: | 772 try: |
746 self.adb.Push(zip_file.name, zip_on_device) | 773 self.adb.Push(zip_file.name, zip_on_device) |
747 self._RunShellCommandImpl( | 774 self.RunShellCommand( |
748 ['unzip', zip_on_device], | 775 ['unzip', zip_on_device], |
749 as_root=True, | 776 as_root=True, |
750 env={'PATH': '$PATH:%s' % install_commands.BIN_DIR}, | 777 env={'PATH': '$PATH:%s' % install_commands.BIN_DIR}, |
751 check_return=True) | 778 check_return=True) |
752 finally: | 779 finally: |
753 if zip_proc.is_alive(): | 780 if zip_proc.is_alive(): |
754 zip_proc.terminate() | 781 zip_proc.terminate() |
755 if self.IsOnline(): | 782 if self.IsOnline(): |
756 self._RunShellCommandImpl(['rm', zip_on_device], check_return=True) | 783 self.RunShellCommand(['rm', zip_on_device], check_return=True) |
757 | 784 |
758 @staticmethod | 785 @staticmethod |
759 def _CreateDeviceZip(zip_path, host_device_tuples): | 786 def _CreateDeviceZip(zip_path, host_device_tuples): |
760 with zipfile.ZipFile(zip_path, 'w') as zip_file: | 787 with zipfile.ZipFile(zip_path, 'w') as zip_file: |
761 for host_path, device_path in host_device_tuples: | 788 for host_path, device_path in host_device_tuples: |
762 if os.path.isfile(host_path): | 789 if os.path.isfile(host_path): |
763 zip_file.write(host_path, device_path, zipfile.ZIP_DEFLATED) | 790 zip_file.write(host_path, device_path, zipfile.ZIP_DEFLATED) |
764 else: | 791 else: |
765 for hd, _, files in os.walk(host_path): | 792 for hd, _, files in os.walk(host_path): |
766 dd = '%s/%s' % (device_path, os.path.relpath(host_path, hd)) | 793 dd = '%s/%s' % (device_path, os.path.relpath(host_path, hd)) |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
884 timeout: timeout in seconds | 911 timeout: timeout in seconds |
885 retries: number of retries | 912 retries: number of retries |
886 | 913 |
887 Raises: | 914 Raises: |
888 CommandFailedError if the file could not be written on the device. | 915 CommandFailedError if the file could not be written on the device. |
889 CommandTimeoutError on timeout. | 916 CommandTimeoutError on timeout. |
890 DeviceUnreachableError on missing device. | 917 DeviceUnreachableError on missing device. |
891 """ | 918 """ |
892 cmd = 'echo %s > %s' % (cmd_helper.SingleQuote(text), | 919 cmd = 'echo %s > %s' % (cmd_helper.SingleQuote(text), |
893 cmd_helper.SingleQuote(device_path)) | 920 cmd_helper.SingleQuote(device_path)) |
894 self._RunShellCommandImpl(cmd, as_root=as_root, check_return=True) | 921 self.RunShellCommand(cmd, as_root=as_root, check_return=True) |
895 | 922 |
896 @decorators.WithTimeoutAndRetriesFromInstance() | 923 @decorators.WithTimeoutAndRetriesFromInstance() |
897 def Ls(self, device_path, timeout=None, retries=None): | 924 def Ls(self, device_path, timeout=None, retries=None): |
898 """Lists the contents of a directory on the device. | 925 """Lists the contents of a directory on the device. |
899 | 926 |
900 Args: | 927 Args: |
901 device_path: A string containing the path of the directory on the device | 928 device_path: A string containing the path of the directory on the device |
902 to list. | 929 to list. |
903 timeout: timeout in seconds | 930 timeout: timeout in seconds |
904 retries: number of retries | 931 retries: number of retries |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 provided |process_name|. | 1054 provided |process_name|. |
1028 | 1055 |
1029 Raises: | 1056 Raises: |
1030 CommandTimeoutError on timeout. | 1057 CommandTimeoutError on timeout. |
1031 DeviceUnreachableError on missing device. | 1058 DeviceUnreachableError on missing device. |
1032 """ | 1059 """ |
1033 return self._GetPidsImpl(process_name) | 1060 return self._GetPidsImpl(process_name) |
1034 | 1061 |
1035 def _GetPidsImpl(self, process_name): | 1062 def _GetPidsImpl(self, process_name): |
1036 procs_pids = {} | 1063 procs_pids = {} |
1037 for line in self._RunShellCommandImpl('ps', check_return=True): | 1064 for line in self.RunShellCommand('ps', check_return=True): |
1038 try: | 1065 try: |
1039 ps_data = line.split() | 1066 ps_data = line.split() |
1040 if process_name in ps_data[-1]: | 1067 if process_name in ps_data[-1]: |
1041 procs_pids[ps_data[-1]] = ps_data[1] | 1068 procs_pids[ps_data[-1]] = ps_data[1] |
1042 except IndexError: | 1069 except IndexError: |
1043 pass | 1070 pass |
1044 return procs_pids | 1071 return procs_pids |
1045 | 1072 |
1046 @decorators.WithTimeoutAndRetriesFromInstance() | 1073 @decorators.WithTimeoutAndRetriesFromInstance() |
1047 def TakeScreenshot(self, host_path=None, timeout=None, retries=None): | 1074 def TakeScreenshot(self, host_path=None, timeout=None, retries=None): |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1125 Returns: | 1152 Returns: |
1126 A Parallelizer operating over |devices|. | 1153 A Parallelizer operating over |devices|. |
1127 """ | 1154 """ |
1128 if not devices or len(devices) == 0: | 1155 if not devices or len(devices) == 0: |
1129 devices = pylib.android_commands.GetAttachedDevices() | 1156 devices = pylib.android_commands.GetAttachedDevices() |
1130 parallelizer_type = (parallelizer.Parallelizer if async | 1157 parallelizer_type = (parallelizer.Parallelizer if async |
1131 else parallelizer.SyncParallelizer) | 1158 else parallelizer.SyncParallelizer) |
1132 return parallelizer_type([ | 1159 return parallelizer_type([ |
1133 d if isinstance(d, DeviceUtils) else DeviceUtils(d) | 1160 d if isinstance(d, DeviceUtils) else DeviceUtils(d) |
1134 for d in devices]) | 1161 for d in devices]) |
OLD | NEW |