Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

from .base import ANDROID_SDK_VERSION_T, Command, ValidationError
from .config_builder import create_common_config_parser, PREDEFINED_PERFETTO_CONFIGS
from .device import OsCodes
from .handle_input import HandleInput
from .profiler import verify_trigger_args
from .utils import run_subprocess, TEXTPROTO_FILE_EXTENSIONS
Expand All @@ -28,7 +29,7 @@ def add_config_parser(subparsers):
common_config_args = argparse.ArgumentParser(add_help=False)
common_config_args.add_argument(
'config_name',
choices=['lightweight', 'default', 'memory', 'qnx'],
choices=['lightweight', 'default', 'memory', 'qnx', 'android-qnx'],
help='Name of the predefined config to copy')

common_profiler_args = create_common_config_parser()
Expand Down Expand Up @@ -132,7 +133,7 @@ def create_config_command(args):

def execute_show_or_pull_command(command, device):
android_sdk_version = ANDROID_SDK_VERSION_T
if device is not None:
if device is not None and device.os() == OsCodes.OS_ANDROID:
device.root_device()
android_sdk_version = device.get_android_sdk_version()

Expand Down
25 changes: 21 additions & 4 deletions src/config_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def create_trigger_config(trigger_names, trigger_mode, trigger_timeout_ms,


def build_predefined_config(command,
android_sdk_version,
android_sdk_version=None,
predefined_ftrace_events=None,
sys_stats_events=None,
predefined_atrace_events=None,
Expand Down Expand Up @@ -260,7 +260,7 @@ def build_predefined_config(command,
return None, error

cpufreq_period_string = "cpufreq_period_ms: 500"
if android_sdk_version < ANDROID_SDK_VERSION_T:
if android_sdk_version is None or android_sdk_version < ANDROID_SDK_VERSION_T:
cpufreq_period_string = ""

trigger_config = ""
Expand Down Expand Up @@ -571,7 +571,6 @@ def build_qnx_config(command, android_sdk_version):
# QNX config does not use Android specific data sources
return build_predefined_config(
command,
android_sdk_version,
predefined_ftrace_events=[],
sys_stats_events="",
predefined_atrace_events="",
Expand All @@ -586,11 +585,29 @@ def build_qnx_config(command, android_sdk_version):
extra_configs=extra_configs)


def build_android_qnx_config(command, android_sdk_version):
# Android-QNX config merges Android default with QNX config
extra_configs = f'''
data_sources {{
config {{
name: "qnx.kernel"
target_buffer: 2
}}
}}

trace_all_machines: true
'''

return build_predefined_config(
command, android_sdk_version, extra_configs=extra_configs)


PREDEFINED_PERFETTO_CONFIGS = {
'default': build_default_config,
'lightweight': build_lightweight_config,
'memory': build_memory_config,
'qnx': build_qnx_config
'qnx': build_qnx_config,
'android-qnx': build_android_qnx_config
}


Expand Down
188 changes: 187 additions & 1 deletion tests/config_command_executor_unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import io
from pathlib import Path
from unittest import mock
from src.device import AndroidDevice, get_device
from src.device import AndroidDevice, OsCodes, get_device
from src.base import ValidationError
from src.config import PREDEFINED_PERFETTO_CONFIGS
from tests.test_utils import generate_adb_devices_result, generate_mock_completed_process, run_cli
Expand Down Expand Up @@ -354,6 +354,175 @@

'''

TEST_ANDROID_QNX_CONFIG = f'''\
buffers: {{
size_kb: 4096
fill_policy: RING_BUFFER
}}
buffers {{
size_kb: 4096
fill_policy: RING_BUFFER
}}
buffers: {{
size_kb: 260096
fill_policy: RING_BUFFER
}}
data_sources: {{
config {{
name: "linux.process_stats"
process_stats_config {{
scan_all_processes_on_start: true
}}
}}
}}
data_sources: {{
config {{
name: "android.log"
android_log_config {{
min_prio: PRIO_VERBOSE
}}
}}
}}
data_sources {{
config {{
name: "android.packages_list"
}}
}}
data_sources: {{
config {{
name: "linux.sys_stats"
target_buffer: 1
sys_stats_config {{
stat_period_ms: 500
stat_counters: STAT_CPU_TIMES
stat_counters: STAT_FORK_COUNT
meminfo_period_ms: 1000
meminfo_counters: MEMINFO_ACTIVE_ANON
meminfo_counters: MEMINFO_ACTIVE_FILE
meminfo_counters: MEMINFO_INACTIVE_ANON
meminfo_counters: MEMINFO_INACTIVE_FILE
meminfo_counters: MEMINFO_KERNEL_STACK
meminfo_counters: MEMINFO_MLOCKED
meminfo_counters: MEMINFO_SHMEM
meminfo_counters: MEMINFO_SLAB
meminfo_counters: MEMINFO_SLAB_UNRECLAIMABLE
meminfo_counters: MEMINFO_VMALLOC_USED
meminfo_counters: MEMINFO_MEM_FREE
meminfo_counters: MEMINFO_SWAP_FREE
vmstat_period_ms: 1000
vmstat_counters: VMSTAT_PGFAULT
vmstat_counters: VMSTAT_PGMAJFAULT
vmstat_counters: VMSTAT_PGFREE
vmstat_counters: VMSTAT_PGPGIN
vmstat_counters: VMSTAT_PGPGOUT
vmstat_counters: VMSTAT_PSWPIN
vmstat_counters: VMSTAT_PSWPOUT
vmstat_counters: VMSTAT_PGSCAN_DIRECT
vmstat_counters: VMSTAT_PGSTEAL_DIRECT
vmstat_counters: VMSTAT_PGSCAN_KSWAPD
vmstat_counters: VMSTAT_PGSTEAL_KSWAPD
vmstat_counters: VMSTAT_WORKINGSET_REFAULT
cpufreq_period_ms: 500
}}
}}
}}
data_sources: {{
config {{
name: "android.surfaceflinger.frametimeline"
target_buffer: 2
}}
}}
data_sources: {{
config {{
name: "linux.ftrace"
target_buffer: 2
ftrace_config {{
ftrace_events: "dmabuf_heap/dma_heap_stat"
ftrace_events: "ftrace/print"
ftrace_events: "gpu_mem/gpu_mem_total"
ftrace_events: "ion/ion_stat"
ftrace_events: "kmem/ion_heap_grow"
ftrace_events: "kmem/ion_heap_shrink"
ftrace_events: "kmem/rss_stat"
ftrace_events: "lowmemorykiller/lowmemory_kill"
ftrace_events: "mm_event/mm_event_record"
ftrace_events: "oom/mark_victim"
ftrace_events: "oom/oom_score_adj_update"
ftrace_events: "power/cpu_frequency"
ftrace_events: "power/cpu_idle"
ftrace_events: "power/gpu_frequency"
ftrace_events: "power/suspend_resume"
ftrace_events: "power/wakeup_source_activate"
ftrace_events: "power/wakeup_source_deactivate"
ftrace_events: "sched/sched_blocked_reason"
ftrace_events: "sched/sched_process_exit"
ftrace_events: "sched/sched_process_free"
ftrace_events: "sched/sched_switch"
ftrace_events: "sched/sched_wakeup"
ftrace_events: "sched/sched_wakeup_new"
ftrace_events: "sched/sched_waking"
ftrace_events: "task/task_newtask"
ftrace_events: "task/task_rename"
ftrace_events: "vmscan/*"
ftrace_events: "workqueue/*"
atrace_categories: "aidl"
atrace_categories: "am"
atrace_categories: "dalvik"
atrace_categories: "binder_lock"
atrace_categories: "binder_driver"
atrace_categories: "bionic"
atrace_categories: "camera"
atrace_categories: "disk"
atrace_categories: "freq"
atrace_categories: "idle"
atrace_categories: "gfx"
atrace_categories: "hal"
atrace_categories: "input"
atrace_categories: "pm"
atrace_categories: "power"
atrace_categories: "res"
atrace_categories: "rro"
atrace_categories: "sched"
atrace_categories: "sm"
atrace_categories: "ss"
atrace_categories: "thermal"
atrace_categories: "video"
atrace_categories: "view"
atrace_categories: "wm"
atrace_apps: "*"
buffer_size_kb: 16384
drain_period_ms: 150
symbolize_ksyms: true
}}
}}
}}
data_sources {{
config {{
name: "qnx.kernel"
target_buffer: 2
}}
}}

trace_all_machines: true

data_sources {{
config {{
name: "perfetto.metatrace"
target_buffer: 2
}}
producer_name_filter: "perfetto.traced_probes"
}}

write_into_file: true
file_write_period_ms: 5000
max_file_size_bytes: 100000000000
flush_period_ms: 5000
incremental_state_config {{
clear_period_ms: 5000
}}

'''


class ConfigCommandExecutorUnitTest(unittest.TestCase):

Expand All @@ -362,6 +531,7 @@ def setUp(self):
self.mock_get_device_patcher = mock.patch("src.torq.get_device")
self.mock_get_device = self.mock_get_device_patcher.start()
self.mock_device = mock.create_autospec(AndroidDevice, instance=True)
self.mock_device.os.return_value = OsCodes.OS_ANDROID
self.mock_get_device.return_value = (self.mock_device, None)
self.mock_device.get_android_sdk_version.return_value = (
ANDROID_SDK_VERSION_T)
Expand All @@ -388,6 +558,12 @@ def test_config_show(self):
self.assertEqual(self.stderr_output.getvalue(), "")
self.assertEqual(self.stdout_output.getvalue(), TEST_DEFAULT_CONFIG)

def test_config_show_android_qnx(self):
run_cli("torq config show android-qnx")

self.assertEqual(self.stderr_output.getvalue(), "")
self.assertEqual(self.stdout_output.getvalue(), TEST_ANDROID_QNX_CONFIG)

@mock.patch.object(subprocess, "run", autospec=True)
def test_config_show_no_device_connected(self, mock_subprocess_run):
self.mock_get_device.return_value = (None, None)
Expand All @@ -397,6 +573,16 @@ def test_config_show_no_device_connected(self, mock_subprocess_run):
self.assertEqual(self.stderr_output.getvalue(), "")
self.assertEqual(self.stdout_output.getvalue(), TEST_DEFAULT_CONFIG)

@mock.patch.object(subprocess, "run", autospec=True)
def test_config_show_no_device_connected_android_qnx(self,
mock_subprocess_run):
self.mock_get_device.return_value = (None, None)

run_cli("torq config show android-qnx")

self.assertEqual(self.stderr_output.getvalue(), "")
self.assertEqual(self.stdout_output.getvalue(), TEST_ANDROID_QNX_CONFIG)

@mock.patch.object(subprocess, "run", autospec=True)
def test_config_show_old_android_version(self, mock_subprocess_run):
mock_subprocess_run.return_value = (
Expand Down
48 changes: 26 additions & 22 deletions tests/torq_unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,17 +343,19 @@ def test_verify_args_invalid_perfetto_config_path(self, mock_is_file):
self.assertEqual(error.message, ("Command is invalid because"
" --perfetto-config is not a"
" valid file path: unexisting-file"))
self.assertEqual(error.suggestion, ("Predefined perfetto configs can be"
" used:\n"
"\t torq --perfetto-config default\n"
"\t torq --perfetto-config"
" lightweight\n"
"\t torq --perfetto-config memory\n"
"\t torq --perfetto-config qnx\n"
"\t A filepath with a config can also"
" be used:\n"
"\t torq --perfetto-config"
" <config-filepath>"))
self.assertEqual(error.suggestion,
("Predefined perfetto configs can be"
" used:\n"
"\t torq --perfetto-config default\n"
"\t torq --perfetto-config"
" lightweight\n"
"\t torq --perfetto-config memory\n"
"\t torq --perfetto-config qnx\n"
"\t torq --perfetto-config android-qnx\n"
"\t A filepath with a config can also"
" be used:\n"
"\t torq --perfetto-config"
" <config-filepath>"))

args = parse_cli("torq --perfetto-config mock-directory")

Expand All @@ -362,17 +364,19 @@ def test_verify_args_invalid_perfetto_config_path(self, mock_is_file):
self.assertEqual(error.message, ("Command is invalid because"
" --perfetto-config is not a"
" valid file path: mock-directory"))
self.assertEqual(error.suggestion, ("Predefined perfetto configs can be"
" used:\n"
"\t torq --perfetto-config default\n"
"\t torq --perfetto-config"
" lightweight\n"
"\t torq --perfetto-config memory\n"
"\t torq --perfetto-config qnx\n"
"\t A filepath with a config can also"
" be used:\n"
"\t torq --perfetto-config"
" <config-filepath>"))
self.assertEqual(error.suggestion,
("Predefined perfetto configs can be"
" used:\n"
"\t torq --perfetto-config default\n"
"\t torq --perfetto-config"
" lightweight\n"
"\t torq --perfetto-config memory\n"
"\t torq --perfetto-config qnx\n"
"\t torq --perfetto-config android-qnx\n"
"\t A filepath with a config can also"
" be used:\n"
"\t torq --perfetto-config"
" <config-filepath>"))

def test_verify_args_from_user_and_event_valid_dependency(self):
args = parse_cli(("torq -e user-switch --from-user 0"
Expand Down
Loading