Chromium Code Reviews| 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 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 565 if not output: | 565 if not output: |
| 566 return '' | 566 return '' |
| 567 elif len(output) == 1: | 567 elif len(output) == 1: |
| 568 return output[0] | 568 return output[0] |
| 569 else: | 569 else: |
| 570 msg = 'one line of output was expected, but got: %s' | 570 msg = 'one line of output was expected, but got: %s' |
| 571 raise device_errors.CommandFailedError(msg % output, str(self)) | 571 raise device_errors.CommandFailedError(msg % output, str(self)) |
| 572 else: | 572 else: |
| 573 return output | 573 return output |
| 574 | 574 |
| 575 def _RunPipedShellCommand(self, script, **kwargs): | |
| 576 PIPESTATUS_LEADER = 'PIPESTATUS: ' | |
| 577 | |
| 578 if not isinstance(script, basestring): | |
| 579 script = ' '.join(script) | |
|
perezju
2015/04/14 10:17:29
I'm not sure I link this. The caller should be res
jbudorick
2015/04/14 13:42:46
I wasn't sure about this. Removed.
| |
| 580 | |
| 581 script += '; echo "%s${PIPESTATUS[@]}"' % PIPESTATUS_LEADER | |
| 582 output = self.RunShellCommand(script, **kwargs) | |
| 583 pipestatus_line = output[-1] | |
| 584 output = output[:-1] | |
| 585 | |
| 586 if not pipestatus_line.startswith(PIPESTATUS_LEADER): | |
| 587 logging.error('exit statuses of shell script %r missing.', script) | |
|
perezju
2015/04/14 10:17:29
RunShellCommand should have already logged the scr
jbudorick
2015/04/14 13:42:46
Done.
| |
| 588 raise device_errors.AdbShellCommandFailedError( | |
| 589 script, output, status=None, | |
|
perezju
2015/04/14 10:17:29
if the PIPESTATUS_LEADER is missing, maybe we want
jbudorick
2015/04/14 13:42:46
moved output = output[:-1] below this check
| |
| 590 device_serial=self.adb.GetDeviceSerial()) | |
| 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 | |
| 575 @decorators.WithTimeoutAndRetriesFromInstance() | 599 @decorators.WithTimeoutAndRetriesFromInstance() |
| 576 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, |
| 577 timeout=None, retries=None): | 601 timeout=None, retries=None): |
| 578 """Kill all processes with the given name on the device. | 602 """Kill all processes with the given name on the device. |
| 579 | 603 |
| 580 Args: | 604 Args: |
| 581 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. |
| 582 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 |
| 583 to 9 (SIGKILL). | 607 to 9 (SIGKILL). |
| 584 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 |
| 585 root privileges. | 609 root privileges. |
| 586 blocking: A boolean indicating whether we should wait until all processes | 610 blocking: A boolean indicating whether we should wait until all processes |
| 587 with the given |process_name| are dead. | 611 with the given |process_name| are dead. |
| 588 timeout: timeout in seconds | 612 timeout: timeout in seconds |
| 589 retries: number of retries | 613 retries: number of retries |
| 590 | 614 |
| 591 Raises: | 615 Raises: |
| 592 CommandFailedError if no process was killed. | 616 CommandFailedError if no process was killed. |
| 593 CommandTimeoutError on timeout. | 617 CommandTimeoutError on timeout. |
| 594 DeviceUnreachableError on missing device. | 618 DeviceUnreachableError on missing device. |
| 595 """ | 619 """ |
| 596 pids = self._GetPidsImpl(process_name) | 620 pids = self.GetPids(process_name) |
| 597 if not pids: | 621 if not pids: |
| 598 raise device_errors.CommandFailedError( | 622 raise device_errors.CommandFailedError( |
| 599 'No process "%s"' % process_name, str(self)) | 623 'No process "%s"' % process_name, str(self)) |
| 600 | 624 |
| 601 cmd = ['kill', '-%d' % signum] + pids.values() | 625 cmd = ['kill', '-%d' % signum] + pids.values() |
| 602 self.RunShellCommand(cmd, as_root=as_root, check_return=True) | 626 self.RunShellCommand(cmd, as_root=as_root, check_return=True) |
| 603 | 627 |
| 604 if blocking: | 628 if blocking: |
| 605 wait_period = 0.1 | 629 wait_period = 0.1 |
| 606 while self._GetPidsImpl(process_name): | 630 while self.GetPids(process_name): |
| 607 time.sleep(wait_period) | 631 time.sleep(wait_period) |
| 608 | 632 |
| 609 return len(pids) | 633 return len(pids) |
| 610 | 634 |
| 611 @decorators.WithTimeoutAndRetriesFromInstance() | 635 @decorators.WithTimeoutAndRetriesFromInstance() |
| 612 def StartActivity(self, intent_obj, blocking=False, trace_file_name=None, | 636 def StartActivity(self, intent_obj, blocking=False, trace_file_name=None, |
| 613 force_stop=False, timeout=None, retries=None): | 637 force_stop=False, timeout=None, retries=None): |
| 614 """Start package's activity on the device. | 638 """Start package's activity on the device. |
| 615 | 639 |
| 616 Args: | 640 Args: |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1011 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, |
| 1012 check_return=True) | 1036 check_return=True) |
| 1013 for line in ls_out: | 1037 for line in ls_out: |
| 1014 m = self._LS_RE.match(line) | 1038 m = self._LS_RE.match(line) |
| 1015 if m and m.group('name') == posixpath.basename(device_path): | 1039 if m and m.group('name') == posixpath.basename(device_path): |
| 1016 size = int(m.group('size')) | 1040 size = int(m.group('size')) |
| 1017 break | 1041 break |
| 1018 else: | 1042 else: |
| 1019 logging.warning('Could not determine size of %s.', device_path) | 1043 logging.warning('Could not determine size of %s.', device_path) |
| 1020 | 1044 |
| 1021 if size is None or size <= self._MAX_ADB_OUTPUT_LENGTH: | 1045 if size > 0 and size <= self._MAX_ADB_OUTPUT_LENGTH: |
|
perezju
2015/04/14 10:17:29
I think you can write this as: 0 < size <= self._M
jbudorick
2015/04/14 13:42:46
this is sorcery
done
| |
| 1022 return _JoinLines(self.RunShellCommand( | 1046 return _JoinLines(self.RunShellCommand( |
| 1023 ['cat', device_path], as_root=as_root, check_return=True)) | 1047 ['cat', device_path], as_root=as_root, check_return=True)) |
| 1024 elif as_root and self.NeedsSU(): | 1048 elif as_root and self.NeedsSU(): |
| 1025 with device_temp_file.DeviceTempFile(self.adb) as device_temp: | 1049 with device_temp_file.DeviceTempFile(self.adb) as device_temp: |
| 1026 self.RunShellCommand(['cp', device_path, device_temp.name], | 1050 self.RunShellCommand(['cp', device_path, device_temp.name], |
| 1027 as_root=True, check_return=True) | 1051 as_root=True, check_return=True) |
| 1028 return self._ReadFileWithPull(device_temp.name) | 1052 return self._ReadFileWithPull(device_temp.name) |
| 1029 else: | 1053 else: |
| 1030 return self._ReadFileWithPull(device_path) | 1054 return self._ReadFileWithPull(device_path) |
| 1031 | 1055 |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1346 retries: number of retries | 1370 retries: number of retries |
| 1347 | 1371 |
| 1348 Returns: | 1372 Returns: |
| 1349 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 |
| 1350 provided |process_name|. | 1374 provided |process_name|. |
| 1351 | 1375 |
| 1352 Raises: | 1376 Raises: |
| 1353 CommandTimeoutError on timeout. | 1377 CommandTimeoutError on timeout. |
| 1354 DeviceUnreachableError on missing device. | 1378 DeviceUnreachableError on missing device. |
| 1355 """ | 1379 """ |
| 1356 return self._GetPidsImpl(process_name) | 1380 procs_pids = {} |
| 1381 try: | |
| 1382 ps_output = self._RunPipedShellCommand( | |
| 1383 'ps | grep -F %s' % process_name, check_return=True) | |
|
perezju
2015/04/14 10:17:29
use cmd_helper.SingleQuote(process_name)
jbudorick
2015/04/14 13:42:46
Done.
| |
| 1384 except device_errors.AdbShellCommandFailedError as e: | |
|
perezju
2015/04/14 10:17:29
just to clarify, what is the relationship between
jbudorick
2015/04/14 13:42:46
I'm not sure whether $? is the same as the last it
| |
| 1385 if e.status and not e.status[0]: | |
| 1386 # If ps succeeded but grep failed, there were no processes with the | |
| 1387 # given name. | |
| 1388 return procs_pids | |
| 1389 else: | |
| 1390 raise | |
| 1357 | 1391 |
| 1358 def _GetPidsImpl(self, process_name): | 1392 for line in ps_output: |
| 1359 procs_pids = {} | |
| 1360 for line in self.RunShellCommand('ps', check_return=True): | |
| 1361 try: | 1393 try: |
| 1362 ps_data = line.split() | 1394 ps_data = line.split() |
| 1363 if process_name in ps_data[-1]: | 1395 if process_name in ps_data[-1]: |
| 1364 procs_pids[ps_data[-1]] = ps_data[1] | 1396 procs_pids[ps_data[-1]] = ps_data[1] |
| 1365 except IndexError: | 1397 except IndexError: |
| 1366 pass | 1398 pass |
| 1367 return procs_pids | 1399 return procs_pids |
| 1368 | 1400 |
| 1369 @decorators.WithTimeoutAndRetriesFromInstance() | 1401 @decorators.WithTimeoutAndRetriesFromInstance() |
| 1370 def TakeScreenshot(self, host_path=None, timeout=None, retries=None): | 1402 def TakeScreenshot(self, host_path=None, timeout=None, retries=None): |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1422 except device_errors.CommandFailedError: | 1454 except device_errors.CommandFailedError: |
| 1423 logging.exception('Error getting memory usage from status') | 1455 logging.exception('Error getting memory usage from status') |
| 1424 | 1456 |
| 1425 return result | 1457 return result |
| 1426 | 1458 |
| 1427 def _GetMemoryUsageForPidFromSmaps(self, pid): | 1459 def _GetMemoryUsageForPidFromSmaps(self, pid): |
| 1428 SMAPS_COLUMNS = ( | 1460 SMAPS_COLUMNS = ( |
| 1429 'Size', 'Rss', 'Pss', 'Shared_Clean', 'Shared_Dirty', 'Private_Clean', | 1461 'Size', 'Rss', 'Pss', 'Shared_Clean', 'Shared_Dirty', 'Private_Clean', |
| 1430 'Private_Dirty') | 1462 'Private_Dirty') |
| 1431 | 1463 |
| 1432 showmap_out = self.RunShellCommand( | 1464 showmap_out = self._RunPipedShellCommand( |
| 1433 ['showmap', str(pid)], as_root=True, check_return=True) | 1465 'showmap %s | grep TOTAL' % str(pid), as_root=True, check_return=True) |
|
perezju
2015/04/14 10:17:29
maybe rewrite as: 'showmap %d | grep TOTAL' % pid
perezju
2015/04/14 10:49:19
actually, maybe: 'showmap %d | grep TOTAL' % int(p
jbudorick
2015/04/14 13:42:46
Done.
| |
| 1434 if not showmap_out: | |
| 1435 raise device_errors.CommandFailedError('No output from showmap') | |
| 1436 | 1466 |
| 1437 split_totals = showmap_out[-1].split() | 1467 split_totals = showmap_out[-1].split() |
| 1438 if (not split_totals | 1468 if (not split_totals |
| 1439 or len(split_totals) != 9 | 1469 or len(split_totals) != 9 |
| 1440 or split_totals[-1] != 'TOTAL'): | 1470 or split_totals[-1] != 'TOTAL'): |
| 1441 raise device_errors.CommandFailedError( | 1471 raise device_errors.CommandFailedError( |
| 1442 'Invalid output from showmap: %s' % '\n'.join(showmap_out)) | 1472 'Invalid output from showmap: %s' % '\n'.join(showmap_out)) |
| 1443 | 1473 |
| 1444 return dict(itertools.izip(SMAPS_COLUMNS, (int(n) for n in split_totals))) | 1474 return dict(itertools.izip(SMAPS_COLUMNS, (int(n) for n in split_totals))) |
| 1445 | 1475 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1531 """Returns client cache.""" | 1561 """Returns client cache.""" |
| 1532 if client_name not in self._client_caches: | 1562 if client_name not in self._client_caches: |
| 1533 self._client_caches[client_name] = {} | 1563 self._client_caches[client_name] = {} |
| 1534 return self._client_caches[client_name] | 1564 return self._client_caches[client_name] |
| 1535 | 1565 |
| 1536 def _ClearCache(self): | 1566 def _ClearCache(self): |
| 1537 """Clears all caches.""" | 1567 """Clears all caches.""" |
| 1538 for client in self._client_caches: | 1568 for client in self._client_caches: |
| 1539 self._client_caches[client].clear() | 1569 self._client_caches[client].clear() |
| 1540 self._cache.clear() | 1570 self._cache.clear() |
| OLD | NEW |