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 |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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]) |
OLD | NEW |