xref: /aosp_15_r20/system/extras/torq/config_builder.py (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1#
2# Copyright (C) 2024 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17import textwrap
18from validation_error import ValidationError
19
20ANDROID_SDK_VERSION_T = 33
21
22
23def create_ftrace_events_string(predefined_ftrace_events,
24    excluded_ftrace_events, included_ftrace_events):
25  if excluded_ftrace_events is not None:
26    for event in excluded_ftrace_events:
27      if event in predefined_ftrace_events:
28        predefined_ftrace_events.remove(event)
29      else:
30        return None, ValidationError(("Cannot remove ftrace event %s from"
31                                      " config because it is not one"
32                                      " of the config's ftrace events."
33                                      % event),
34                                     ("Please specify one of the following"
35                                      " possible ftrace events:\n\t %s"
36                                      % "\n\t ".join(predefined_ftrace_events)))
37
38  if included_ftrace_events is not None:
39    for event in included_ftrace_events:
40      if event not in predefined_ftrace_events:
41        predefined_ftrace_events.append(event)
42      else:
43        return None, ValidationError(("Cannot add ftrace event %s to config"
44                                      " because it is already one of the"
45                                      " config's ftrace events." % event),
46                                     ("Please do not specify any of the"
47                                      " following ftrace events that are"
48                                      " already included:\n\t %s"
49                                      % "\n\t ".join(predefined_ftrace_events)))
50
51  ftrace_events_string = ("ftrace_events: \"%s\"" % ("""\"
52          ftrace_events: \"""".join(predefined_ftrace_events)))
53  return ftrace_events_string, None
54
55
56def build_default_config(command, android_sdk_version):
57  if command.dur_ms is None:
58    # This is always defined because it has a default value that is always
59    # set in torq.py.
60    raise ValueError("Cannot create config because a valid dur_ms was not set.")
61  predefined_ftrace_events = [
62      "dmabuf_heap/dma_heap_stat",
63      "ftrace/print",
64      "gpu_mem/gpu_mem_total",
65      "ion/ion_stat",
66      "kmem/ion_heap_grow",
67      "kmem/ion_heap_shrink",
68      "kmem/rss_stat",
69      "lowmemorykiller/lowmemory_kill",
70      "mm_event/mm_event_record",
71      "oom/mark_victim",
72      "oom/oom_score_adj_update",
73      "power/cpu_frequency",
74      "power/cpu_idle",
75      "power/gpu_frequency",
76      "power/suspend_resume",
77      "power/wakeup_source_activate",
78      "power/wakeup_source_deactivate",
79      "sched/sched_blocked_reason",
80      "sched/sched_process_exit",
81      "sched/sched_process_free",
82      "sched/sched_switch",
83      "sched/sched_wakeup",
84      "sched/sched_wakeup_new",
85      "sched/sched_waking",
86      "task/task_newtask",
87      "task/task_rename",
88      "vmscan/*",
89      "workqueue/*",
90  ]
91  ftrace_events_string, error = create_ftrace_events_string(
92      predefined_ftrace_events, command.excluded_ftrace_events,
93      command.included_ftrace_events)
94  if error is not None:
95    return None, error
96  cpufreq_period_string = "cpufreq_period_ms: 500"
97  if android_sdk_version < ANDROID_SDK_VERSION_T:
98    cpufreq_period_string = ""
99  config = f'''\
100    <<EOF
101
102    buffers: {{
103      size_kb: 4096
104      fill_policy: RING_BUFFER
105    }}
106    buffers {{
107      size_kb: 4096
108      fill_policy: RING_BUFFER
109    }}
110    buffers: {{
111      size_kb: 260096
112      fill_policy: RING_BUFFER
113    }}
114
115    data_sources: {{
116      config {{
117        name: "linux.process_stats"
118        process_stats_config {{
119          scan_all_processes_on_start: true
120        }}
121      }}
122    }}
123
124    data_sources: {{
125      config {{
126        name: "android.log"
127        android_log_config {{
128        }}
129      }}
130    }}
131
132    data_sources {{
133      config {{
134        name: "android.packages_list"
135      }}
136    }}
137
138    data_sources: {{
139      config {{
140        name: "linux.sys_stats"
141        target_buffer: 1
142        sys_stats_config {{
143          stat_period_ms: 500
144          stat_counters: STAT_CPU_TIMES
145          stat_counters: STAT_FORK_COUNT
146          meminfo_period_ms: 1000
147          meminfo_counters: MEMINFO_ACTIVE_ANON
148          meminfo_counters: MEMINFO_ACTIVE_FILE
149          meminfo_counters: MEMINFO_INACTIVE_ANON
150          meminfo_counters: MEMINFO_INACTIVE_FILE
151          meminfo_counters: MEMINFO_KERNEL_STACK
152          meminfo_counters: MEMINFO_MLOCKED
153          meminfo_counters: MEMINFO_SHMEM
154          meminfo_counters: MEMINFO_SLAB
155          meminfo_counters: MEMINFO_SLAB_UNRECLAIMABLE
156          meminfo_counters: MEMINFO_VMALLOC_USED
157          meminfo_counters: MEMINFO_MEM_FREE
158          meminfo_counters: MEMINFO_SWAP_FREE
159          vmstat_period_ms: 1000
160          vmstat_counters: VMSTAT_PGFAULT
161          vmstat_counters: VMSTAT_PGMAJFAULT
162          vmstat_counters: VMSTAT_PGFREE
163          vmstat_counters: VMSTAT_PGPGIN
164          vmstat_counters: VMSTAT_PGPGOUT
165          vmstat_counters: VMSTAT_PSWPIN
166          vmstat_counters: VMSTAT_PSWPOUT
167          vmstat_counters: VMSTAT_PGSCAN_DIRECT
168          vmstat_counters: VMSTAT_PGSTEAL_DIRECT
169          vmstat_counters: VMSTAT_PGSCAN_KSWAPD
170          vmstat_counters: VMSTAT_PGSTEAL_KSWAPD
171          vmstat_counters: VMSTAT_WORKINGSET_REFAULT
172          {cpufreq_period_string}
173        }}
174      }}
175    }}
176
177    data_sources: {{
178      config {{
179        name: "android.surfaceflinger.frametimeline"
180        target_buffer: 2
181      }}
182    }}
183
184    data_sources: {{
185      config {{
186        name: "linux.ftrace"
187        target_buffer: 2
188        ftrace_config {{
189          {ftrace_events_string}
190          atrace_categories: "aidl"
191          atrace_categories: "am"
192          atrace_categories: "dalvik"
193          atrace_categories: "binder_lock"
194          atrace_categories: "binder_driver"
195          atrace_categories: "bionic"
196          atrace_categories: "camera"
197          atrace_categories: "disk"
198          atrace_categories: "freq"
199          atrace_categories: "idle"
200          atrace_categories: "gfx"
201          atrace_categories: "hal"
202          atrace_categories: "input"
203          atrace_categories: "pm"
204          atrace_categories: "power"
205          atrace_categories: "res"
206          atrace_categories: "rro"
207          atrace_categories: "sched"
208          atrace_categories: "sm"
209          atrace_categories: "ss"
210          atrace_categories: "thermal"
211          atrace_categories: "video"
212          atrace_categories: "view"
213          atrace_categories: "wm"
214          atrace_apps: "lmkd"
215          atrace_apps: "system_server"
216          atrace_apps: "com.android.systemui"
217          atrace_apps: "com.google.android.gms"
218          atrace_apps: "com.google.android.gms.persistent"
219          atrace_apps: "android:ui"
220          atrace_apps: "com.google.android.apps.maps"
221          atrace_apps: "*"
222          buffer_size_kb: 16384
223          drain_period_ms: 150
224          symbolize_ksyms: true
225        }}
226      }}
227    }}
228    duration_ms: {command.dur_ms}
229    write_into_file: true
230    file_write_period_ms: 5000
231    max_file_size_bytes: 100000000000
232    flush_period_ms: 5000
233    incremental_state_config {{
234      clear_period_ms: 5000
235    }}
236
237    EOF'''
238  return textwrap.dedent(config), None
239
240
241def build_lightweight_config(command, android_sdk_version):
242  raise NotImplementedError
243
244
245def build_memory_config(command, android_sdk_version):
246  raise NotImplementedError
247
248
249PREDEFINED_PERFETTO_CONFIGS = {
250    'default': build_default_config,
251    'lightweight': build_lightweight_config,
252    'memory': build_memory_config
253}
254
255
256def build_custom_config(command):
257  file_content = ""
258  duration_prefix = "duration_ms:"
259  appended_duration = duration_prefix + " " + str(command.dur_ms)
260  try:
261    with open(command.perfetto_config, "r") as file:
262      for line in file:
263        stripped_line = line.strip()
264        if stripped_line.startswith(duration_prefix):
265          duration = stripped_line[len(duration_prefix):].strip()
266          appended_duration = ""
267          command.dur_ms = int(duration)
268        file_content += line
269  except ValueError:
270    return None, ValidationError(("Failed to parse custom perfetto-config on"
271                                  " local file path: %s. Invalid duration_ms"
272                                  " field in config."
273                                  % command.perfetto_config),
274                                 ("Make sure the perfetto config passed via"
275                                  " arguments has a valid duration_ms value."))
276  except Exception as e:
277    return None, ValidationError(("Failed to parse custom perfetto-config on"
278                                  " local file path: %s. %s"
279                                  % (command.perfetto_config, str(e))), None)
280  config_string = f"<<EOF\n\n{file_content}\n{appended_duration}\n\nEOF"
281  return config_string, None
282