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 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 if not output: | 568 if not output: |
569 return '' | 569 return '' |
570 elif len(output) == 1: | 570 elif len(output) == 1: |
571 return output[0] | 571 return output[0] |
572 else: | 572 else: |
573 msg = 'one line of output was expected, but got: %s' | 573 msg = 'one line of output was expected, but got: %s' |
574 raise device_errors.CommandFailedError(msg % output, str(self)) | 574 raise device_errors.CommandFailedError(msg % output, str(self)) |
575 else: | 575 else: |
576 return output | 576 return output |
577 | 577 |
| 578 def _RunPipedShellCommand(self, script, **kwargs): |
| 579 PIPESTATUS_LEADER = 'PIPESTATUS: ' |
| 580 |
| 581 script += '; echo "%s${PIPESTATUS[@]}"' % PIPESTATUS_LEADER |
| 582 kwargs['check_return'] = True |
| 583 output = self.RunShellCommand(script, **kwargs) |
| 584 pipestatus_line = output[-1] |
| 585 |
| 586 if not pipestatus_line.startswith(PIPESTATUS_LEADER): |
| 587 logging.error('Pipe exit statuses of shell script missing.') |
| 588 raise device_errors.AdbShellCommandFailedError( |
| 589 script, output, status=None, |
| 590 device_serial=self.adb.GetDeviceSerial()) |
| 591 |
| 592 output = output[:-1] |
| 593 statuses = [ |
| 594 int(s) for s in pipestatus_line[len(PIPESTATUS_LEADER):].split()] |
| 595 if any(statuses): |
| 596 raise device_errors.AdbShellCommandFailedError( |
| 597 script, output, status=statuses, |
| 598 device_serial=self.adb.GetDeviceSerial()) |
| 599 return output |
| 600 |
578 @decorators.WithTimeoutAndRetriesFromInstance() | 601 @decorators.WithTimeoutAndRetriesFromInstance() |
579 def KillAll(self, process_name, signum=device_signal.SIGKILL, as_root=False, | 602 def KillAll(self, process_name, signum=device_signal.SIGKILL, as_root=False, |
580 blocking=False, quiet=False, timeout=None, retries=None): | 603 blocking=False, quiet=False, timeout=None, retries=None): |
581 """Kill all processes with the given name on the device. | 604 """Kill all processes with the given name on the device. |
582 | 605 |
583 Args: | 606 Args: |
584 process_name: A string containing the name of the process to kill. | 607 process_name: A string containing the name of the process to kill. |
585 signum: An integer containing the signal number to send to kill. Defaults | 608 signum: An integer containing the signal number to send to kill. Defaults |
586 to SIGKILL (9). | 609 to SIGKILL (9). |
587 as_root: A boolean indicating whether the kill should be executed with | 610 as_root: A boolean indicating whether the kill should be executed with |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1023 ls_out = self.RunShellCommand(['ls', '-l', device_path], as_root=as_root, | 1046 ls_out = self.RunShellCommand(['ls', '-l', device_path], as_root=as_root, |
1024 check_return=True) | 1047 check_return=True) |
1025 for line in ls_out: | 1048 for line in ls_out: |
1026 m = self._LS_RE.match(line) | 1049 m = self._LS_RE.match(line) |
1027 if m and m.group('name') == posixpath.basename(device_path): | 1050 if m and m.group('name') == posixpath.basename(device_path): |
1028 size = int(m.group('size')) | 1051 size = int(m.group('size')) |
1029 break | 1052 break |
1030 else: | 1053 else: |
1031 logging.warning('Could not determine size of %s.', device_path) | 1054 logging.warning('Could not determine size of %s.', device_path) |
1032 | 1055 |
1033 if size is None or size <= self._MAX_ADB_OUTPUT_LENGTH: | 1056 if 0 < size <= self._MAX_ADB_OUTPUT_LENGTH: |
1034 return _JoinLines(self.RunShellCommand( | 1057 return _JoinLines(self.RunShellCommand( |
1035 ['cat', device_path], as_root=as_root, check_return=True)) | 1058 ['cat', device_path], as_root=as_root, check_return=True)) |
1036 elif as_root and self.NeedsSU(): | 1059 elif as_root and self.NeedsSU(): |
1037 with device_temp_file.DeviceTempFile(self.adb) as device_temp: | 1060 with device_temp_file.DeviceTempFile(self.adb) as device_temp: |
1038 self.RunShellCommand(['cp', device_path, device_temp.name], | 1061 self.RunShellCommand(['cp', device_path, device_temp.name], |
1039 as_root=True, check_return=True) | 1062 as_root=True, check_return=True) |
1040 return self._ReadFileWithPull(device_temp.name) | 1063 return self._ReadFileWithPull(device_temp.name) |
1041 else: | 1064 else: |
1042 return self._ReadFileWithPull(device_path) | 1065 return self._ReadFileWithPull(device_path) |
1043 | 1066 |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1359 | 1382 |
1360 Returns: | 1383 Returns: |
1361 A dict mapping process name to PID for each process that contained the | 1384 A dict mapping process name to PID for each process that contained the |
1362 provided |process_name|. | 1385 provided |process_name|. |
1363 | 1386 |
1364 Raises: | 1387 Raises: |
1365 CommandTimeoutError on timeout. | 1388 CommandTimeoutError on timeout. |
1366 DeviceUnreachableError on missing device. | 1389 DeviceUnreachableError on missing device. |
1367 """ | 1390 """ |
1368 procs_pids = {} | 1391 procs_pids = {} |
1369 for line in self.RunShellCommand('ps', check_return=True): | 1392 try: |
| 1393 ps_output = self._RunPipedShellCommand( |
| 1394 'ps | grep -F %s' % cmd_helper.SingleQuote(process_name)) |
| 1395 except device_errors.AdbShellCommandFailedError as e: |
| 1396 if e.status and isinstance(e.status, list) and not e.status[0]: |
| 1397 # If ps succeeded but grep failed, there were no processes with the |
| 1398 # given name. |
| 1399 return procs_pids |
| 1400 else: |
| 1401 raise |
| 1402 |
| 1403 for line in ps_output: |
1370 try: | 1404 try: |
1371 ps_data = line.split() | 1405 ps_data = line.split() |
1372 if process_name in ps_data[-1]: | 1406 if process_name in ps_data[-1]: |
1373 procs_pids[ps_data[-1]] = ps_data[1] | 1407 procs_pids[ps_data[-1]] = ps_data[1] |
1374 except IndexError: | 1408 except IndexError: |
1375 pass | 1409 pass |
1376 return procs_pids | 1410 return procs_pids |
1377 | 1411 |
1378 @decorators.WithTimeoutAndRetriesFromInstance() | 1412 @decorators.WithTimeoutAndRetriesFromInstance() |
1379 def TakeScreenshot(self, host_path=None, timeout=None, retries=None): | 1413 def TakeScreenshot(self, host_path=None, timeout=None, retries=None): |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1431 except device_errors.CommandFailedError: | 1465 except device_errors.CommandFailedError: |
1432 logging.exception('Error getting memory usage from status') | 1466 logging.exception('Error getting memory usage from status') |
1433 | 1467 |
1434 return result | 1468 return result |
1435 | 1469 |
1436 def _GetMemoryUsageForPidFromSmaps(self, pid): | 1470 def _GetMemoryUsageForPidFromSmaps(self, pid): |
1437 SMAPS_COLUMNS = ( | 1471 SMAPS_COLUMNS = ( |
1438 'Size', 'Rss', 'Pss', 'Shared_Clean', 'Shared_Dirty', 'Private_Clean', | 1472 'Size', 'Rss', 'Pss', 'Shared_Clean', 'Shared_Dirty', 'Private_Clean', |
1439 'Private_Dirty') | 1473 'Private_Dirty') |
1440 | 1474 |
1441 showmap_out = self.RunShellCommand( | 1475 showmap_out = self._RunPipedShellCommand( |
1442 ['showmap', str(pid)], as_root=True, check_return=True) | 1476 'showmap %d | grep TOTAL' % int(pid), as_root=True) |
1443 if not showmap_out: | |
1444 raise device_errors.CommandFailedError('No output from showmap') | |
1445 | 1477 |
1446 split_totals = showmap_out[-1].split() | 1478 split_totals = showmap_out[-1].split() |
1447 if (not split_totals | 1479 if (not split_totals |
1448 or len(split_totals) != 9 | 1480 or len(split_totals) != 9 |
1449 or split_totals[-1] != 'TOTAL'): | 1481 or split_totals[-1] != 'TOTAL'): |
1450 raise device_errors.CommandFailedError( | 1482 raise device_errors.CommandFailedError( |
1451 'Invalid output from showmap: %s' % '\n'.join(showmap_out)) | 1483 'Invalid output from showmap: %s' % '\n'.join(showmap_out)) |
1452 | 1484 |
1453 return dict(itertools.izip(SMAPS_COLUMNS, (int(n) for n in split_totals))) | 1485 return dict(itertools.izip(SMAPS_COLUMNS, (int(n) for n in split_totals))) |
1454 | 1486 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1543 """Returns client cache.""" | 1575 """Returns client cache.""" |
1544 if client_name not in self._client_caches: | 1576 if client_name not in self._client_caches: |
1545 self._client_caches[client_name] = {} | 1577 self._client_caches[client_name] = {} |
1546 return self._client_caches[client_name] | 1578 return self._client_caches[client_name] |
1547 | 1579 |
1548 def _ClearCache(self): | 1580 def _ClearCache(self): |
1549 """Clears all caches.""" | 1581 """Clears all caches.""" |
1550 for client in self._client_caches: | 1582 for client in self._client_caches: |
1551 self._client_caches[client].clear() | 1583 self._client_caches[client].clear() |
1552 self._cache.clear() | 1584 self._cache.clear() |
OLD | NEW |