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

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

Issue 1077173002: [Android] Tune DeviceUtils commands that are prone to large outputs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 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
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=unused-argument 9 # pylint: disable=unused-argument
10 10
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 if not output: 567 if not output:
568 return '' 568 return ''
569 elif len(output) == 1: 569 elif len(output) == 1:
570 return output[0] 570 return output[0]
571 else: 571 else:
572 msg = 'one line of output was expected, but got: %s' 572 msg = 'one line of output was expected, but got: %s'
573 raise device_errors.CommandFailedError(msg % output, str(self)) 573 raise device_errors.CommandFailedError(msg % output, str(self))
574 else: 574 else:
575 return output 575 return output
576 576
577 def _RunPipedShellCommand(self, script, **kwargs):
578 PIPESTATUS_LEADER = 'PIPESTATUS: '
579
580 script += '; echo "%s${PIPESTATUS[@]}"' % PIPESTATUS_LEADER
581 kwargs['check_return'] = True
582 output = self.RunShellCommand(script, **kwargs)
583 pipestatus_line = output[-1]
584
585 if not pipestatus_line.startswith(PIPESTATUS_LEADER):
586 logging.error('Pipe exit statuses of shell script missing.')
587 raise device_errors.AdbShellCommandFailedError(
588 script, output, status=None,
589 device_serial=self.adb.GetDeviceSerial())
590
591 output = output[:-1]
592 statuses = [
593 int(s) for s in pipestatus_line[len(PIPESTATUS_LEADER):].split()]
594 if any(statuses):
595 raise device_errors.AdbShellCommandFailedError(
596 script, output, status=statuses,
597 device_serial=self.adb.GetDeviceSerial())
598 return output
599
577 @decorators.WithTimeoutAndRetriesFromInstance() 600 @decorators.WithTimeoutAndRetriesFromInstance()
578 def KillAll(self, process_name, signum=9, as_root=False, blocking=False, 601 def KillAll(self, process_name, signum=9, as_root=False, blocking=False,
579 timeout=None, retries=None): 602 timeout=None, retries=None):
580 """Kill all processes with the given name on the device. 603 """Kill all processes with the given name on the device.
581 604
582 Args: 605 Args:
583 process_name: A string containing the name of the process to kill. 606 process_name: A string containing the name of the process to kill.
584 signum: An integer containing the signal number to send to kill. Defaults 607 signum: An integer containing the signal number to send to kill. Defaults
585 to 9 (SIGKILL). 608 to 9 (SIGKILL).
586 as_root: A boolean indicating whether the kill should be executed with 609 as_root: A boolean indicating whether the kill should be executed with
587 root privileges. 610 root privileges.
588 blocking: A boolean indicating whether we should wait until all processes 611 blocking: A boolean indicating whether we should wait until all processes
589 with the given |process_name| are dead. 612 with the given |process_name| are dead.
590 timeout: timeout in seconds 613 timeout: timeout in seconds
591 retries: number of retries 614 retries: number of retries
592 615
593 Raises: 616 Raises:
594 CommandFailedError if no process was killed. 617 CommandFailedError if no process was killed.
595 CommandTimeoutError on timeout. 618 CommandTimeoutError on timeout.
596 DeviceUnreachableError on missing device. 619 DeviceUnreachableError on missing device.
597 """ 620 """
598 pids = self._GetPidsImpl(process_name) 621 pids = self.GetPids(process_name)
599 if not pids: 622 if not pids:
600 raise device_errors.CommandFailedError( 623 raise device_errors.CommandFailedError(
601 'No process "%s"' % process_name, str(self)) 624 'No process "%s"' % process_name, str(self))
602 625
603 cmd = ['kill', '-%d' % signum] + pids.values() 626 cmd = ['kill', '-%d' % signum] + pids.values()
604 self.RunShellCommand(cmd, as_root=as_root, check_return=True) 627 self.RunShellCommand(cmd, as_root=as_root, check_return=True)
605 628
606 if blocking: 629 if blocking:
607 wait_period = 0.1 630 wait_period = 0.1
608 while self._GetPidsImpl(process_name): 631 while self.GetPids(process_name):
609 time.sleep(wait_period) 632 time.sleep(wait_period)
610 633
611 return len(pids) 634 return len(pids)
612 635
613 @decorators.WithTimeoutAndRetriesFromInstance() 636 @decorators.WithTimeoutAndRetriesFromInstance()
614 def StartActivity(self, intent_obj, blocking=False, trace_file_name=None, 637 def StartActivity(self, intent_obj, blocking=False, trace_file_name=None,
615 force_stop=False, timeout=None, retries=None): 638 force_stop=False, timeout=None, retries=None):
616 """Start package's activity on the device. 639 """Start package's activity on the device.
617 640
618 Args: 641 Args:
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 ls_out = self.RunShellCommand(['ls', '-l', device_path], as_root=as_root, 1036 ls_out = self.RunShellCommand(['ls', '-l', device_path], as_root=as_root,
1014 check_return=True) 1037 check_return=True)
1015 for line in ls_out: 1038 for line in ls_out:
1016 m = self._LS_RE.match(line) 1039 m = self._LS_RE.match(line)
1017 if m and m.group('name') == posixpath.basename(device_path): 1040 if m and m.group('name') == posixpath.basename(device_path):
1018 size = int(m.group('size')) 1041 size = int(m.group('size'))
1019 break 1042 break
1020 else: 1043 else:
1021 logging.warning('Could not determine size of %s.', device_path) 1044 logging.warning('Could not determine size of %s.', device_path)
1022 1045
1023 if size is None or size <= self._MAX_ADB_OUTPUT_LENGTH: 1046 if 0 < size <= self._MAX_ADB_OUTPUT_LENGTH:
1024 return _JoinLines(self.RunShellCommand( 1047 return _JoinLines(self.RunShellCommand(
1025 ['cat', device_path], as_root=as_root, check_return=True)) 1048 ['cat', device_path], as_root=as_root, check_return=True))
1026 elif as_root and self.NeedsSU(): 1049 elif as_root and self.NeedsSU():
1027 with device_temp_file.DeviceTempFile(self.adb) as device_temp: 1050 with device_temp_file.DeviceTempFile(self.adb) as device_temp:
1028 self.RunShellCommand(['cp', device_path, device_temp.name], 1051 self.RunShellCommand(['cp', device_path, device_temp.name],
1029 as_root=True, check_return=True) 1052 as_root=True, check_return=True)
1030 return self._ReadFileWithPull(device_temp.name) 1053 return self._ReadFileWithPull(device_temp.name)
1031 else: 1054 else:
1032 return self._ReadFileWithPull(device_path) 1055 return self._ReadFileWithPull(device_path)
1033 1056
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
1348 retries: number of retries 1371 retries: number of retries
1349 1372
1350 Returns: 1373 Returns:
1351 A dict mapping process name to PID for each process that contained the 1374 A dict mapping process name to PID for each process that contained the
1352 provided |process_name|. 1375 provided |process_name|.
1353 1376
1354 Raises: 1377 Raises:
1355 CommandTimeoutError on timeout. 1378 CommandTimeoutError on timeout.
1356 DeviceUnreachableError on missing device. 1379 DeviceUnreachableError on missing device.
1357 """ 1380 """
1358 return self._GetPidsImpl(process_name) 1381 procs_pids = {}
1382 try:
1383 ps_output = self._RunPipedShellCommand(
1384 cmd_helper.SingleQuote('ps | grep -F %s' % process_name))
perezju 2015/04/15 09:48:43 Oh, no, this is wrong, I think. It should be: ps_
jbudorick 2015/04/15 13:43:15 Done.
1385 except device_errors.AdbShellCommandFailedError as e:
1386 if e.status and isinstance(e.status, list) and not e.status[0]:
1387 # If ps succeeded but grep failed, there were no processes with the
1388 # given name.
1389 return procs_pids
1390 else:
1391 raise
1359 1392
1360 def _GetPidsImpl(self, process_name): 1393 for line in ps_output:
1361 procs_pids = {}
1362 for line in self.RunShellCommand('ps', check_return=True):
1363 try: 1394 try:
1364 ps_data = line.split() 1395 ps_data = line.split()
1365 if process_name in ps_data[-1]: 1396 if process_name in ps_data[-1]:
1366 procs_pids[ps_data[-1]] = ps_data[1] 1397 procs_pids[ps_data[-1]] = ps_data[1]
1367 except IndexError: 1398 except IndexError:
1368 pass 1399 pass
1369 return procs_pids 1400 return procs_pids
1370 1401
1371 @decorators.WithTimeoutAndRetriesFromInstance() 1402 @decorators.WithTimeoutAndRetriesFromInstance()
1372 def TakeScreenshot(self, host_path=None, timeout=None, retries=None): 1403 def TakeScreenshot(self, host_path=None, timeout=None, retries=None):
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1424 except device_errors.CommandFailedError: 1455 except device_errors.CommandFailedError:
1425 logging.exception('Error getting memory usage from status') 1456 logging.exception('Error getting memory usage from status')
1426 1457
1427 return result 1458 return result
1428 1459
1429 def _GetMemoryUsageForPidFromSmaps(self, pid): 1460 def _GetMemoryUsageForPidFromSmaps(self, pid):
1430 SMAPS_COLUMNS = ( 1461 SMAPS_COLUMNS = (
1431 'Size', 'Rss', 'Pss', 'Shared_Clean', 'Shared_Dirty', 'Private_Clean', 1462 'Size', 'Rss', 'Pss', 'Shared_Clean', 'Shared_Dirty', 'Private_Clean',
1432 'Private_Dirty') 1463 'Private_Dirty')
1433 1464
1434 showmap_out = self.RunShellCommand( 1465 showmap_out = self._RunPipedShellCommand(
1435 ['showmap', str(pid)], as_root=True, check_return=True) 1466 'showmap %d | grep TOTAL' % int(pid), as_root=True)
1436 if not showmap_out:
1437 raise device_errors.CommandFailedError('No output from showmap')
1438 1467
1439 split_totals = showmap_out[-1].split() 1468 split_totals = showmap_out[-1].split()
1440 if (not split_totals 1469 if (not split_totals
1441 or len(split_totals) != 9 1470 or len(split_totals) != 9
1442 or split_totals[-1] != 'TOTAL'): 1471 or split_totals[-1] != 'TOTAL'):
1443 raise device_errors.CommandFailedError( 1472 raise device_errors.CommandFailedError(
1444 'Invalid output from showmap: %s' % '\n'.join(showmap_out)) 1473 'Invalid output from showmap: %s' % '\n'.join(showmap_out))
1445 1474
1446 return dict(itertools.izip(SMAPS_COLUMNS, (int(n) for n in split_totals))) 1475 return dict(itertools.izip(SMAPS_COLUMNS, (int(n) for n in split_totals)))
1447 1476
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1536 """Returns client cache.""" 1565 """Returns client cache."""
1537 if client_name not in self._client_caches: 1566 if client_name not in self._client_caches:
1538 self._client_caches[client_name] = {} 1567 self._client_caches[client_name] = {}
1539 return self._client_caches[client_name] 1568 return self._client_caches[client_name]
1540 1569
1541 def _ClearCache(self): 1570 def _ClearCache(self):
1542 """Clears all caches.""" 1571 """Clears all caches."""
1543 for client in self._client_caches: 1572 for client in self._client_caches:
1544 self._client_caches[client].clear() 1573 self._client_caches[client].clear()
1545 self._cache.clear() 1574 self._cache.clear()
OLDNEW
« no previous file with comments | « build/android/pylib/device/device_errors.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