Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Side by Side Diff: build/android/pylib/device/device_utils.py

Issue 683113005: Update from chromium https://crrev.com/302282 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
11 import logging 11 import logging
12 import multiprocessing 12 import multiprocessing
13 import os 13 import os
14 import re 14 import re
15 import sys 15 import sys
16 import tempfile 16 import tempfile
17 import time 17 import time
18 import zipfile 18 import zipfile
19 19
20 import pylib.android_commands 20 import pylib.android_commands
21 from pylib import cmd_helper 21 from pylib import cmd_helper
22 from pylib.device import adb_wrapper 22 from pylib.device import adb_wrapper
23 from pylib.device import decorators 23 from pylib.device import decorators
24 from pylib.device import device_errors 24 from pylib.device import device_errors
25 from pylib.device.commands import install_commands 25 from pylib.device.commands import install_commands
26 from pylib.utils import apk_helper 26 from pylib.utils import apk_helper
27 from pylib.utils import host_utils 27 from pylib.utils import host_utils
28 from pylib.utils import parallelizer 28 from pylib.utils import parallelizer
29 from pylib.utils import timeout_retry
29 30
30 _DEFAULT_TIMEOUT = 30 31 _DEFAULT_TIMEOUT = 30
31 _DEFAULT_RETRIES = 3 32 _DEFAULT_RETRIES = 3
32 33
33 34
34 @decorators.WithExplicitTimeoutAndRetries( 35 @decorators.WithExplicitTimeoutAndRetries(
35 _DEFAULT_TIMEOUT, _DEFAULT_RETRIES) 36 _DEFAULT_TIMEOUT, _DEFAULT_RETRIES)
36 def GetAVDs(): 37 def GetAVDs():
37 """Returns a list of Android Virtual Devices. 38 """Returns a list of Android Virtual Devices.
38 39
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 Args: 102 Args:
102 timeout: timeout in seconds 103 timeout: timeout in seconds
103 retries: number of retries 104 retries: number of retries
104 105
105 Returns: 106 Returns:
106 True if the device is online, False otherwise. 107 True if the device is online, False otherwise.
107 108
108 Raises: 109 Raises:
109 CommandTimeoutError on timeout. 110 CommandTimeoutError on timeout.
110 """ 111 """
111 return self._IsOnlineImpl() 112 return self.adb.GetState() == 'device'
112
113 def _IsOnlineImpl(self):
114 return self.old_interface.IsOnline()
115 113
116 @decorators.WithTimeoutAndRetriesFromInstance() 114 @decorators.WithTimeoutAndRetriesFromInstance()
117 def HasRoot(self, timeout=None, retries=None): 115 def HasRoot(self, timeout=None, retries=None):
118 """Checks whether or not adbd has root privileges. 116 """Checks whether or not adbd has root privileges.
119 117
120 Args: 118 Args:
121 timeout: timeout in seconds 119 timeout: timeout in seconds
122 retries: number of retries 120 retries: number of retries
123 121
124 Returns: 122 Returns:
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 retries: number of retries 160 retries: number of retries
163 161
164 Returns: 162 Returns:
165 True if the device is running a user build, False otherwise (i.e. if 163 True if the device is running a user build, False otherwise (i.e. if
166 it's running a userdebug build). 164 it's running a userdebug build).
167 165
168 Raises: 166 Raises:
169 CommandTimeoutError on timeout. 167 CommandTimeoutError on timeout.
170 DeviceUnreachableError on missing device. 168 DeviceUnreachableError on missing device.
171 """ 169 """
172 return self._GetPropImpl('ro.build.type') == 'user' 170 return self.build_type == 'user'
173 171
174 @decorators.WithTimeoutAndRetriesFromInstance() 172 @decorators.WithTimeoutAndRetriesFromInstance()
175 def GetExternalStoragePath(self, timeout=None, retries=None): 173 def GetExternalStoragePath(self, timeout=None, retries=None):
176 """Get the device's path to its SD card. 174 """Get the device's path to its SD card.
177 175
178 Args: 176 Args:
179 timeout: timeout in seconds 177 timeout: timeout in seconds
180 retries: number of retries 178 retries: number of retries
181 179
182 Returns: 180 Returns:
(...skipping 13 matching lines...) Expand all
196 value = self._RunShellCommandImpl('echo $EXTERNAL_STORAGE', 194 value = self._RunShellCommandImpl('echo $EXTERNAL_STORAGE',
197 single_line=True, 195 single_line=True,
198 check_return=True) 196 check_return=True)
199 if not value: 197 if not value:
200 raise device_errors.CommandFailedError('$EXTERNAL_STORAGE is not set', 198 raise device_errors.CommandFailedError('$EXTERNAL_STORAGE is not set',
201 str(self)) 199 str(self))
202 self._cache['external_storage'] = value 200 self._cache['external_storage'] = value
203 return value 201 return value
204 202
205 @decorators.WithTimeoutAndRetriesFromInstance() 203 @decorators.WithTimeoutAndRetriesFromInstance()
204 def GetApplicationPath(self, package, timeout=None, retries=None):
205 """Get the path of the installed apk on the device for the given package.
206
207 Args:
208 package: Name of the package.
209
210 Returns:
211 Path to the apk on the device if it exists, None otherwise.
212 """
213 output = self.RunShellCommand(['pm', 'path', package], single_line=True,
214 check_return=True)
215 if not output:
216 return None
217 if not output.startswith('package:'):
218 raise device_errors.CommandFailedError('pm path returned: %r' % output,
219 str(self))
220 return output[len('package:'):]
221
222 @decorators.WithTimeoutAndRetriesFromInstance()
206 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None): 223 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None):
207 """Wait for the device to fully boot. 224 """Wait for the device to fully boot.
208 225
209 This means waiting for the device to boot, the package manager to be 226 This means waiting for the device to boot, the package manager to be
210 available, and the SD card to be ready. It can optionally mean waiting 227 available, and the SD card to be ready. It can optionally mean waiting
211 for wifi to come up, too. 228 for wifi to come up, too.
212 229
213 Args: 230 Args:
214 wifi: A boolean indicating if we should wait for wifi to come up or not. 231 wifi: A boolean indicating if we should wait for wifi to come up or not.
215 timeout: timeout in seconds 232 timeout: timeout in seconds
216 retries: number of retries 233 retries: number of retries
217 234
218 Raises: 235 Raises:
219 CommandFailedError on failure. 236 CommandFailedError on failure.
220 CommandTimeoutError if one of the component waits times out. 237 CommandTimeoutError if one of the component waits times out.
221 DeviceUnreachableError if the device becomes unresponsive. 238 DeviceUnreachableError if the device becomes unresponsive.
222 """ 239 """
223 self._WaitUntilFullyBootedImpl(wifi=wifi, timeout=timeout) 240 def sd_card_ready():
241 return self.RunShellCommand(['ls', self.GetExternalStoragePath()],
242 single_line=True, check_return=True)
224 243
225 def _WaitUntilFullyBootedImpl(self, wifi=False, timeout=None): 244 def pm_ready():
226 if timeout is None: 245 try:
227 timeout = self._default_timeout 246 return self.GetApplicationPath('android')
228 self.old_interface.WaitForSystemBootCompleted(timeout) 247 except device_errors.CommandFailedError:
229 self.old_interface.WaitForDevicePm() 248 return False
230 self.old_interface.WaitForSdCardReady(timeout) 249
250 def boot_completed():
251 return self.GetProp('sys.boot_completed') == '1'
252
253 def wifi_enabled():
254 return 'Wi-Fi is enabled' in self.RunShellCommand(['dumpsys', 'wifi'])
255
256 self.adb.WaitForDevice()
257 timeout_retry.WaitFor(sd_card_ready)
258 timeout_retry.WaitFor(pm_ready)
259 timeout_retry.WaitFor(boot_completed)
231 if wifi: 260 if wifi:
232 while not 'Wi-Fi is enabled' in ( 261 timeout_retry.WaitFor(wifi_enabled)
233 self.old_interface.RunShellCommand('dumpsys wifi')):
234 time.sleep(1)
235 262
236 REBOOT_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT 263 REBOOT_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT
237 REBOOT_DEFAULT_RETRIES = _DEFAULT_RETRIES 264 REBOOT_DEFAULT_RETRIES = _DEFAULT_RETRIES
238 265
239 @decorators.WithTimeoutAndRetriesDefaults( 266 @decorators.WithTimeoutAndRetriesDefaults(
240 REBOOT_DEFAULT_TIMEOUT, 267 REBOOT_DEFAULT_TIMEOUT,
241 REBOOT_DEFAULT_RETRIES) 268 REBOOT_DEFAULT_RETRIES)
242 def Reboot(self, block=True, timeout=None, retries=None): 269 def Reboot(self, block=True, timeout=None, retries=None):
243 """Reboot the device. 270 """Reboot the device.
244 271
245 Args: 272 Args:
246 block: A boolean indicating if we should wait for the reboot to complete. 273 block: A boolean indicating if we should wait for the reboot to complete.
247 timeout: timeout in seconds 274 timeout: timeout in seconds
248 retries: number of retries 275 retries: number of retries
249 276
250 Raises: 277 Raises:
251 CommandTimeoutError on timeout. 278 CommandTimeoutError on timeout.
252 DeviceUnreachableError on missing device. 279 DeviceUnreachableError on missing device.
253 """ 280 """
254 self.old_interface.Reboot() 281 def device_offline():
282 return not self.IsOnline()
283
284 self.adb.Reboot()
285 self._cache = {}
286 timeout_retry.WaitFor(device_offline, wait_period=1, max_tries=5)
255 if block: 287 if block:
256 self._WaitUntilFullyBootedImpl(timeout=timeout) 288 self.WaitUntilFullyBooted()
257 289
258 INSTALL_DEFAULT_TIMEOUT = 4 * _DEFAULT_TIMEOUT 290 INSTALL_DEFAULT_TIMEOUT = 4 * _DEFAULT_TIMEOUT
259 INSTALL_DEFAULT_RETRIES = _DEFAULT_RETRIES 291 INSTALL_DEFAULT_RETRIES = _DEFAULT_RETRIES
260 292
261 @decorators.WithTimeoutAndRetriesDefaults( 293 @decorators.WithTimeoutAndRetriesDefaults(
262 INSTALL_DEFAULT_TIMEOUT, 294 INSTALL_DEFAULT_TIMEOUT,
263 INSTALL_DEFAULT_RETRIES) 295 INSTALL_DEFAULT_RETRIES)
264 def Install(self, apk_path, reinstall=False, timeout=None, retries=None): 296 def Install(self, apk_path, reinstall=False, timeout=None, retries=None):
265 """Install an APK. 297 """Install an APK.
266 298
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 364
333 Args: 365 Args:
334 cmd: A string with the full command to run on the device, or a sequence 366 cmd: A string with the full command to run on the device, or a sequence
335 containing the command and its arguments. 367 containing the command and its arguments.
336 check_return: A boolean indicating whether or not the return code should 368 check_return: A boolean indicating whether or not the return code should
337 be checked. 369 be checked.
338 cwd: The device directory in which the command should be run. 370 cwd: The device directory in which the command should be run.
339 env: The environment variables with which the command should be run. 371 env: The environment variables with which the command should be run.
340 as_root: A boolean indicating whether the shell command should be run 372 as_root: A boolean indicating whether the shell command should be run
341 with root privileges. 373 with root privileges.
342 single_line: A boolean indicating if a single line of output is expected, 374 single_line: A boolean indicating if only a single line of output is
343 and the caller wants to retrieve the value of that line. The default 375 expected.
344 behaviour is to return a list of output lines.
345 timeout: timeout in seconds 376 timeout: timeout in seconds
346 retries: number of retries 377 retries: number of retries
347 378
348 Returns: 379 Returns:
349 The output of the command either as list of lines or, when single_line is 380 If single_line is False, the output of the command as a list of lines,
350 True, the value contained in the single expected line of output. 381 otherwise, a string with the unique line of output emmited by the command
382 (with the optional newline at the end stripped).
351 383
352 Raises: 384 Raises:
353 AdbShellCommandFailedError if check_return is True and the exit code of 385 AdbShellCommandFailedError if check_return is True and the exit code of
354 the command run on the device is non-zero. 386 the command run on the device is non-zero.
355 CommandFailedError if single_line is True but the output consists of 387 CommandFailedError if single_line is True but the output contains two or
356 either zero or more than one lines. 388 more lines.
357 CommandTimeoutError on timeout. 389 CommandTimeoutError on timeout.
358 DeviceUnreachableError on missing device. 390 DeviceUnreachableError on missing device.
359 """ 391 """
360 return self._RunShellCommandImpl(cmd, check_return=check_return, cwd=cwd, 392 return self._RunShellCommandImpl(cmd, check_return=check_return, cwd=cwd,
361 env=env, as_root=as_root, single_line=single_line, timeout=timeout) 393 env=env, as_root=as_root, single_line=single_line, timeout=timeout)
362 394
363 def _RunShellCommandImpl(self, cmd, check_return=False, cwd=None, env=None, 395 def _RunShellCommandImpl(self, cmd, check_return=False, cwd=None, env=None,
364 as_root=False, single_line=False, timeout=None): 396 as_root=False, single_line=False, timeout=None):
365 def env_quote(key, value): 397 def env_quote(key, value):
366 if not DeviceUtils._VALID_SHELL_VARIABLE.match(key): 398 if not DeviceUtils._VALID_SHELL_VARIABLE.match(key):
(...skipping 18 matching lines...) Expand all
385 # adb.Shell without a timeout-and-retries wrapper. 417 # adb.Shell without a timeout-and-retries wrapper.
386 output = self.adb.Shell(cmd, expect_rc=0, timeout=timeout, retries=0) 418 output = self.adb.Shell(cmd, expect_rc=0, timeout=timeout, retries=0)
387 except device_errors.AdbShellCommandFailedError as e: 419 except device_errors.AdbShellCommandFailedError as e:
388 if check_return: 420 if check_return:
389 raise 421 raise
390 else: 422 else:
391 output = e.output 423 output = e.output
392 424
393 output = output.splitlines() 425 output = output.splitlines()
394 if single_line: 426 if single_line:
395 if len(output) != 1: 427 if not output:
396 msg = 'exactly one line of output expected, but got: %s' 428 return ''
397 raise device_errors.CommandFailedError(msg % output) 429 elif len(output) == 1:
398 return output[0] 430 return output[0]
431 else:
432 msg = 'one line of output was expected, but got: %s'
433 raise device_errors.CommandFailedError(msg % output, str(self))
399 else: 434 else:
400 return output 435 return output
401 436
402 @decorators.WithTimeoutAndRetriesFromInstance() 437 @decorators.WithTimeoutAndRetriesFromInstance()
403 def KillAll(self, process_name, signum=9, as_root=False, blocking=False, 438 def KillAll(self, process_name, signum=9, as_root=False, blocking=False,
404 timeout=None, retries=None): 439 timeout=None, retries=None):
405 """Kill all processes with the given name on the device. 440 """Kill all processes with the given name on the device.
406 441
407 Args: 442 Args:
408 process_name: A string containing the name of the process to kill. 443 process_name: A string containing the name of the process to kill.
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 self._RunShellCommandImpl( 647 self._RunShellCommandImpl(
613 ['chmod', '-R', '777'] + [d for _, d in host_device_tuples], 648 ['chmod', '-R', '777'] + [d for _, d in host_device_tuples],
614 as_root=True, check_return=True) 649 as_root=True, check_return=True)
615 650
616 def _GetChangedFilesImpl(self, host_path, device_path): 651 def _GetChangedFilesImpl(self, host_path, device_path):
617 real_host_path = os.path.realpath(host_path) 652 real_host_path = os.path.realpath(host_path)
618 try: 653 try:
619 real_device_path = self._RunShellCommandImpl( 654 real_device_path = self._RunShellCommandImpl(
620 ['realpath', device_path], single_line=True, check_return=True) 655 ['realpath', device_path], single_line=True, check_return=True)
621 except device_errors.CommandFailedError: 656 except device_errors.CommandFailedError:
657 real_device_path = None
658 if not real_device_path:
622 return [(host_path, device_path)] 659 return [(host_path, device_path)]
623 660
624 # TODO(jbudorick): Move the md5 logic up into DeviceUtils or base 661 # TODO(jbudorick): Move the md5 logic up into DeviceUtils or base
625 # this function on mtime. 662 # this function on mtime.
626 # pylint: disable=W0212 663 # pylint: disable=W0212
627 host_hash_tuples, device_hash_tuples = self.old_interface._RunMd5Sum( 664 host_hash_tuples, device_hash_tuples = self.old_interface._RunMd5Sum(
628 real_host_path, real_device_path) 665 real_host_path, real_device_path)
629 # pylint: enable=W0212 666 # pylint: enable=W0212
630 667
631 if os.path.isfile(host_path): 668 if os.path.isfile(host_path):
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 try: 745 try:
709 self.adb.Push(zip_file.name, zip_on_device) 746 self.adb.Push(zip_file.name, zip_on_device)
710 self._RunShellCommandImpl( 747 self._RunShellCommandImpl(
711 ['unzip', zip_on_device], 748 ['unzip', zip_on_device],
712 as_root=True, 749 as_root=True,
713 env={'PATH': '$PATH:%s' % install_commands.BIN_DIR}, 750 env={'PATH': '$PATH:%s' % install_commands.BIN_DIR},
714 check_return=True) 751 check_return=True)
715 finally: 752 finally:
716 if zip_proc.is_alive(): 753 if zip_proc.is_alive():
717 zip_proc.terminate() 754 zip_proc.terminate()
718 if self._IsOnlineImpl(): 755 if self.IsOnline():
719 self._RunShellCommandImpl(['rm', zip_on_device], check_return=True) 756 self._RunShellCommandImpl(['rm', zip_on_device], check_return=True)
720 757
721 @staticmethod 758 @staticmethod
722 def _CreateDeviceZip(zip_path, host_device_tuples): 759 def _CreateDeviceZip(zip_path, host_device_tuples):
723 with zipfile.ZipFile(zip_path, 'w') as zip_file: 760 with zipfile.ZipFile(zip_path, 'w') as zip_file:
724 for host_path, device_path in host_device_tuples: 761 for host_path, device_path in host_device_tuples:
725 if os.path.isfile(host_path): 762 if os.path.isfile(host_path):
726 zip_file.write(host_path, device_path, zipfile.ZIP_DEFLATED) 763 zip_file.write(host_path, device_path, zipfile.ZIP_DEFLATED)
727 else: 764 else:
728 for hd, _, files in os.walk(host_path): 765 for hd, _, files in os.walk(host_path):
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
887 924
888 Returns: 925 Returns:
889 True if the device-side property changed and a restart is required as a 926 True if the device-side property changed and a restart is required as a
890 result, False otherwise. 927 result, False otherwise.
891 928
892 Raises: 929 Raises:
893 CommandTimeoutError on timeout. 930 CommandTimeoutError on timeout.
894 """ 931 """
895 return self.old_interface.SetJavaAssertsEnabled(enabled) 932 return self.old_interface.SetJavaAssertsEnabled(enabled)
896 933
897 @decorators.WithTimeoutAndRetriesFromInstance() 934 @property
898 def GetProp(self, property_name, timeout=None, retries=None): 935 def build_type(self):
936 """Returns the build type of the system (e.g. userdebug)."""
937 return self.GetProp('ro.build.type', cache=True)
938
939 def GetProp(self, property_name, cache=False, timeout=None, retries=None):
899 """Gets a property from the device. 940 """Gets a property from the device.
900 941
901 Args: 942 Args:
902 property_name: A string containing the name of the property to get from 943 property_name: A string containing the name of the property to get from
903 the device. 944 the device.
945 cache: A boolean indicating whether to cache the value of this property.
904 timeout: timeout in seconds 946 timeout: timeout in seconds
905 retries: number of retries 947 retries: number of retries
906 948
907 Returns: 949 Returns:
908 The value of the device's |property_name| property. 950 The value of the device's |property_name| property.
909 951
910 Raises: 952 Raises:
911 CommandTimeoutError on timeout. 953 CommandTimeoutError on timeout.
912 """ 954 """
913 return self._GetPropImpl(property_name) 955 cache_key = '_prop:' + property_name
914 956 if cache and cache_key in self._cache:
915 def _GetPropImpl(self, property_name): 957 return self._cache[cache_key]
916 return self.old_interface.system_properties[property_name] 958 else:
959 # timeout and retries are handled down at run shell, because we don't
960 # want to apply them in the other branch when reading from the cache
961 value = self.RunShellCommand(['getprop', property_name],
962 single_line=True, check_return=True,
963 timeout=timeout, retries=retries)
964 if cache or cache_key in self._cache:
965 self._cache[cache_key] = value
966 return value
917 967
918 @decorators.WithTimeoutAndRetriesFromInstance() 968 @decorators.WithTimeoutAndRetriesFromInstance()
919 def SetProp(self, property_name, value, timeout=None, retries=None): 969 def SetProp(self, property_name, value, check=False, timeout=None,
970 retries=None):
920 """Sets a property on the device. 971 """Sets a property on the device.
921 972
922 Args: 973 Args:
923 property_name: A string containing the name of the property to set on 974 property_name: A string containing the name of the property to set on
924 the device. 975 the device.
925 value: A string containing the value to set to the property on the 976 value: A string containing the value to set to the property on the
926 device. 977 device.
978 check: A boolean indicating whether to check that the property was
979 successfully set on the device.
927 timeout: timeout in seconds 980 timeout: timeout in seconds
928 retries: number of retries 981 retries: number of retries
929 982
930 Raises: 983 Raises:
984 CommandFailedError if check is true and the property was not correctly
985 set on the device (e.g. because it is not rooted).
931 CommandTimeoutError on timeout. 986 CommandTimeoutError on timeout.
932 """ 987 """
933 self.old_interface.system_properties[property_name] = value 988 self.RunShellCommand(['setprop', property_name, value], check_return=True)
989 if property_name in self._cache:
990 del self._cache[property_name]
991 # TODO(perezju) remove the option and make the check mandatory, but using a
992 # single shell script to both set- and getprop.
993 if check and value != self.GetProp(property_name):
994 raise device_errors.CommandFailedError(
995 'Unable to set property %r on the device to %r'
996 % (property_name, value), str(self))
934 997
935 @decorators.WithTimeoutAndRetriesFromInstance() 998 @decorators.WithTimeoutAndRetriesFromInstance()
936 def GetABI(self, timeout=None, retries=None): 999 def GetABI(self, timeout=None, retries=None):
937 """Gets the device main ABI. 1000 """Gets the device main ABI.
938 1001
939 Args: 1002 Args:
940 timeout: timeout in seconds 1003 timeout: timeout in seconds
941 retries: number of retries 1004 retries: number of retries
942 1005
943 Returns: 1006 Returns:
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1062 Returns: 1125 Returns:
1063 A Parallelizer operating over |devices|. 1126 A Parallelizer operating over |devices|.
1064 """ 1127 """
1065 if not devices or len(devices) == 0: 1128 if not devices or len(devices) == 0:
1066 devices = pylib.android_commands.GetAttachedDevices() 1129 devices = pylib.android_commands.GetAttachedDevices()
1067 parallelizer_type = (parallelizer.Parallelizer if async 1130 parallelizer_type = (parallelizer.Parallelizer if async
1068 else parallelizer.SyncParallelizer) 1131 else parallelizer.SyncParallelizer)
1069 return parallelizer_type([ 1132 return parallelizer_type([
1070 d if isinstance(d, DeviceUtils) else DeviceUtils(d) 1133 d if isinstance(d, DeviceUtils) else DeviceUtils(d)
1071 for d in devices]) 1134 for d in devices])
OLDNEW
« no previous file with comments | « build/android/pylib/device/adb_wrapper.py ('k') | build/android/pylib/device/device_utils_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698