 Chromium Code Reviews
 Chromium Code Reviews Issue 99713002:
  Factor out a system_properties interface for interacting with getprop/setprop.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 99713002:
  Factor out a system_properties interface for interacting with getprop/setprop.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| 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 | 
| 11 import datetime | 11 import datetime | 
| 12 import logging | 12 import logging | 
| 13 import os | 13 import os | 
| 14 import re | 14 import re | 
| 15 import shlex | 15 import shlex | 
| 16 import signal | 16 import signal | 
| 17 import subprocess | 17 import subprocess | 
| 18 import sys | 18 import sys | 
| 19 import tempfile | 19 import tempfile | 
| 20 import time | 20 import time | 
| 21 | 21 | 
| 22 import cmd_helper | 22 import cmd_helper | 
| 23 import constants | 23 import constants | 
| 24 import screenshot | 24 import screenshot | 
| 25 import system_properties | |
| 25 | 26 | 
| 26 from utils import host_path_finder | 27 from utils import host_path_finder | 
| 27 | 28 | 
| 28 try: | 29 try: | 
| 29 from pylib import pexpect | 30 from pylib import pexpect | 
| 30 except: | 31 except: | 
| 31 pexpect = None | 32 pexpect = None | 
| 32 | 33 | 
| 33 sys.path.append(os.path.join( | 34 sys.path.append(os.path.join( | 
| 34 constants.DIR_SOURCE_ROOT, 'third_party', 'android_testrunner')) | 35 constants.DIR_SOURCE_ROOT, 'third_party', 'android_testrunner')) | 
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 """Returns the timestamp of the given |log_line| in the given year.""" | 222 """Returns the timestamp of the given |log_line| in the given year.""" | 
| 222 try: | 223 try: | 
| 223 return datetime.datetime.strptime('%s-%s' % (year, log_line[:18]), | 224 return datetime.datetime.strptime('%s-%s' % (year, log_line[:18]), | 
| 224 '%Y-%m-%d %H:%M:%S.%f') | 225 '%Y-%m-%d %H:%M:%S.%f') | 
| 225 except (ValueError, IndexError): | 226 except (ValueError, IndexError): | 
| 226 logging.critical('Error reading timestamp from ' + log_line) | 227 logging.critical('Error reading timestamp from ' + log_line) | 
| 227 return None | 228 return None | 
| 228 | 229 | 
| 229 | 230 | 
| 230 class AndroidCommands(object): | 231 class AndroidCommands(object): | 
| 231 """Helper class for communicating with Android device via adb. | 232 """Helper class for communicating with Android device via adb.""" | 
| 232 | 233 | 
| 233 Args: | 234 def __init__(self, device=None, api_strict_mode=False): | 
| 234 device: If given, adb commands are only send to the device of this ID. | 235 """Constructor. | 
| 235 Otherwise commands are sent to all attached devices. | |
| 236 """ | |
| 237 | 236 | 
| 238 def __init__(self, device=None): | 237 Args: | 
| 238 device: If given, adb commands are only send to the device of this ID. | |
| 239 Otherwise commands are sent to all attached devices. | |
| 240 api_strict_mode: A boolean indicating whether fatal errors should be | |
| 241 raised if this API is used improperly. | |
| 242 """ | |
| 239 adb_dir = os.path.dirname(constants.ADB_PATH) | 243 adb_dir = os.path.dirname(constants.ADB_PATH) | 
| 240 if adb_dir and adb_dir not in os.environ['PATH'].split(os.pathsep): | 244 if adb_dir and adb_dir not in os.environ['PATH'].split(os.pathsep): | 
| 241 # Required by third_party/android_testrunner to call directly 'adb'. | 245 # Required by third_party/android_testrunner to call directly 'adb'. | 
| 242 os.environ['PATH'] += os.pathsep + adb_dir | 246 os.environ['PATH'] += os.pathsep + adb_dir | 
| 243 self._adb = adb_interface.AdbInterface() | 247 self._adb = adb_interface.AdbInterface() | 
| 244 if device: | 248 if device: | 
| 245 self._adb.SetTargetSerial(device) | 249 self._adb.SetTargetSerial(device) | 
| 246 self._device = device | 250 self._device = device | 
| 247 self._logcat = None | 251 self._logcat = None | 
| 248 self.logcat_process = None | 252 self.logcat_process = None | 
| 249 self._logcat_tmpoutfile = None | 253 self._logcat_tmpoutfile = None | 
| 250 self._pushed_files = [] | 254 self._pushed_files = [] | 
| 251 self._device_utc_offset = None | 255 self._device_utc_offset = None | 
| 252 self._potential_push_size = 0 | 256 self._potential_push_size = 0 | 
| 253 self._actual_push_size = 0 | 257 self._actual_push_size = 0 | 
| 254 self._external_storage = '' | 258 self._external_storage = '' | 
| 255 self._util_wrapper = '' | 259 self._util_wrapper = '' | 
| 260 self._api_strict_mode = api_strict_mode | |
| 261 self._system_properties = system_properties.SystemProperties(self.Adb()) | |
| 262 | |
| 263 if not self._api_strict_mode: | |
| 264 logging.warning( | |
| 265 'API STRICT MODE IS DISABLED.\n' | |
| 266 'It should be enabled as soon as possible as it will eventually ' | |
| 267 'become the default.') | |
| 268 | |
| 269 @property | |
| 270 def system_properties(self): | |
| 271 return self._system_properties | |
| 256 | 272 | 
| 257 def _LogShell(self, cmd): | 273 def _LogShell(self, cmd): | 
| 258 """Logs the adb shell command.""" | 274 """Logs the adb shell command.""" | 
| 259 if self._device: | 275 if self._device: | 
| 260 device_repr = self._device[-4:] | 276 device_repr = self._device[-4:] | 
| 261 else: | 277 else: | 
| 262 device_repr = '????' | 278 device_repr = '????' | 
| 263 logging.info('[%s]> %s', device_repr, cmd) | 279 logging.info('[%s]> %s', device_repr, cmd) | 
| 264 | 280 | 
| 265 def Adb(self): | 281 def Adb(self): | 
| 266 """Returns our AdbInterface to avoid us wrapping all its methods.""" | 282 """Returns our AdbInterface to avoid us wrapping all its methods.""" | 
| 283 # TODO(tonyg): Disable this method when in _api_strict_mode. | |
| 267 return self._adb | 284 return self._adb | 
| 268 | 285 | 
| 269 def GetDevice(self): | 286 def GetDevice(self): | 
| 270 """Returns the device serial.""" | 287 """Returns the device serial.""" | 
| 271 return self._device | 288 return self._device | 
| 272 | 289 | 
| 273 def IsOnline(self): | 290 def IsOnline(self): | 
| 274 """Checks whether the device is online. | 291 """Checks whether the device is online. | 
| 275 | 292 | 
| 276 Returns: | 293 Returns: | 
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 Args: | 362 Args: | 
| 346 full_reboot: Whether to fully reboot the device or just restart the shell. | 363 full_reboot: Whether to fully reboot the device or just restart the shell. | 
| 347 """ | 364 """ | 
| 348 # TODO(torne): hive can't reboot the device either way without breaking the | 365 # TODO(torne): hive can't reboot the device either way without breaking the | 
| 349 # connection; work out if we can handle this better | 366 # connection; work out if we can handle this better | 
| 350 if os.environ.get('USING_HIVE'): | 367 if os.environ.get('USING_HIVE'): | 
| 351 logging.warning('Ignoring reboot request as we are on hive') | 368 logging.warning('Ignoring reboot request as we are on hive') | 
| 352 return | 369 return | 
| 353 if full_reboot or not self.IsRootEnabled(): | 370 if full_reboot or not self.IsRootEnabled(): | 
| 354 self._adb.SendCommand('reboot') | 371 self._adb.SendCommand('reboot') | 
| 372 self._system_properties = system_properties.SystemProperties(self.Adb()) | |
| 355 timeout = 300 | 373 timeout = 300 | 
| 356 retries = 1 | 374 retries = 1 | 
| 357 # Wait for the device to disappear. | 375 # Wait for the device to disappear. | 
| 358 while retries < 10 and self.IsOnline(): | 376 while retries < 10 and self.IsOnline(): | 
| 359 time.sleep(1) | 377 time.sleep(1) | 
| 360 retries += 1 | 378 retries += 1 | 
| 361 else: | 379 else: | 
| 362 self.RestartShell() | 380 self.RestartShell() | 
| 363 timeout = 120 | 381 timeout = 120 | 
| 364 # To run tests we need at least the package manager and the sd card (or | 382 # To run tests we need at least the package manager and the sd card (or | 
| 365 # other external storage) to be ready. | 383 # other external storage) to be ready. | 
| 366 self.WaitForDevicePm() | 384 self.WaitForDevicePm() | 
| 367 self.WaitForSdCardReady(timeout) | 385 self.WaitForSdCardReady(timeout) | 
| 368 | 386 | 
| 369 def Shutdown(self): | 387 def Shutdown(self): | 
| 370 """Shuts down the device.""" | 388 """Shuts down the device.""" | 
| 371 self._adb.SendCommand('reboot -p') | 389 self._adb.SendCommand('reboot -p') | 
| 390 self._system_properties = system_properties.SystemProperties(self.Adb()) | |
| 372 | 391 | 
| 373 def Uninstall(self, package): | 392 def Uninstall(self, package): | 
| 374 """Uninstalls the specified package from the device. | 393 """Uninstalls the specified package from the device. | 
| 375 | 394 | 
| 376 Args: | 395 Args: | 
| 377 package: Name of the package to remove. | 396 package: Name of the package to remove. | 
| 378 | 397 | 
| 379 Returns: | 398 Returns: | 
| 380 A status string returned by adb uninstall | 399 A status string returned by adb uninstall | 
| 381 """ | 400 """ | 
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 set. | 548 set. | 
| 530 """ | 549 """ | 
| 531 logging.info('Waiting for system boot completed...') | 550 logging.info('Waiting for system boot completed...') | 
| 532 self._adb.SendCommand('wait-for-device') | 551 self._adb.SendCommand('wait-for-device') | 
| 533 # Now the device is there, but system not boot completed. | 552 # Now the device is there, but system not boot completed. | 
| 534 # Query the sys.boot_completed flag with a basic command | 553 # Query the sys.boot_completed flag with a basic command | 
| 535 boot_completed = False | 554 boot_completed = False | 
| 536 attempts = 0 | 555 attempts = 0 | 
| 537 wait_period = 5 | 556 wait_period = 5 | 
| 538 while not boot_completed and (attempts * wait_period) < wait_time: | 557 while not boot_completed and (attempts * wait_period) < wait_time: | 
| 539 output = self._adb.SendShellCommand('getprop sys.boot_completed', | 558 output = self.system_properties['sys.boot_completed'] | 
| 540 retry_count=1) | |
| 541 output = output.strip() | 559 output = output.strip() | 
| 542 if output == '1': | 560 if output == '1': | 
| 543 boot_completed = True | 561 boot_completed = True | 
| 544 else: | 562 else: | 
| 545 # If 'error: xxx' returned when querying the flag, it means | 563 # If 'error: xxx' returned when querying the flag, it means | 
| 546 # adb server lost the connection to the emulator, so restart the adb | 564 # adb server lost the connection to the emulator, so restart the adb | 
| 547 # server. | 565 # server. | 
| 548 if 'error:' in output: | 566 if 'error:' in output: | 
| 549 self.RestartAdbServer() | 567 self.RestartAdbServer() | 
| 550 time.sleep(wait_period) | 568 time.sleep(wait_period) | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 564 output = self.RunShellCommand('ls ' + external_storage) | 582 output = self.RunShellCommand('ls ' + external_storage) | 
| 565 if output: | 583 if output: | 
| 566 sdcard_ready = True | 584 sdcard_ready = True | 
| 567 else: | 585 else: | 
| 568 time.sleep(wait_period) | 586 time.sleep(wait_period) | 
| 569 attempts += 1 | 587 attempts += 1 | 
| 570 if not sdcard_ready: | 588 if not sdcard_ready: | 
| 571 raise errors.WaitForResponseTimedOutError( | 589 raise errors.WaitForResponseTimedOutError( | 
| 572 'SD card not ready after %s seconds' % timeout_time) | 590 'SD card not ready after %s seconds' % timeout_time) | 
| 573 | 591 | 
| 592 def _CheckCommandIsValid(self, command): | |
| 593 """Raises a ValueError if the command is not valid.""" | |
| 594 | |
| 595 # A dict of commands the user should not run directly and a mapping to the | |
| 596 # API they should use instead. | |
| 597 managed_commands = { | |
| 598 'getprop': 'system_properties[<PROPERTY>]', | |
| 599 'setprop': 'system_properties[<PROPERTY>]', | |
| 
frankf
2013/12/03 00:20:27
Could you add 'su' to this list? People should be
 
tonyg
2013/12/03 01:02:02
Done.
 | |
| 600 } | |
| 601 | |
| 602 base_command = command.split()[0] | |
| 603 if base_command in managed_commands: | |
| 604 error_msg = ('%s cannot be run directly. Instead use: %s' % | |
| 605 (base_command, managed_commands[base_command])) | |
| 606 if self._api_strict_mode: | |
| 607 raise ValueError(error_msg) | |
| 608 else: | |
| 609 logging.warning(error_msg) | |
| 610 | |
| 574 # It is tempting to turn this function into a generator, however this is not | 611 # It is tempting to turn this function into a generator, however this is not | 
| 575 # possible without using a private (local) adb_shell instance (to ensure no | 612 # possible without using a private (local) adb_shell instance (to ensure no | 
| 576 # other command interleaves usage of it), which would defeat the main aim of | 613 # other command interleaves usage of it), which would defeat the main aim of | 
| 577 # being able to reuse the adb shell instance across commands. | 614 # being able to reuse the adb shell instance across commands. | 
| 578 def RunShellCommand(self, command, timeout_time=20, log_result=False): | 615 def RunShellCommand(self, command, timeout_time=20, log_result=False): | 
| 579 """Send a command to the adb shell and return the result. | 616 """Send a command to the adb shell and return the result. | 
| 580 | 617 | 
| 581 Args: | 618 Args: | 
| 582 command: String containing the shell command to send. Must not include | 619 command: String containing the shell command to send. Must not include | 
| 583 the single quotes as we use them to escape the whole command. | 620 the single quotes as we use them to escape the whole command. | 
| 584 timeout_time: Number of seconds to wait for command to respond before | 621 timeout_time: Number of seconds to wait for command to respond before | 
| 585 retrying, used by AdbInterface.SendShellCommand. | 622 retrying, used by AdbInterface.SendShellCommand. | 
| 586 log_result: Boolean to indicate whether we should log the result of the | 623 log_result: Boolean to indicate whether we should log the result of the | 
| 587 shell command. | 624 shell command. | 
| 588 | 625 | 
| 589 Returns: | 626 Returns: | 
| 590 list containing the lines of output received from running the command | 627 list containing the lines of output received from running the command | 
| 591 """ | 628 """ | 
| 629 self._CheckCommandIsValid(command) | |
| 592 self._LogShell(command) | 630 self._LogShell(command) | 
| 593 if "'" in command: logging.warning(command + " contains ' quotes") | 631 if "'" in command: logging.warning(command + " contains ' quotes") | 
| 594 result = self._adb.SendShellCommand( | 632 result = self._adb.SendShellCommand( | 
| 595 "'%s'" % command, timeout_time).splitlines() | 633 "'%s'" % command, timeout_time).splitlines() | 
| 596 if ['error: device not found'] == result: | 634 if ['error: device not found'] == result: | 
| 597 raise errors.DeviceUnresponsiveError('device not found') | 635 raise errors.DeviceUnresponsiveError('device not found') | 
| 598 if log_result: | 636 if log_result: | 
| 599 self._LogShell('\n'.join(result)) | 637 self._LogShell('\n'.join(result)) | 
| 600 return result | 638 return result | 
| 601 | 639 | 
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1096 r'\s*=\s*\w+\s*$', re.MULTILINE) | 1134 r'\s*=\s*\w+\s*$', re.MULTILINE) | 
| 1097 properties = re.sub(re_replace, '', properties) | 1135 properties = re.sub(re_replace, '', properties) | 
| 1098 if enable: | 1136 if enable: | 
| 1099 properties += '\n%s=all\n' % JAVA_ASSERT_PROPERTY | 1137 properties += '\n%s=all\n' % JAVA_ASSERT_PROPERTY | 
| 1100 | 1138 | 
| 1101 file(temp_props_file.name, 'w').write(properties) | 1139 file(temp_props_file.name, 'w').write(properties) | 
| 1102 self._adb.Push(temp_props_file.name, LOCAL_PROPERTIES_PATH) | 1140 self._adb.Push(temp_props_file.name, LOCAL_PROPERTIES_PATH) | 
| 1103 | 1141 | 
| 1104 # Next, check the current runtime value is what we need, and | 1142 # Next, check the current runtime value is what we need, and | 
| 1105 # if not, set it and report that a reboot is required. | 1143 # if not, set it and report that a reboot is required. | 
| 1106 was_set = 'all' in self.RunShellCommand('getprop ' + JAVA_ASSERT_PROPERTY) | 1144 was_set = 'all' in self.system_properties[JAVA_ASSERT_PROPERTY] | 
| 1107 if was_set == enable: | 1145 if was_set == enable: | 
| 1108 return False | 1146 return False | 
| 1109 | 1147 self.system_properties[JAVA_ASSERT_PROPERTY] = enable and 'all' or '' | 
| 1110 self.RunShellCommand('setprop %s "%s"' % (JAVA_ASSERT_PROPERTY, | |
| 1111 enable and 'all' or '')) | |
| 1112 return True | 1148 return True | 
| 1113 | 1149 | 
| 1114 def GetBuildId(self): | 1150 def GetBuildId(self): | 
| 1115 """Returns the build ID of the system (e.g. JRM79C).""" | 1151 """Returns the build ID of the system (e.g. JRM79C).""" | 
| 1116 build_id = self.RunShellCommand('getprop ro.build.id')[0] | 1152 build_id = self.system_properties['ro.build.id'] | 
| 1117 assert build_id | 1153 assert build_id | 
| 1118 return build_id | 1154 return build_id | 
| 1119 | 1155 | 
| 1120 def GetBuildType(self): | 1156 def GetBuildType(self): | 
| 1121 """Returns the build type of the system (e.g. eng).""" | 1157 """Returns the build type of the system (e.g. eng).""" | 
| 1122 build_type = self.RunShellCommand('getprop ro.build.type')[0] | 1158 build_type = self.system_properties['ro.build.type'] | 
| 1123 assert build_type | 1159 assert build_type | 
| 1124 return build_type | 1160 return build_type | 
| 1125 | 1161 | 
| 1126 def GetBuildProduct(self): | 1162 def GetBuildProduct(self): | 
| 1127 """Returns the build product of the device (e.g. maguro).""" | 1163 """Returns the build product of the device (e.g. maguro).""" | 
| 1128 build_product = self.RunShellCommand('getprop ro.build.product')[0] | 1164 build_product = self.system_properties['ro.build.product'] | 
| 1129 assert build_product | 1165 assert build_product | 
| 1130 return build_product | 1166 return build_product | 
| 1131 | 1167 | 
| 1132 def GetProductName(self): | 1168 def GetProductName(self): | 
| 1133 """Returns the product name of the device (e.g. takju).""" | 1169 """Returns the product name of the device (e.g. takju).""" | 
| 1134 name = self.RunShellCommand('getprop ro.product.name')[0] | 1170 name = self.system_properties['ro.product.name'] | 
| 1135 assert name | 1171 assert name | 
| 1136 return name | 1172 return name | 
| 1137 | 1173 | 
| 1138 def GetBuildFingerprint(self): | 1174 def GetBuildFingerprint(self): | 
| 1139 """Returns the build fingerprint of the device.""" | 1175 """Returns the build fingerprint of the device.""" | 
| 1140 build_fingerprint = self.RunShellCommand('getprop ro.build.fingerprint')[0] | 1176 build_fingerprint = self.system_properties['ro.build.fingerprint'] | 
| 1141 assert build_fingerprint | 1177 assert build_fingerprint | 
| 1142 return build_fingerprint | 1178 return build_fingerprint | 
| 1143 | 1179 | 
| 1144 def GetDescription(self): | 1180 def GetDescription(self): | 
| 1145 """Returns the description of the system. | 1181 """Returns the description of the system. | 
| 1146 | 1182 | 
| 1147 For example, "yakju-userdebug 4.1 JRN54F 364167 dev-keys". | 1183 For example, "yakju-userdebug 4.1 JRN54F 364167 dev-keys". | 
| 1148 """ | 1184 """ | 
| 1149 description = self.RunShellCommand('getprop ro.build.description')[0] | 1185 description = self.system_properties['ro.build.description'] | 
| 1150 assert description | 1186 assert description | 
| 1151 return description | 1187 return description | 
| 1152 | 1188 | 
| 1153 def GetProductModel(self): | 1189 def GetProductModel(self): | 
| 1154 """Returns the name of the product model (e.g. "Galaxy Nexus") """ | 1190 """Returns the name of the product model (e.g. "Galaxy Nexus") """ | 
| 1155 model = self.RunShellCommand('getprop ro.product.model')[0] | 1191 model = self.system_properties['ro.product.model'] | 
| 1156 assert model | 1192 assert model | 
| 1157 return model | 1193 return model | 
| 1158 | 1194 | 
| 1159 def GetWifiIP(self): | 1195 def GetWifiIP(self): | 
| 1160 """Returns the wifi IP on the device.""" | 1196 """Returns the wifi IP on the device.""" | 
| 1161 wifi_ip = self.RunShellCommand('getprop dhcp.wlan0.ipaddress')[0] | 1197 wifi_ip = self.system_properties['dhcp.wlan0.ipaddress'] | 
| 1162 # Do not assert here. Devices (e.g. emulators) may not have a WifiIP. | 1198 # Do not assert here. Devices (e.g. emulators) may not have a WifiIP. | 
| 1163 return wifi_ip | 1199 return wifi_ip | 
| 1164 | 1200 | 
| 1165 def GetSubscriberInfo(self): | 1201 def GetSubscriberInfo(self): | 
| 1166 """Returns the device subscriber info (e.g. GSM and device ID) as string.""" | 1202 """Returns the device subscriber info (e.g. GSM and device ID) as string.""" | 
| 1167 iphone_sub = self.RunShellCommand('dumpsys iphonesubinfo') | 1203 iphone_sub = self.RunShellCommand('dumpsys iphonesubinfo') | 
| 1168 assert iphone_sub | 1204 assert iphone_sub | 
| 1169 return '\n'.join(iphone_sub) | 1205 return '\n'.join(iphone_sub) | 
| 1170 | 1206 | 
| 1171 def GetBatteryInfo(self): | 1207 def GetBatteryInfo(self): | 
| 1172 """Returns the device battery info (e.g. status, level, etc) as string.""" | 1208 """Returns the device battery info (e.g. status, level, etc) as string.""" | 
| 1173 battery = self.RunShellCommand('dumpsys battery') | 1209 battery = self.RunShellCommand('dumpsys battery') | 
| 1174 assert battery | 1210 assert battery | 
| 1175 return '\n'.join(battery) | 1211 return '\n'.join(battery) | 
| 1176 | 1212 | 
| 1177 def GetSetupWizardStatus(self): | 1213 def GetSetupWizardStatus(self): | 
| 1178 """Returns the status of the device setup wizard (e.g. DISABLED).""" | 1214 """Returns the status of the device setup wizard (e.g. DISABLED).""" | 
| 1179 status = self.RunShellCommand('getprop ro.setupwizard.mode')[0] | 1215 status = self.system_properties['ro.setupwizard.mode'] | 
| 1180 # On some devices, the status is empty if not otherwise set. In such cases | 1216 # On some devices, the status is empty if not otherwise set. In such cases | 
| 1181 # the caller should expect an empty string to be returned. | 1217 # the caller should expect an empty string to be returned. | 
| 1182 return status | 1218 return status | 
| 1183 | 1219 | 
| 1184 def StartMonitoringLogcat(self, clear=True, logfile=None, filters=None): | 1220 def StartMonitoringLogcat(self, clear=True, logfile=None, filters=None): | 
| 1185 """Starts monitoring the output of logcat, for use with WaitForLogMatch. | 1221 """Starts monitoring the output of logcat, for use with WaitForLogMatch. | 
| 1186 | 1222 | 
| 1187 Args: | 1223 Args: | 
| 1188 clear: If True the existing logcat output will be cleared, to avoiding | 1224 clear: If True the existing logcat output will be cleared, to avoiding | 
| 1189 matching historical output lurking in the log. | 1225 matching historical output lurking in the log. | 
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1713 """ | 1749 """ | 
| 1714 def __init__(self, output): | 1750 def __init__(self, output): | 
| 1715 self._output = output | 1751 self._output = output | 
| 1716 | 1752 | 
| 1717 def write(self, data): | 1753 def write(self, data): | 
| 1718 data = data.replace('\r\r\n', '\n') | 1754 data = data.replace('\r\r\n', '\n') | 
| 1719 self._output.write(data) | 1755 self._output.write(data) | 
| 1720 | 1756 | 
| 1721 def flush(self): | 1757 def flush(self): | 
| 1722 self._output.flush() | 1758 self._output.flush() | 
| OLD | NEW |