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

Side by Side Diff: build/android/pylib/android_commands.py

Issue 10824227: Organize adb install cmds and reboot on failure (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months 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 | Annotate | Revision Log
« no previous file with comments | « build/android/adb_install_content_shell ('k') | build/android/pylib/test_package_apk.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 io_stats_parser
13 import logging 12 import logging
14 import optparse
15 import os 13 import os
16 import pexpect
17 import re 14 import re
18 import shlex 15 import shlex
19 import subprocess 16 import subprocess
20 import sys 17 import sys
21 import tempfile 18 import tempfile
22 import time 19 import time
23 20
21 import pexpect
22 import io_stats_parser
24 23
25 # adb_interface.py is under ../../../third_party/android_testrunner/ 24 # adb_interface.py is under ../../../third_party/android_testrunner/
26 sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..', 25 sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..',
27 '..', '..', 'third_party', 'android_testrunner')) 26 '..', '..', 'third_party', 'android_testrunner'))
28 import adb_interface 27 import adb_interface
29 import cmd_helper 28 import cmd_helper
30 import errors # is under ../../../third_party/android_testrunner/errors.py 29 import errors # is under ../../../third_party/android_testrunner/errors.py
31 30
32 31
33 # Pattern to search for the next whole line of pexpect output and capture it 32 # Pattern to search for the next whole line of pexpect output and capture it
34 # into a match group. We can't use ^ and $ for line start end with pexpect, 33 # into a match group. We can't use ^ and $ for line start end with pexpect,
35 # see http://www.noah.org/python/pexpect/#doc for explanation why. 34 # see http://www.noah.org/python/pexpect/#doc for explanation why.
36 PEXPECT_LINE_RE = re.compile('\n([^\r]*)\r') 35 PEXPECT_LINE_RE = re.compile('\n([^\r]*)\r')
37 36
38 # Set the adb shell prompt to be a unique marker that will [hopefully] not 37 # Set the adb shell prompt to be a unique marker that will [hopefully] not
39 # appear at the start of any line of a command's output. 38 # appear at the start of any line of a command's output.
40 SHELL_PROMPT = '~+~PQ\x17RS~+~' 39 SHELL_PROMPT = '~+~PQ\x17RS~+~'
41 40
42 # This only works for single core devices. 41 # This only works for single core devices.
43 SCALING_GOVERNOR = '/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor' 42 SCALING_GOVERNOR = '/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor'
44 DROP_CACHES = '/proc/sys/vm/drop_caches' 43 DROP_CACHES = '/proc/sys/vm/drop_caches'
45 44
46 # Java properties file 45 # Java properties file
47 LOCAL_PROPERTIES_PATH = '/data/local.prop' 46 LOCAL_PROPERTIES_PATH = '/data/local.prop'
48 47
49 # Property in /data/local.prop that controls Java assertions. 48 # Property in /data/local.prop that controls Java assertions.
50 JAVA_ASSERT_PROPERTY = 'dalvik.vm.enableassertions' 49 JAVA_ASSERT_PROPERTY = 'dalvik.vm.enableassertions'
51 50
52 BOOT_COMPLETE_RE = re.compile( 51 BOOT_COMPLETE_RE = re.compile(
53 'android.intent.action.MEDIA_MOUNTED path: /\w+/sdcard\d?' 52 'android.intent.action.MEDIA_MOUNTED path: /\w+/sdcard\d?'
54 + '|' + 'PowerManagerService(\(\s+\d+\))?: bootCompleted') 53 '|PowerManagerService(\(\s+\d+\))?: bootCompleted')
55 54
56 MEMORY_INFO_RE = re.compile('^(?P<key>\w+):\s+(?P<usage_kb>\d+) kB$') 55 MEMORY_INFO_RE = re.compile('^(?P<key>\w+):\s+(?P<usage_kb>\d+) kB$')
57 NVIDIA_MEMORY_INFO_RE = re.compile('^\s*(?P<user>\S+)\s*(?P<name>\S+)\s*' 56 NVIDIA_MEMORY_INFO_RE = re.compile('^\s*(?P<user>\S+)\s*(?P<name>\S+)\s*'
58 '(?P<pid>\d+)\s*(?P<usage_bytes>\d+)$') 57 '(?P<pid>\d+)\s*(?P<usage_bytes>\d+)$')
59 58
60 # Keycode "enum" suitable for passing to AndroidCommands.SendKey(). 59 # Keycode "enum" suitable for passing to AndroidCommands.SendKey().
61 KEYCODE_HOME = 3 60 KEYCODE_HOME = 3
62 KEYCODE_BACK = 4 61 KEYCODE_BACK = 4
63 KEYCODE_DPAD_UP = 19 62 KEYCODE_DPAD_UP = 19
64 KEYCODE_DPAD_DOWN = 20 63 KEYCODE_DPAD_DOWN = 20
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 Example output: 99 Example output:
101 100
102 * daemon not running. starting it now on port 5037 * 101 * daemon not running. starting it now on port 5037 *
103 * daemon started successfully * 102 * daemon started successfully *
104 List of devices attached 103 List of devices attached
105 027c10494100b4d7 device 104 027c10494100b4d7 device
106 emulator-5554 offline 105 emulator-5554 offline
107 """ 106 """
108 re_device = re.compile('^([a-zA-Z0-9_:.-]+)\tdevice$', re.MULTILINE) 107 re_device = re.compile('^([a-zA-Z0-9_:.-]+)\tdevice$', re.MULTILINE)
109 devices = re_device.findall(cmd_helper.GetCmdOutput(['adb', 'devices'])) 108 devices = re_device.findall(cmd_helper.GetCmdOutput(['adb', 'devices']))
110 preferred_device = os.environ.get("ANDROID_SERIAL") 109 preferred_device = os.environ.get('ANDROID_SERIAL')
111 if preferred_device in devices: 110 if preferred_device in devices:
112 devices.remove(preferred_device) 111 devices.remove(preferred_device)
113 devices.insert(0, preferred_device) 112 devices.insert(0, preferred_device)
114 return devices 113 return devices
115 114
116 115
117 def _GetHostFileInfo(file_name): 116 def _GetHostFileInfo(file_name):
118 """Returns a tuple containing size and modified UTC time for file_name.""" 117 """Returns a tuple containing size and modified UTC time for file_name."""
119 # The time accuracy on device is only to minute level, remove the second and 118 # The time accuracy on device is only to minute level, remove the second and
120 # microsecond from host results. 119 # microsecond from host results.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 filename = filename[len(path_dir)+1:] 188 filename = filename[len(path_dir)+1:]
190 lastmod = datetime.datetime.strptime( 189 lastmod = datetime.datetime.strptime(
191 file_match.group('date') + ' ' + file_match.group('time')[:5], 190 file_match.group('date') + ' ' + file_match.group('time')[:5],
192 '%Y-%m-%d %H:%M') 191 '%Y-%m-%d %H:%M')
193 if not utc_offset and 'timezone' in re_file.groupindex: 192 if not utc_offset and 'timezone' in re_file.groupindex:
194 utc_offset = file_match.group('timezone') 193 utc_offset = file_match.group('timezone')
195 if isinstance(utc_offset, str) and len(utc_offset) == 5: 194 if isinstance(utc_offset, str) and len(utc_offset) == 5:
196 utc_delta = datetime.timedelta(hours=int(utc_offset[1:3]), 195 utc_delta = datetime.timedelta(hours=int(utc_offset[1:3]),
197 minutes=int(utc_offset[3:5])) 196 minutes=int(utc_offset[3:5]))
198 if utc_offset[0:1] == '-': 197 if utc_offset[0:1] == '-':
199 utc_delta = -utc_delta; 198 utc_delta = -utc_delta
200 lastmod -= utc_delta 199 lastmod -= utc_delta
201 files[filename] = (int(file_match.group('size')), lastmod) 200 files[filename] = (int(file_match.group('size')), lastmod)
202 return files 201 return files
203 202
204 203
205 def GetLogTimestamp(log_line, year): 204 def GetLogTimestamp(log_line, year):
206 """Returns the timestamp of the given |log_line| in the given year.""" 205 """Returns the timestamp of the given |log_line| in the given year."""
207 try: 206 try:
208 return datetime.datetime.strptime('%s-%s' % (year, log_line[:18]), 207 return datetime.datetime.strptime('%s-%s' % (year, log_line[:18]),
209 '%Y-%m-%d %H:%M:%S.%f') 208 '%Y-%m-%d %H:%M:%S.%f')
(...skipping 24 matching lines...) Expand all
234 233
235 def Adb(self): 234 def Adb(self):
236 """Returns our AdbInterface to avoid us wrapping all its methods.""" 235 """Returns our AdbInterface to avoid us wrapping all its methods."""
237 return self._adb 236 return self._adb
238 237
239 def IsRootEnabled(self): 238 def IsRootEnabled(self):
240 """Returns whether or not _adb.EnabledAdbRoot() has succeeded.""" 239 """Returns whether or not _adb.EnabledAdbRoot() has succeeded."""
241 return self._root_enabled 240 return self._root_enabled
242 241
243 def GetDeviceYear(self): 242 def GetDeviceYear(self):
244 """Returns the year information of the date on device""" 243 """Returns the year information of the date on device."""
245 return self.RunShellCommand('date +%Y')[0] 244 return self.RunShellCommand('date +%Y')[0]
246 245
247 def WaitForDevicePm(self): 246 def WaitForDevicePm(self):
248 """Blocks until the device's package manager is available. 247 """Blocks until the device's package manager is available.
249 248
250 To workaround http://b/5201039, we restart the shell and retry if the 249 To workaround http://b/5201039, we restart the shell and retry if the
251 package manager isn't back after 120 seconds. 250 package manager isn't back after 120 seconds.
252 251
253 Raises: 252 Raises:
254 errors.WaitForResponseTimedOutError after max retries reached. 253 errors.WaitForResponseTimedOutError after max retries reached.
255 """ 254 """
256 last_err = None 255 last_err = None
257 retries = 3 256 retries = 3
258 while retries: 257 while retries:
259 try: 258 try:
260 self._adb.WaitForDevicePm() 259 self._adb.WaitForDevicePm()
261 return # Success 260 return # Success
262 except errors.WaitForResponseTimedOutError as e: 261 except errors.WaitForResponseTimedOutError as e:
263 last_err = e 262 last_err = e
264 logging.warning('Restarting and retrying after timeout: %s' % str(e)) 263 logging.warning('Restarting and retrying after timeout: %s', e)
265 retries -= 1 264 retries -= 1
266 self.RestartShell() 265 self.RestartShell()
267 raise last_err # Only reached after max retries, re-raise the last error. 266 raise last_err # Only reached after max retries, re-raise the last error.
268 267
269 def SynchronizeDateTime(self): 268 def SynchronizeDateTime(self):
270 """Synchronize date/time between host and device.""" 269 """Synchronize date/time between host and device."""
271 self._adb.SendShellCommand('date -u %f' % time.time()) 270 self._adb.SendShellCommand('date -u %f' % time.time())
272 271
273 def RestartShell(self): 272 def RestartShell(self):
274 """Restarts the shell on the device. Does not block for it to return.""" 273 """Restarts the shell on the device. Does not block for it to return."""
275 self.RunShellCommand('stop') 274 self.RunShellCommand('stop')
276 self.RunShellCommand('start') 275 self.RunShellCommand('start')
277 276
278 def Reboot(self, full_reboot=True): 277 def Reboot(self, full_reboot=True):
279 """Reboots the device and waits for the package manager to return. 278 """Reboots the device and waits for the package manager to return.
280 279
281 Args: 280 Args:
282 full_reboot: Whether to fully reboot the device or just restart the shell. 281 full_reboot: Whether to fully reboot the device or just restart the shell.
283 """ 282 """
284 # TODO(torne): hive can't reboot the device either way without breaking the 283 # TODO(torne): hive can't reboot the device either way without breaking the
285 # connection; work out if we can handle this better 284 # connection; work out if we can handle this better
286 if os.environ.get('USING_HIVE'): 285 if os.environ.get('USING_HIVE'):
287 logging.warning('Ignoring reboot request as we are on hive') 286 logging.warning('Ignoring reboot request as we are on hive')
288 return 287 return
289 if full_reboot: 288 if full_reboot or not self.IsRootEnabled():
290 self._adb.SendCommand('reboot') 289 self._adb.SendCommand('reboot')
290 timeout = 300
291 else: 291 else:
292 self.RestartShell() 292 self.RestartShell()
293 timeout = 120
293 self.WaitForDevicePm() 294 self.WaitForDevicePm()
294 self.StartMonitoringLogcat(timeout=120) 295 self.StartMonitoringLogcat(timeout=timeout)
295 self.WaitForLogMatch(BOOT_COMPLETE_RE, None) 296 self.WaitForLogMatch(BOOT_COMPLETE_RE, None)
296 297
297 def Uninstall(self, package): 298 def Uninstall(self, package):
298 """Uninstalls the specified package from the device. 299 """Uninstalls the specified package from the device.
299 300
300 Args: 301 Args:
301 package: Name of the package to remove. 302 package: Name of the package to remove.
302 303
303 Returns: 304 Returns:
304 A status string returned by adb uninstall 305 A status string returned by adb uninstall
305 """ 306 """
306 uninstall_command = 'uninstall %s' % package 307 uninstall_command = 'uninstall %s' % package
307 308
308 logging.info('>>> $' + uninstall_command) 309 logging.info('>>> $' + uninstall_command)
309 return self._adb.SendCommand(uninstall_command, timeout_time=60) 310 return self._adb.SendCommand(uninstall_command, timeout_time=60)
310 311
311 def Install(self, package_file_path): 312 def Install(self, package_file_path, reinstall=False):
312 """Installs the specified package to the device. 313 """Installs the specified package to the device.
313 314
314 Args: 315 Args:
315 package_file_path: Path to .apk file to install. 316 package_file_path: Path to .apk file to install.
317 reinstall: Whether to reinstall over existing package
316 318
317 Returns: 319 Returns:
318 A status string returned by adb install 320 A status string returned by adb install
319 """ 321 """
320 assert os.path.isfile(package_file_path) 322 assert os.path.isfile(package_file_path)
321 323
322 install_command = 'install %s' % package_file_path 324 if reinstall:
325 install_cmd = 'install -r %s'
326 else:
327 install_cmd = 'install %s'
323 328
324 logging.info('>>> $' + install_command) 329 return self._adb.SendCommand(install_cmd % package_file_path,
325 return self._adb.SendCommand(install_command, timeout_time=2*60) 330 timeout_time=2*60, retry_count=0)
331
332 def ManagedInstall(self, apk_path, keep_data, package_name=None,
333 reboots_on_failure=2):
334 """Installs specified package and reboots device on timeouts.
335
336 Args:
337 apk_path: Path to .apk file to install.
338 keep_data: Whether to keep data if package already exists
339 package_name: Package name (only needed if keep_data=False)
340 reboots_on_failure: number of time to reboot if package manager is frozen.
341
342 Returns:
343 A status string returned by adb install
344 """
345 reboots_left = reboots_on_failure
346 while True:
347 try:
348 if not keep_data:
349 self.Uninstall(package_name)
350 install_status = self.Install(apk_path, keep_data)
351 if 'Success' in install_status:
352 return install_status
353 except errors.WaitForResponseTimedOutError:
354 logging.info('Timout on installing %s' % apk_path)
355
356 if reboots_left <= 0:
357 raise Exception('Install failure')
358
359 # Force a hard reboot on last attempt
360 self.Reboot(full_reboot=(reboots_left == 1))
361 reboots_left -= 1
326 362
327 def MakeSystemFolderWritable(self): 363 def MakeSystemFolderWritable(self):
328 """Remounts the /system folder rw. """ 364 """Remounts the /system folder rw."""
329 out = self._adb.SendCommand('remount') 365 out = self._adb.SendCommand('remount')
330 if out.strip() != 'remount succeeded': 366 if out.strip() != 'remount succeeded':
331 raise errors.MsgException('Remount failed: %s' % out) 367 raise errors.MsgException('Remount failed: %s' % out)
332 368
333 def RestartAdbServer(self): 369 def RestartAdbServer(self):
334 """Restart the adb server.""" 370 """Restart the adb server."""
335 self.KillAdbServer() 371 self.KillAdbServer()
336 self.StartAdbServer() 372 self.StartAdbServer()
337 373
338 def KillAdbServer(self): 374 def KillAdbServer(self):
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 'sys.boot_completed flag was not set after %s seconds' % wait_time) 417 'sys.boot_completed flag was not set after %s seconds' % wait_time)
382 418
383 def WaitForSdCardReady(self, timeout_time): 419 def WaitForSdCardReady(self, timeout_time):
384 """Wait for the SD card ready before pushing data into it.""" 420 """Wait for the SD card ready before pushing data into it."""
385 logging.info('Waiting for SD card ready...') 421 logging.info('Waiting for SD card ready...')
386 sdcard_ready = False 422 sdcard_ready = False
387 attempts = 0 423 attempts = 0
388 wait_period = 5 424 wait_period = 5
389 while not sdcard_ready and attempts * wait_period < timeout_time: 425 while not sdcard_ready and attempts * wait_period < timeout_time:
390 output = self.RunShellCommand('ls /sdcard/') 426 output = self.RunShellCommand('ls /sdcard/')
391 if len(output) > 0: 427 if output:
392 sdcard_ready = True 428 sdcard_ready = True
393 else: 429 else:
394 time.sleep(wait_period) 430 time.sleep(wait_period)
395 attempts += 1 431 attempts += 1
396 if not sdcard_ready: 432 if not sdcard_ready:
397 raise errors.WaitForResponseTimedOutError( 433 raise errors.WaitForResponseTimedOutError(
398 'SD card not ready after %s seconds' % timeout_time) 434 'SD card not ready after %s seconds' % timeout_time)
399 435
400 # It is tempting to turn this function into a generator, however this is not 436 # It is tempting to turn this function into a generator, however this is not
401 # possible without using a private (local) adb_shell instance (to ensure no 437 # possible without using a private (local) adb_shell instance (to ensure no
402 # other command interleaves usage of it), which would defeat the main aim of 438 # other command interleaves usage of it), which would defeat the main aim of
403 # being able to reuse the adb shell instance across commands. 439 # being able to reuse the adb shell instance across commands.
404 def RunShellCommand(self, command, timeout_time=20, log_result=True): 440 def RunShellCommand(self, command, timeout_time=20, log_result=True):
405 """Send a command to the adb shell and return the result. 441 """Send a command to the adb shell and return the result.
406 442
407 Args: 443 Args:
408 command: String containing the shell command to send. Must not include 444 command: String containing the shell command to send. Must not include
409 the single quotes as we use them to escape the whole command. 445 the single quotes as we use them to escape the whole command.
410 timeout_time: Number of seconds to wait for command to respond before 446 timeout_time: Number of seconds to wait for command to respond before
411 retrying, used by AdbInterface.SendShellCommand. 447 retrying, used by AdbInterface.SendShellCommand.
412 log_result: Boolean to indicate whether we should log the result of the 448 log_result: Boolean to indicate whether we should log the result of the
413 shell command. 449 shell command.
414 450
415 Returns: 451 Returns:
416 list containing the lines of output received from running the command 452 list containing the lines of output received from running the command
417 """ 453 """
418 logging.info('>>> $' + command) 454 logging.info('>>> $' + command)
419 if "'" in command: logging.warning(command + " contains ' quotes") 455 if "'" in command: logging.warning(command + " contains ' quotes")
420 result = self._adb.SendShellCommand("'%s'" % command, 456 result = self._adb.SendShellCommand(
421 timeout_time).splitlines() 457 "'%s'" % command, timeout_time).splitlines()
458 if ['error: device not found'] == result:
459 raise errors.DeviceUnresponsiveError('device not found')
422 if log_result: 460 if log_result:
423 logging.info('\n>>> '.join(result)) 461 logging.info('\n>>> '.join(result))
424 return result 462 return result
425 463
426 def KillAll(self, process): 464 def KillAll(self, process):
427 """Android version of killall, connected via adb. 465 """Android version of killall, connected via adb.
428 466
429 Args: 467 Args:
430 process: name of the process to kill off 468 process: name of the process to kill off
431 469
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 elif isinstance(value, int): 511 elif isinstance(value, int):
474 cmd += ' --ei' 512 cmd += ' --ei'
475 else: 513 else:
476 raise NotImplementedError( 514 raise NotImplementedError(
477 'Need to teach StartActivity how to pass %s extras' % type(value)) 515 'Need to teach StartActivity how to pass %s extras' % type(value))
478 cmd += ' %s %s' % (key, value) 516 cmd += ' %s %s' % (key, value)
479 if trace_file_name: 517 if trace_file_name:
480 cmd += ' --start-profiler ' + trace_file_name 518 cmd += ' --start-profiler ' + trace_file_name
481 self.RunShellCommand(cmd) 519 self.RunShellCommand(cmd)
482 520
483
484 def CloseApplication(self, package): 521 def CloseApplication(self, package):
485 """Attempt to close down the application, using increasing violence. 522 """Attempt to close down the application, using increasing violence.
486 523
487 Args: 524 Args:
488 package: Name of the process to kill off, e.g. 525 package: Name of the process to kill off, e.g.
489 com.google.android.apps.chrome 526 com.google.android.apps.chrome
490 """ 527 """
491 self.RunShellCommand('am force-stop ' + package) 528 self.RunShellCommand('am force-stop ' + package)
492 529
493 def ClearApplicationState(self, package): 530 def ClearApplicationState(self, package):
(...skipping 28 matching lines...) Expand all
522 local_contents = ListHostPathContents(local_path) 559 local_contents = ListHostPathContents(local_path)
523 device_contents = self.ListPathContents(device_path) 560 device_contents = self.ListPathContents(device_path)
524 # Only compare the size and timestamp if only copying a file because 561 # Only compare the size and timestamp if only copying a file because
525 # the filename on device can be renamed. 562 # the filename on device can be renamed.
526 if os.path.isfile(local_path): 563 if os.path.isfile(local_path):
527 assert len(local_contents) == 1 564 assert len(local_contents) == 1
528 is_equal = local_contents.values() == device_contents.values() 565 is_equal = local_contents.values() == device_contents.values()
529 else: 566 else:
530 is_equal = local_contents == device_contents 567 is_equal = local_contents == device_contents
531 if is_equal: 568 if is_equal:
532 logging.info('%s is up-to-date. Skipping file push.' % device_path) 569 logging.info('%s is up-to-date. Skipping file push.', device_path)
533 return 570 return
534 571
535 # They don't match, so remove everything first and then create it. 572 # They don't match, so remove everything first and then create it.
536 if os.path.isdir(local_path): 573 if os.path.isdir(local_path):
537 self.RunShellCommand('rm -r %s' % device_path, timeout_time=2*60) 574 self.RunShellCommand('rm -r %s' % device_path, timeout_time=2*60)
538 self.RunShellCommand('mkdir -p %s' % device_path) 575 self.RunShellCommand('mkdir -p %s' % device_path)
539 576
540 # NOTE: We can't use adb_interface.Push() because it hardcodes a timeout of 577 # NOTE: We can't use adb_interface.Push() because it hardcodes a timeout of
541 # 60 seconds which isn't sufficient for a lot of users of this method. 578 # 60 seconds which isn't sufficient for a lot of users of this method.
542 push_command = 'push %s %s' % (local_path, device_path) 579 push_command = 'push %s %s' % (local_path, device_path)
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 675
639 self.RunShellCommand('setprop %s "%s"' % (JAVA_ASSERT_PROPERTY, 676 self.RunShellCommand('setprop %s "%s"' % (JAVA_ASSERT_PROPERTY,
640 enable and 'all' or '')) 677 enable and 'all' or ''))
641 return True 678 return True
642 679
643 def DropRamCaches(self): 680 def DropRamCaches(self):
644 """Drops the filesystem ram caches for performance testing.""" 681 """Drops the filesystem ram caches for performance testing."""
645 self.RunShellCommand('echo 3 > ' + DROP_CACHES) 682 self.RunShellCommand('echo 3 > ' + DROP_CACHES)
646 683
647 def StartMonitoringLogcat(self, clear=True, timeout=10, logfile=None, 684 def StartMonitoringLogcat(self, clear=True, timeout=10, logfile=None,
648 filters=[]): 685 filters=None):
649 """Starts monitoring the output of logcat, for use with WaitForLogMatch. 686 """Starts monitoring the output of logcat, for use with WaitForLogMatch.
650 687
651 Args: 688 Args:
652 clear: If True the existing logcat output will be cleared, to avoiding 689 clear: If True the existing logcat output will be cleared, to avoiding
653 matching historical output lurking in the log. 690 matching historical output lurking in the log.
654 timeout: How long WaitForLogMatch will wait for the given match 691 timeout: How long WaitForLogMatch will wait for the given match
655 filters: A list of logcat filters to be used. 692 filters: A list of logcat filters to be used.
656 """ 693 """
657 if clear: 694 if clear:
658 self.RunShellCommand('logcat -c') 695 self.RunShellCommand('logcat -c')
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 786
750 Returns: 787 Returns:
751 The logcat output as a string or an empty string if logcat was not 788 The logcat output as a string or an empty string if logcat was not
752 being recorded at the time. 789 being recorded at the time.
753 """ 790 """
754 if not self.logcat_process: 791 if not self.logcat_process:
755 return '' 792 return ''
756 # Cannot evaluate directly as 0 is a possible value. 793 # Cannot evaluate directly as 0 is a possible value.
757 # Better to read the self.logcat_process.stdout before killing it, 794 # Better to read the self.logcat_process.stdout before killing it,
758 # Otherwise the communicate may return incomplete output due to pipe break. 795 # Otherwise the communicate may return incomplete output due to pipe break.
759 if self.logcat_process.poll() == None: 796 if self.logcat_process.poll() is None:
760 self.logcat_process.kill() 797 self.logcat_process.kill()
761 (output, _) = self.logcat_process.communicate() 798 (output, _) = self.logcat_process.communicate()
762 self.logcat_process = None 799 self.logcat_process = None
763 return output 800 return output
764 801
765 def SearchLogcatRecord(self, record, message, thread_id=None, proc_id=None, 802 def SearchLogcatRecord(self, record, message, thread_id=None, proc_id=None,
766 log_level=None, component=None): 803 log_level=None, component=None):
767 """Searches the specified logcat output and returns results. 804 """Searches the specified logcat output and returns results.
768 805
769 This method searches through the logcat output specified by record for a 806 This method searches through the logcat output specified by record for a
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 usage_bytes = int(match.group('usage_bytes')) 925 usage_bytes = int(match.group('usage_bytes'))
889 usage_dict['Nvidia'] = int(round(usage_bytes / 1000.0)) # kB 926 usage_dict['Nvidia'] = int(round(usage_bytes / 1000.0)) # kB
890 break 927 break
891 928
892 return (usage_dict, smaps) 929 return (usage_dict, smaps)
893 930
894 def GetMemoryUsageForPackage(self, package): 931 def GetMemoryUsageForPackage(self, package):
895 """Returns the memory usage for all processes whose name contains |pacakge|. 932 """Returns the memory usage for all processes whose name contains |pacakge|.
896 933
897 Args: 934 Args:
898 name: A string holding process name to lookup pid list for. 935 package: A string holding process name to lookup pid list for.
899 936
900 Returns: 937 Returns:
901 A tuple containg: 938 A tuple containg:
902 [0]: Dict of {metric:usage_kb}, summed over all pids associated with 939 [0]: Dict of {metric:usage_kb}, summed over all pids associated with
903 |name|. 940 |name|.
904 The metric keys which may be included are: Size, Rss, Pss, Shared_Clean, 941 The metric keys which may be included are: Size, Rss, Pss, Shared_Clean,
905 Shared_Dirty, Private_Clean, Private_Dirty, Referenced, Swap, 942 Shared_Dirty, Private_Clean, Private_Dirty, Referenced, Swap,
906 KernelPageSize, MMUPageSize, Nvidia (tablet only). 943 KernelPageSize, MMUPageSize, Nvidia (tablet only).
907 [1]: a list with detailed /proc/[PID]/smaps information. 944 [1]: a list with detailed /proc/[PID]/smaps information.
908 """ 945 """
909 usage_dict = collections.defaultdict(int) 946 usage_dict = collections.defaultdict(int)
910 pid_list = self.ExtractPid(package) 947 pid_list = self.ExtractPid(package)
911 smaps = collections.defaultdict(dict) 948 smaps = collections.defaultdict(dict)
912 949
913 for pid in pid_list: 950 for pid in pid_list:
914 usage_dict_per_pid, smaps_per_pid = self.GetMemoryUsageForPid(pid) 951 usage_dict_per_pid, smaps_per_pid = self.GetMemoryUsageForPid(pid)
915 smaps[pid] = smaps_per_pid 952 smaps[pid] = smaps_per_pid
916 for (key, value) in usage_dict_per_pid.items(): 953 for (key, value) in usage_dict_per_pid.items():
917 usage_dict[key] += value 954 usage_dict[key] += value
918 955
919 return usage_dict, smaps 956 return usage_dict, smaps
920 957
921 def ProcessesUsingDevicePort(self, device_port): 958 def ProcessesUsingDevicePort(self, device_port):
922 """Lists the processes using the specified device port on loopback 959 """Lists processes using the specified device port on loopback interface.
923 interface.
924 960
925 Args: 961 Args:
926 device_port: Port on device we want to check. 962 device_port: Port on device we want to check.
927 963
928 Returns: 964 Returns:
929 A list of (pid, process_name) tuples using the specified port. 965 A list of (pid, process_name) tuples using the specified port.
930 """ 966 """
931 tcp_results = self.RunShellCommand('cat /proc/net/tcp', log_result=False) 967 tcp_results = self.RunShellCommand('cat /proc/net/tcp', log_result=False)
932 tcp_address = "0100007F:%04X" % device_port 968 tcp_address = '0100007F:%04X' % device_port
933 pids = [] 969 pids = []
934 for single_connect in tcp_results: 970 for single_connect in tcp_results:
935 connect_results = single_connect.split() 971 connect_results = single_connect.split()
936 # Column 1 is the TCP port, and Column 9 is the inode of the socket 972 # Column 1 is the TCP port, and Column 9 is the inode of the socket
937 if connect_results[1] == tcp_address: 973 if connect_results[1] == tcp_address:
938 socket_inode = connect_results[9] 974 socket_inode = connect_results[9]
939 socket_name = 'socket:[%s]' % socket_inode 975 socket_name = 'socket:[%s]' % socket_inode
940 lsof_results = self.RunShellCommand('lsof', log_result=False) 976 lsof_results = self.RunShellCommand('lsof', log_result=False)
941 for single_process in lsof_results: 977 for single_process in lsof_results:
942 process_results = single_process.split() 978 process_results = single_process.split()
943 # Ignore the line if it has less than nine columns in it, which may 979 # Ignore the line if it has less than nine columns in it, which may
944 # be the case when a process stops while lsof is executing. 980 # be the case when a process stops while lsof is executing.
945 if len(process_results) <= 8: 981 if len(process_results) <= 8:
946 continue 982 continue
947 # Column 0 is the executable name 983 # Column 0 is the executable name
948 # Column 1 is the pid 984 # Column 1 is the pid
949 # Column 8 is the Inode in use 985 # Column 8 is the Inode in use
950 if process_results[8] == socket_name: 986 if process_results[8] == socket_name:
951 pids.append( (int(process_results[1]), process_results[0]) ) 987 pids.append((int(process_results[1]), process_results[0]))
952 break 988 break
953 logging.info('PidsUsingDevicePort: %s', pids) 989 logging.info('PidsUsingDevicePort: %s', pids)
954 return pids 990 return pids
OLDNEW
« no previous file with comments | « build/android/adb_install_content_shell ('k') | build/android/pylib/test_package_apk.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698