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