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

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: perezju comments 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 output = self.RunShellCommand(script, **kwargs)
582 pipestatus_line = output[-1]
583
584 if not pipestatus_line.startswith(PIPESTATUS_LEADER):
585 logging.error('Pipe exit statuses of shell script missing.')
586 raise device_errors.AdbShellCommandFailedError(
587 script, output, status=None,
588 device_serial=self.adb.GetDeviceSerial())
589
590 output = output[:-1]
591 statuses = [
592 int(s) for s in pipestatus_line[len(PIPESTATUS_LEADER):].split()]
593 if any(statuses):
594 raise device_errors.AdbShellCommandFailedError(
595 script, output, status=statuses,
596 device_serial=self.adb.GetDeviceSerial())
597 return output
598
577 @decorators.WithTimeoutAndRetriesFromInstance() 599 @decorators.WithTimeoutAndRetriesFromInstance()
578 def KillAll(self, process_name, signum=9, as_root=False, blocking=False, 600 def KillAll(self, process_name, signum=9, as_root=False, blocking=False,
579 timeout=None, retries=None): 601 timeout=None, retries=None):
580 """Kill all processes with the given name on the device. 602 """Kill all processes with the given name on the device.
581 603
582 Args: 604 Args:
583 process_name: A string containing the name of the process to kill. 605 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 606 signum: An integer containing the signal number to send to kill. Defaults
585 to 9 (SIGKILL). 607 to 9 (SIGKILL).
586 as_root: A boolean indicating whether the kill should be executed with 608 as_root: A boolean indicating whether the kill should be executed with
587 root privileges. 609 root privileges.
588 blocking: A boolean indicating whether we should wait until all processes 610 blocking: A boolean indicating whether we should wait until all processes
589 with the given |process_name| are dead. 611 with the given |process_name| are dead.
590 timeout: timeout in seconds 612 timeout: timeout in seconds
591 retries: number of retries 613 retries: number of retries
592 614
593 Raises: 615 Raises:
594 CommandFailedError if no process was killed. 616 CommandFailedError if no process was killed.
595 CommandTimeoutError on timeout. 617 CommandTimeoutError on timeout.
596 DeviceUnreachableError on missing device. 618 DeviceUnreachableError on missing device.
597 """ 619 """
598 pids = self._GetPidsImpl(process_name) 620 pids = self.GetPids(process_name)
599 if not pids: 621 if not pids:
600 raise device_errors.CommandFailedError( 622 raise device_errors.CommandFailedError(
601 'No process "%s"' % process_name, str(self)) 623 'No process "%s"' % process_name, str(self))
602 624
603 cmd = ['kill', '-%d' % signum] + pids.values() 625 cmd = ['kill', '-%d' % signum] + pids.values()
604 self.RunShellCommand(cmd, as_root=as_root, check_return=True) 626 self.RunShellCommand(cmd, as_root=as_root, check_return=True)
605 627
606 if blocking: 628 if blocking:
607 wait_period = 0.1 629 wait_period = 0.1
608 while self._GetPidsImpl(process_name): 630 while self.GetPids(process_name):
609 time.sleep(wait_period) 631 time.sleep(wait_period)
610 632
611 return len(pids) 633 return len(pids)
612 634
613 @decorators.WithTimeoutAndRetriesFromInstance() 635 @decorators.WithTimeoutAndRetriesFromInstance()
614 def StartActivity(self, intent_obj, blocking=False, trace_file_name=None, 636 def StartActivity(self, intent_obj, blocking=False, trace_file_name=None,
615 force_stop=False, timeout=None, retries=None): 637 force_stop=False, timeout=None, retries=None):
616 """Start package's activity on the device. 638 """Start package's activity on the device.
617 639
618 Args: 640 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, 1035 ls_out = self.RunShellCommand(['ls', '-l', device_path], as_root=as_root,
1014 check_return=True) 1036 check_return=True)
1015 for line in ls_out: 1037 for line in ls_out:
1016 m = self._LS_RE.match(line) 1038 m = self._LS_RE.match(line)
1017 if m and m.group('name') == posixpath.basename(device_path): 1039 if m and m.group('name') == posixpath.basename(device_path):
1018 size = int(m.group('size')) 1040 size = int(m.group('size'))
1019 break 1041 break
1020 else: 1042 else:
1021 logging.warning('Could not determine size of %s.', device_path) 1043 logging.warning('Could not determine size of %s.', device_path)
1022 1044
1023 if size is None or size <= self._MAX_ADB_OUTPUT_LENGTH: 1045 if 0 < size <= self._MAX_ADB_OUTPUT_LENGTH:
1024 return _JoinLines(self.RunShellCommand( 1046 return _JoinLines(self.RunShellCommand(
1025 ['cat', device_path], as_root=as_root, check_return=True)) 1047 ['cat', device_path], as_root=as_root, check_return=True))
1026 elif as_root and self.NeedsSU(): 1048 elif as_root and self.NeedsSU():
1027 with device_temp_file.DeviceTempFile(self.adb) as device_temp: 1049 with device_temp_file.DeviceTempFile(self.adb) as device_temp:
1028 self.RunShellCommand(['cp', device_path, device_temp.name], 1050 self.RunShellCommand(['cp', device_path, device_temp.name],
1029 as_root=True, check_return=True) 1051 as_root=True, check_return=True)
1030 return self._ReadFileWithPull(device_temp.name) 1052 return self._ReadFileWithPull(device_temp.name)
1031 else: 1053 else:
1032 return self._ReadFileWithPull(device_path) 1054 return self._ReadFileWithPull(device_path)
1033 1055
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
1348 retries: number of retries 1370 retries: number of retries
1349 1371
1350 Returns: 1372 Returns:
1351 A dict mapping process name to PID for each process that contained the 1373 A dict mapping process name to PID for each process that contained the
1352 provided |process_name|. 1374 provided |process_name|.
1353 1375
1354 Raises: 1376 Raises:
1355 CommandTimeoutError on timeout. 1377 CommandTimeoutError on timeout.
1356 DeviceUnreachableError on missing device. 1378 DeviceUnreachableError on missing device.
1357 """ 1379 """
1358 return self._GetPidsImpl(process_name) 1380 procs_pids = {}
1381 try:
1382 ps_output = self._RunPipedShellCommand(
1383 cmd_helper.SingleQuote('ps | grep -F %s' % process_name),
1384 check_return=False)
perezju 2015/04/14 14:13:35 nit: I'm ok with this, but maybe _RunPipedShellCom
jbudorick 2015/04/14 16:56:13 After our offline discussion, I realized that chec
1385 except device_errors.AdbShellCommandFailedError as e:
1386 if e.status 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),
1436 if not showmap_out: 1467 as_root=True, check_return=False)
1437 raise device_errors.CommandFailedError('No output from showmap')
1438 1468
1439 split_totals = showmap_out[-1].split() 1469 split_totals = showmap_out[-1].split()
1440 if (not split_totals 1470 if (not split_totals
1441 or len(split_totals) != 9 1471 or len(split_totals) != 9
1442 or split_totals[-1] != 'TOTAL'): 1472 or split_totals[-1] != 'TOTAL'):
1443 raise device_errors.CommandFailedError( 1473 raise device_errors.CommandFailedError(
1444 'Invalid output from showmap: %s' % '\n'.join(showmap_out)) 1474 'Invalid output from showmap: %s' % '\n'.join(showmap_out))
1445 1475
1446 return dict(itertools.izip(SMAPS_COLUMNS, (int(n) for n in split_totals))) 1476 return dict(itertools.izip(SMAPS_COLUMNS, (int(n) for n in split_totals)))
1447 1477
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1515 all attached devices will be used. 1545 all attached devices will be used.
1516 async: If true, returns a Parallelizer that runs operations 1546 async: If true, returns a Parallelizer that runs operations
1517 asynchronously. 1547 asynchronously.
1518 1548
1519 Returns: 1549 Returns:
1520 A Parallelizer operating over |devices|. 1550 A Parallelizer operating over |devices|.
1521 """ 1551 """
1522 if not devices: 1552 if not devices:
1523 blacklist = device_blacklist.ReadBlacklist() 1553 blacklist = device_blacklist.ReadBlacklist()
1524 devices = [d for d in adb_wrapper.AdbWrapper.GetDevices() 1554 devices = [d for d in adb_wrapper.AdbWrapper.GetDevices()
1525 if d.GetDeviceSerial() not in blacklist] 1555 if d.GetDeviceSerial() not in blacklist]
perezju 2015/04/14 14:13:35 what's this? merged from another CL?
jbudorick 2015/04/14 16:56:12 You're looking at the 2-3 diff, I take it?
perezju 2015/04/15 09:40:43 I guess that was it.
1526 if not devices: 1556 if not devices:
1527 raise device_errors.NoDevicesError() 1557 raise device_errors.NoDevicesError()
1528 1558
1529 devices = [d if isinstance(d, cls) else cls(d) for d in devices] 1559 devices = [d if isinstance(d, cls) else cls(d) for d in devices]
1530 if async: 1560 if async:
1531 return parallelizer.Parallelizer(devices) 1561 return parallelizer.Parallelizer(devices)
1532 else: 1562 else:
1533 return parallelizer.SyncParallelizer(devices) 1563 return parallelizer.SyncParallelizer(devices)
1534 1564
1535 def GetClientCache(self, client_name): 1565 def GetClientCache(self, client_name):
1536 """Returns client cache.""" 1566 """Returns client cache."""
1537 if client_name not in self._client_caches: 1567 if client_name not in self._client_caches:
1538 self._client_caches[client_name] = {} 1568 self._client_caches[client_name] = {}
1539 return self._client_caches[client_name] 1569 return self._client_caches[client_name]
1540 1570
1541 def _ClearCache(self): 1571 def _ClearCache(self):
1542 """Clears all caches.""" 1572 """Clears all caches."""
1543 for client in self._client_caches: 1573 for client in self._client_caches:
1544 self._client_caches[client].clear() 1574 self._client_caches[client].clear()
1545 self._cache.clear() 1575 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