I have a rooted Android phone.
When I run ./app_profiler.py --system_wide
, I get the following output:
simpleperf E cmd_record.cpp:1256] System wide profiling needs root privilege.
Failed to record profiling data.
After debugging, I found out that the scripts have a way to use adb root
+ adb unroot
if the ro.build.type
is not user
. But my phone's build type is user
, and adb root
prints adbd cannot run as root in production builds
.
However, I can run simpleperf as root manually using adb shell su -c "..."
.
Could we adjust the scripts so that they do this?
--- /Users/mstange/Downloads/simpleperf_utils.py 2024-06-05 14:57:51 +++ /Users/mstange/.mozbuild/android-ndk-r26c/simpleperf/simpleperf_utils.py 2024-06-05 15:13:13 @@ -336,16 +336,20 @@ return True build_type = self.get_property('ro.build.type') if build_type == 'user': return False self.run(['root']) time.sleep(1) self.run(['wait-for-device']) result, stdoutdata = self.run_and_return_output(['shell', 'whoami']) + return result and 'root' in stdoutdata + + def check_su(self) -> bool: + result, stdoutdata = self.run_and_return_output(['shell', 'su', '-c', 'whoami']) return result and 'root' in stdoutdata def get_property(self, name: str) -> Optional[str]: result, stdoutdata = self.run_and_return_output(['shell', 'getprop', name]) return stdoutdata.strip() if result else None def set_property(self, name: str, value: str) -> bool: return self.run(['shell', 'setprop', name, value])
--- /Users/mstange/Downloads/app_profiler.py 2024-06-05 14:57:50 +++ /Users/mstange/.mozbuild/android-ndk-r26c/simpleperf/app_profiler.py 2024-06-05 15:14:35 @@ -23,16 +23,17 @@ import logging import os import os.path import re import subprocess import sys import time +import shlex from simpleperf_utils import ( AdbHelper, BaseArgumentParser, bytes_to_str, extant_dir, get_script_dir, get_target_binary_path, log_exit, ReadElf, remove, str_to_bytes) NATIVE_LIBS_DIR_ON_DEVICE = '/data/local/tmp/native_libs/' SHELL_PS_UID_PATTERN = re.compile(r'USER.*\nu(\d+)_.*') @@ -190,16 +191,17 @@ class ProfilerBase(object): """Base class of all Profilers.""" def __init__(self, args): self.args = args self.adb = AdbHelper(enable_switch_to_root=not args.disable_adb_root) self.is_root_device = self.adb.switch_to_root() + self.have_su = self.adb.check_su() self.android_version = self.adb.get_android_version() if self.android_version < 7: log_exit("""app_profiler.py isn't supported on Android < N, please switch to use simpleperf binary directly.""") self.device_arch = self.adb.get_device_arch() self.record_subproc = None def profile(self): @@ -235,17 +237,20 @@ def start_profiling(self, target_args): """Start simpleperf reocrd process on device.""" args = ['/data/local/tmp/simpleperf', 'record', '-o', '/data/local/tmp/perf.data', self.args.record_options] if self.adb.run(['shell', 'ls', NATIVE_LIBS_DIR_ON_DEVICE]): args += ['--symfs', NATIVE_LIBS_DIR_ON_DEVICE] args += ['--log', self.args.log] args += target_args - adb_args = [self.adb.adb_path, 'shell'] + args + if self.have_su: + adb_args = [self.adb.adb_path, 'shell', 'su', '-c', ' '.join(shlex.quote(arg) for arg in args)] + else: + adb_args = [self.adb.adb_path, 'shell'] + args logging.info('run adb cmd: %s' % adb_args) self.record_subproc = subprocess.Popen(adb_args) def wait_profiling(self): """Wait until profiling finishes, or stop profiling when user presses Ctrl-C.""" returncode = None try: returncode = self.record_subproc.wait() @@ -266,17 +271,27 @@ while True: (result, _) = self.adb.run_and_return_output(['shell', 'pidof', 'simpleperf']) if not result: break if not has_killed: has_killed = True self.adb.run_and_return_output(['shell', 'pkill', '-l', '2', 'simpleperf']) time.sleep(1) + self.make_perf_data_owned_by_user() + def make_perf_data_owned_by_user(self): + if not self.have_su: + return + result, shell_user = self.adb.run_and_return_output(['shell', 'whoami']) + if not result: + return + logging.info('adb shell user: %s', shell_user) + self.adb.run(['shell', 'su', '-c', 'chown', shell_user, '/data/local/tmp/perf.data']) + def collect_profiling_data(self): self.adb.check_run_and_return_output(['pull', '/data/local/tmp/perf.data', self.args.perf_data_path]) if not self.args.skip_collect_binaries: binary_cache_args = [sys.executable, os.path.join(get_script_dir(), 'binary_cache_builder.py')] binary_cache_args += ['-i', self.args.perf_data_path, '--log', self.args.log] if self.args.native_lib_dir:
cc @yabinc
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.3