| Index: tools/memory_inspector/memory_inspector/backends/android/android_backend.py
|
| diff --git a/tools/memory_inspector/memory_inspector/backends/android/android_backend.py b/tools/memory_inspector/memory_inspector/backends/android/android_backend.py
|
| index f38c2de21f7ebbfcc0fc97f06ab7917c1a498ff1..50d905eb79426f6e4f0d6370827af4e2fbd8c7aa 100644
|
| --- a/tools/memory_inspector/memory_inspector/backends/android/android_backend.py
|
| +++ b/tools/memory_inspector/memory_inspector/backends/android/android_backend.py
|
| @@ -11,7 +11,6 @@ import datetime
|
| import glob
|
| import hashlib
|
| import json
|
| -import logging
|
| import os
|
| import posixpath
|
|
|
| @@ -32,11 +31,11 @@ from pylib.device import device_utils
|
| from pylib.symbols import elf_symbolizer
|
|
|
|
|
| -_MEMDUMP_PREBUILT_PATH = os.path.join(constants.PROJECT_SRC,
|
| - 'prebuilts', 'memdump-android-arm')
|
| +_MEMDUMP_PREBUILT_PATH = os.path.join(constants.PREBUILTS_PATH,
|
| + 'memdump-android-arm')
|
| _MEMDUMP_PATH_ON_DEVICE = '/data/local/tmp/memdump'
|
| -_PSEXT_PREBUILT_PATH = os.path.join(constants.PROJECT_SRC,
|
| - 'prebuilts', 'ps_ext-android-arm')
|
| +_PSEXT_PREBUILT_PATH = os.path.join(constants.PREBUILTS_PATH,
|
| + 'ps_ext-android-arm')
|
| _PSEXT_PATH_ON_DEVICE = '/data/local/tmp/ps_ext'
|
| _DLMALLOC_DEBUG_SYSPROP = 'libc.debug.malloc'
|
| _DUMPHEAP_OUT_FILE_PATH = '/data/local/tmp/heap-%d-native.dump'
|
| @@ -128,11 +127,18 @@ class AndroidBackend(backends.Backend):
|
| break
|
|
|
| # If no luck, try looking just for the file name in the sym path,
|
| - # e.g. /host/syms/ + (/system/lib/)foo.so => /host/syms/foo.so
|
| + # e.g. /host/syms/ + (/system/lib/)foo.so => /host/syms/foo.so.
|
| exec_file_abs_path = os.path.join(sym_path, exec_file_name)
|
| if os.path.exists(exec_file_abs_path):
|
| break
|
|
|
| + # In the case of a Chrome component=shared_library build, the libs are
|
| + # renamed to .cr.so. Look for foo.so => foo.cr.so.
|
| + exec_file_abs_path = os.path.join(
|
| + sym_path, exec_file_name.replace('.so', '.cr.so'))
|
| + if os.path.exists(exec_file_abs_path):
|
| + break
|
| +
|
| if not os.path.exists(exec_file_abs_path):
|
| continue
|
|
|
| @@ -160,13 +166,13 @@ class AndroidDevice(backends.Device):
|
| _SETTINGS_KEYS = {
|
| 'native_symbol_paths': 'Semicolon-sep. list of native libs search path'}
|
|
|
| - def __init__(self, backend, underlying_device):
|
| + def __init__(self, backend, adb):
|
| super(AndroidDevice, self).__init__(
|
| backend=backend,
|
| settings=backends.Settings(AndroidDevice._SETTINGS_KEYS))
|
| - self.underlying_device = underlying_device
|
| - self._id = str(underlying_device)
|
| - self._name = underlying_device.GetProp('ro.product.model')
|
| + self.adb = adb
|
| + self._id = str(adb)
|
| + self._name = adb.GetProp('ro.product.model')
|
| self._sys_stats = None
|
| self._last_device_stats = None
|
| self._sys_stats_last_update = None
|
| @@ -176,12 +182,12 @@ class AndroidDevice(backends.Device):
|
| def Initialize(self):
|
| """Starts adb root and deploys the prebuilt binaries on initialization."""
|
| try:
|
| - self.underlying_device.EnableRoot()
|
| - except device_errors.CommandFailedError as e:
|
| - # Try to deploy memdump and ps_ext anyway.
|
| - # TODO(jbudorick) Handle this exception appropriately after interface
|
| - # conversions are finished.
|
| - logging.error(str(e))
|
| + self.adb.EnableRoot()
|
| + except device_errors.CommandFailedError:
|
| + # TODO(jbudorick): Handle this exception appropriately after interface
|
| + # conversions are finished.
|
| + raise exceptions.MemoryInspectorException(
|
| + 'The device must be adb root-able in order to use memory_inspector')
|
|
|
| # Download (from GCS) and deploy prebuilt helper binaries on the device.
|
| self._DeployPrebuiltOnDeviceIfNeeded(_MEMDUMP_PREBUILT_PATH,
|
| @@ -192,17 +198,17 @@ class AndroidDevice(backends.Device):
|
|
|
| def IsNativeTracingEnabled(self):
|
| """Checks for the libc.debug.malloc system property."""
|
| - return bool(self.underlying_device.GetProp(
|
| - _DLMALLOC_DEBUG_SYSPROP))
|
| + return bool(self.adb.GetProp(_DLMALLOC_DEBUG_SYSPROP))
|
|
|
| def EnableNativeTracing(self, enabled):
|
| """Enables libc.debug.malloc and restarts the shell."""
|
| assert(self._initialized)
|
| prop_value = '1' if enabled else ''
|
| - self.underlying_device.SetProp(_DLMALLOC_DEBUG_SYSPROP, prop_value)
|
| + self.adb.SetProp(_DLMALLOC_DEBUG_SYSPROP, prop_value)
|
| assert(self.IsNativeTracingEnabled())
|
| # The libc.debug property takes effect only after restarting the Zygote.
|
| - self.underlying_device.old_interface.RestartShell()
|
| + self.adb.old_interface.RestartShell()
|
| + self.adb.old_interface.Adb().WaitForDevicePm(wait_time=30)
|
|
|
| def ListProcesses(self):
|
| """Returns a sequence of |AndroidProcess|."""
|
| @@ -259,7 +265,7 @@ class AndroidDevice(backends.Device):
|
| return self._sys_stats
|
|
|
| dump_out = '\n'.join(
|
| - self.underlying_device.RunShellCommand(_PSEXT_PATH_ON_DEVICE))
|
| + self.adb.RunShellCommand(_PSEXT_PATH_ON_DEVICE))
|
| stats = json.loads(dump_out)
|
| assert(all([x in stats for x in ['cpu', 'processes', 'time', 'mem']])), (
|
| 'ps_ext returned a malformed JSON dictionary.')
|
| @@ -286,12 +292,12 @@ class AndroidDevice(backends.Device):
|
| prebuilts_fetcher.GetIfChanged(local_path)
|
| with open(local_path, 'rb') as f:
|
| local_hash = hashlib.md5(f.read()).hexdigest()
|
| - device_md5_out = self.underlying_device.RunShellCommand(
|
| + device_md5_out = self.adb.RunShellCommand(
|
| 'md5 "%s"' % path_on_device)
|
| if local_hash in device_md5_out:
|
| return
|
| - self.underlying_device.old_interface.Adb().Push(local_path, path_on_device)
|
| - self.underlying_device.RunShellCommand('chmod 755 "%s"' % path_on_device)
|
| + self.adb.old_interface.Adb().Push(local_path, path_on_device)
|
| + self.adb.RunShellCommand('chmod 755 "%s"' % path_on_device)
|
|
|
| @property
|
| def name(self):
|
| @@ -314,7 +320,7 @@ class AndroidProcess(backends.Process):
|
| def DumpMemoryMaps(self):
|
| """Grabs and parses memory maps through memdump."""
|
| cmd = '%s %d' % (_MEMDUMP_PATH_ON_DEVICE, self.pid)
|
| - dump_out = self.device.underlying_device.RunShellCommand(cmd)
|
| + dump_out = self.device.adb.RunShellCommand(cmd)
|
| return memdump_parser.Parse(dump_out)
|
|
|
| def DumpNativeHeap(self):
|
| @@ -322,12 +328,12 @@ class AndroidProcess(backends.Process):
|
| # TODO(primiano): grab also mmap bt (depends on pending framework change).
|
| dump_file_path = _DUMPHEAP_OUT_FILE_PATH % self.pid
|
| cmd = 'am dumpheap -n %d %s' % (self.pid, dump_file_path)
|
| - self.device.underlying_device.RunShellCommand(cmd)
|
| + self.device.adb.RunShellCommand(cmd)
|
| # TODO(primiano): Some pre-KK versions of Android might need a sleep here
|
| # as, IIRC, 'am dumpheap' did not wait for the dump to be completed before
|
| # returning. Double check this and either add a sleep or remove this TODO.
|
| - dump_out = self.device.underlying_device.ReadFile(dump_file_path)
|
| - self.device.underlying_device.RunShellCommand('rm %s' % dump_file_path)
|
| + dump_out = self.device.adb.ReadFile(dump_file_path)
|
| + self.device.adb.RunShellCommand('rm %s' % dump_file_path)
|
| return dumpheap_native_parser.Parse(dump_out)
|
|
|
| def GetStats(self):
|
|
|