OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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() |
OLD | NEW |