Index: build/android/pylib/device/device_utils.py |
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py |
index b2fa1ff3953a702f6cd3676f495db89144dcf0d7..14ee6623da49e1d770051a8ea23c6420c0b03548 100644 |
--- a/build/android/pylib/device/device_utils.py |
+++ b/build/android/pylib/device/device_utils.py |
@@ -14,6 +14,7 @@ import os |
import re |
import sys |
import tempfile |
+import threading |
import time |
import zipfile |
@@ -220,18 +221,50 @@ class DeviceUtils(object): |
CommandTimeoutError if one of the component waits times out. |
DeviceUnreachableError if the device becomes unresponsive. |
""" |
- self._WaitUntilFullyBootedImpl(wifi=wifi, timeout=timeout) |
+ def sd_card_ready(): |
+ return self.RunShellCommand(['ls', self.GetExternalStoragePath()]) |
- def _WaitUntilFullyBootedImpl(self, wifi=False, timeout=None): |
- if timeout is None: |
- timeout = self._default_timeout |
- self.old_interface.WaitForSystemBootCompleted(timeout) |
- self.old_interface.WaitForDevicePm() |
- self.old_interface.WaitForSdCardReady(timeout) |
+ def pm_ready(): |
+ return self.GetApplicationPath('android') |
+ |
+ def boot_completed(): |
+ return self.GetProp('sys.boot_completed') == '1' |
+ |
+ def wifi_enabled(): |
+ return 'Wi-Fi is enabled' in self.RunShellCommand(['dumpsys', 'wifi']) |
+ |
+ self.adb.WaitForDevice() |
+ self._WaitFor(sd_card_ready) |
+ self._WaitFor(pm_ready) |
+ self._WaitFor(boot_completed) |
if wifi: |
- while not 'Wi-Fi is enabled' in ( |
- self.old_interface.RunShellCommand('dumpsys wifi')): |
- time.sleep(1) |
+ self._WaitFor(wifi_enabled) |
+ |
+ def _WaitFor(self, condition, wait_period=5): |
+ start = time.time() |
+ while not threading.current_thread().Stopped(): |
+ try: |
+ r = condition() |
+ except device_errors.CommandFailedError as e: |
+ r = False |
jbudorick
2014/10/24 17:30:51
nit: similarly here w.r.t False v None
|
+ logging.warning('%s at %s', str(e), threading.current_thread().name) |
+ elapsed = time.time() - start |
+ if r: |
+ logging.warning('%s: condition %r met (%1.2f) at %s', str(self), |
jbudorick
2014/10/24 17:30:51
nit: should be info or debug, not warning
perezju
2014/10/27 11:07:07
Yes, I agree these should be info. At the moment t
|
+ condition.__name__, elapsed, threading.current_thread().name) |
+ return r |
+ time.sleep(wait_period) |
+ logging.warning('%s: condition %r not yet met (%1.2f) at %s', str(self), |
+ condition.__name__, elapsed, threading.current_thread().name) |
+ return False |
jbudorick
2014/10/24 17:30:51
nit: I think this should return None, as False imp
perezju
2014/10/27 11:07:06
Agree.
|
+ |
+ @decorators.WithTimeoutAndRetriesFromInstance() |
+ def GetApplicationPath(self, package, timeout=None, retries=None): |
+ output = self.RunShellCommand(['pm', 'path', package], single_line=True) |
+ if not output.startswith('package:'): |
+ raise device_errors.CommandFailedError('pm path returned: %r' % output, str(self)) |
+ return output[len('package:'):] |
+ |
REBOOT_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT |
REBOOT_DEFAULT_RETRIES = _DEFAULT_RETRIES |
@@ -394,7 +427,7 @@ class DeviceUtils(object): |
if single_line: |
if len(output) != 1: |
msg = 'exactly one line of output expected, but got: %s' |
- raise device_errors.CommandFailedError(msg % output) |
+ raise device_errors.CommandFailedError(msg % output, str(self)) |
return output[0] |
else: |
return output |
@@ -894,13 +927,13 @@ class DeviceUtils(object): |
""" |
return self.old_interface.SetJavaAssertsEnabled(enabled) |
- @decorators.WithTimeoutAndRetriesFromInstance() |
- def GetProp(self, property_name, timeout=None, retries=None): |
+ def GetProp(self, property_name, cache=False, timeout=None, retries=None): |
jbudorick
2014/10/24 17:30:51
We should make sure we test the timeout/retries pa
perezju
2014/10/27 11:07:07
Acknowledged.
|
"""Gets a property from the device. |
Args: |
property_name: A string containing the name of the property to get from |
- the device. |
+ the device. |
+ cache: A boolean indicating whether to cache the value of this property. |
timeout: timeout in seconds |
retries: number of retries |
@@ -910,13 +943,21 @@ class DeviceUtils(object): |
Raises: |
CommandTimeoutError on timeout. |
""" |
- return self._GetPropImpl(property_name) |
- |
- def _GetPropImpl(self, property_name): |
- return self.old_interface.system_properties[property_name] |
+ cache_name = '_prop:' + property_name |
+ if cache and cache_name in self._cache: |
jbudorick
2014/10/24 17:30:51
I think that, for now, we should limit property ca
perezju
2014/10/27 11:07:07
An idea I had was to provide the class with some p
|
+ return self._cache[cache_name] |
+ else: |
+ # timeout and retries are handled down at run shell, because we don't |
+ # want to apply them in the other branch when reading from the cache |
+ value = self.RunShellCommand(['getprop', property_name], single_line=True, |
+ timeout=timeout, retries=retries) |
+ if cache or cache_name in self._cache: |
+ self._cache[cache_name] = value |
+ return value |
@decorators.WithTimeoutAndRetriesFromInstance() |
- def SetProp(self, property_name, value, timeout=None, retries=None): |
+ def SetProp(self, property_name, value, check=False, timeout=None, |
jbudorick
2014/10/24 17:30:51
What's the motivation behind check?
perezju
2014/10/27 11:07:07
The TODO here https://cs.corp.google.com/#clankium
jbudorick
2014/10/27 19:15:36
Use the public cs for upstream reviews:
https://co
|
+ retries=None): |
"""Sets a property on the device. |
Args: |
@@ -930,7 +971,11 @@ class DeviceUtils(object): |
Raises: |
CommandTimeoutError on timeout. |
""" |
- self.old_interface.system_properties[property_name] = value |
+ self.RunShellCommand(['setprop', property_name, value]) |
jbudorick
2014/10/24 17:30:51
If we expand caching beyond read-only properties,
perezju
2014/10/27 11:07:06
This happens "auto-magically" when check=True. May
|
+ if check and value != self.GetProp(property_name): |
+ raise device_errors.CommandFailedError( |
+ 'Unable to set property %r on the device to %r' |
+ % (property_name, value), str(self)) |
@decorators.WithTimeoutAndRetriesFromInstance() |
def GetABI(self, timeout=None, retries=None): |