xref: /aosp_15_r20/frameworks/native/cmds/atrace/atrace.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright (C) 2012 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 
17 #define LOG_TAG "atrace"
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <getopt.h>
22 #include <inttypes.h>
23 #include <signal.h>
24 #include <stdarg.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30 #include <unistd.h>
31 #include <zlib.h>
32 
33 #include <fstream>
34 #include <memory>
35 
36 #include <binder/IBinder.h>
37 #include <binder/IServiceManager.h>
38 #include <binder/Parcel.h>
39 
40 #include <android/hardware/atrace/1.0/IAtraceDevice.h>
41 #include <android/hidl/manager/1.0/IServiceManager.h>
42 #include <hidl/ServiceManagement.h>
43 
44 #include <utils/String8.h>
45 #include <utils/Timers.h>
46 #include <utils/Tokenizer.h>
47 #include <utils/Trace.h>
48 #include <android-base/file.h>
49 #include <android-base/macros.h>
50 #include <android-base/properties.h>
51 #include <android-base/strings.h>
52 #include <android-base/stringprintf.h>
53 
54 using namespace android;
55 using hardware::hidl_vec;
56 using hardware::hidl_string;
57 using hardware::Return;
58 using hardware::atrace::V1_0::IAtraceDevice;
59 using hardware::atrace::V1_0::Status;
60 using hardware::atrace::V1_0::toString;
61 
62 using std::string;
63 
64 #define MAX_SYS_FILES 13
65 
66 const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
67 const char* k_userInitiatedTraceProperty = "debug.atrace.user_initiated";
68 
69 const char* k_tracePreferSdkProperty = "debug.atrace.prefer_sdk";
70 const char* k_traceAppsNumberProperty = "debug.atrace.app_number";
71 const char* k_traceAppsPropertyTemplate = "debug.atrace.app_%d";
72 const char* k_coreServiceCategory = "core_services";
73 const char* k_coreServicesProp = "ro.atrace.core.services";
74 
75 const char* kVendorCategoriesPath = "/vendor/etc/atrace/atrace_categories.txt";
76 
77 typedef enum { OPT, REQ } requiredness;
78 
79 struct TracingCategory {
80     // The name identifying the category.
81     const char* name;
82 
83     // A longer description of the category.
84     const char* longname;
85 
86     // The userland tracing tags that the category enables.
87     uint64_t tags;
88 
89     // The fname==NULL terminated list of /sys/ files that the category
90     // enables.
91     struct {
92         // Whether the file must be writable in order to enable the tracing
93         // category.
94         requiredness required;
95 
96         // The path to the enable file.
97         const char* path;
98     } sysfiles[MAX_SYS_FILES];
99 };
100 
101 /* Tracing categories */
102 static const TracingCategory k_categories[] = {
103     { "gfx",        "Graphics",                 ATRACE_TAG_GRAPHICS, {
104         { OPT,      "events/gpu_mem/gpu_mem_total/enable" },
105     } },
106     { "input",      "Input",                    ATRACE_TAG_INPUT, { } },
107     { "view",       "View System",              ATRACE_TAG_VIEW, { } },
108     { "webview",    "WebView",                  ATRACE_TAG_WEBVIEW, { } },
109     { "wm",         "Window Manager",           ATRACE_TAG_WINDOW_MANAGER, { } },
110     { "am",         "Activity Manager",         ATRACE_TAG_ACTIVITY_MANAGER, { } },
111     { "sm",         "Sync Manager",             ATRACE_TAG_SYNC_MANAGER, { } },
112     { "audio",      "Audio",                    ATRACE_TAG_AUDIO, { } },
113     { "video",      "Video",                    ATRACE_TAG_VIDEO, { } },
114     { "camera",     "Camera",                   ATRACE_TAG_CAMERA, { } },
115     { "hal",        "Hardware Modules",         ATRACE_TAG_HAL, { } },
116     { "res",        "Resource Loading",         ATRACE_TAG_RESOURCES, { } },
117     { "dalvik",     "Dalvik VM",                ATRACE_TAG_DALVIK, { } },
118     { "rs",         "RenderScript",             ATRACE_TAG_RS, { } },
119     { "bionic",     "Bionic C Library",         ATRACE_TAG_BIONIC, { } },
120     { "power",      "Power Management",         ATRACE_TAG_POWER, { } },
121     { "pm",         "Package Manager",          ATRACE_TAG_PACKAGE_MANAGER, { } },
122     { "ss",         "System Server",            ATRACE_TAG_SYSTEM_SERVER, { } },
123     { "database",   "Database",                 ATRACE_TAG_DATABASE, { } },
124     { "network",    "Network",                  ATRACE_TAG_NETWORK, { } },
125     { "adb",        "ADB",                      ATRACE_TAG_ADB, { } },
126     { "vibrator",   "Vibrator",                 ATRACE_TAG_VIBRATOR, { } },
127     { "aidl",       "AIDL calls",               ATRACE_TAG_AIDL, { } },
128     { "nnapi",      "NNAPI",                    ATRACE_TAG_NNAPI, { } },
129     { "rro",        "Runtime Resource Overlay", ATRACE_TAG_RRO, { } },
130     { k_coreServiceCategory, "Core services", 0, { } },
131     { "sched",      "CPU Scheduling",   0, {
132         { REQ,      "events/sched/sched_switch/enable" },
133         { REQ,      "events/sched/sched_wakeup/enable" },
134         { OPT,      "events/sched/sched_waking/enable" },
135         { OPT,      "events/sched/sched_blocked_reason/enable" },
136         { OPT,      "events/sched/sched_cpu_hotplug/enable" },
137         { OPT,      "events/sched/sched_pi_setprio/enable" },
138         { OPT,      "events/sched/sched_process_exit/enable" },
139         { OPT,      "events/cgroup/enable" },
140         { OPT,      "events/oom/oom_score_adj_update/enable" },
141         { OPT,      "events/task/task_rename/enable" },
142         { OPT,      "events/task/task_newtask/enable" },
143     } },
144     { "irq",        "IRQ Events",   0, {
145         { REQ,      "events/irq/enable" },
146         { OPT,      "events/ipi/enable" },
147     } },
148     { "irqoff",     "IRQ-disabled code section tracing", 0, {
149         { REQ,      "events/preemptirq/irq_enable/enable" },
150         { REQ,      "events/preemptirq/irq_disable/enable" },
151     } },
152     { "preemptoff", "Preempt-disabled code section tracing", 0, {
153         { REQ,      "events/preemptirq/preempt_enable/enable" },
154         { REQ,      "events/preemptirq/preempt_disable/enable" },
155     } },
156     { "i2c",        "I2C Events",   0, {
157         { REQ,      "events/i2c/enable" },
158         { REQ,      "events/i2c/i2c_read/enable" },
159         { REQ,      "events/i2c/i2c_write/enable" },
160         { REQ,      "events/i2c/i2c_result/enable" },
161         { REQ,      "events/i2c/i2c_reply/enable" },
162         { OPT,      "events/i2c/smbus_read/enable" },
163         { OPT,      "events/i2c/smbus_write/enable" },
164         { OPT,      "events/i2c/smbus_result/enable" },
165         { OPT,      "events/i2c/smbus_reply/enable" },
166     } },
167     { "freq",       "CPU Frequency",    0, {
168         { REQ,      "events/power/cpu_frequency/enable" },
169         { OPT,      "events/power/clock_set_rate/enable" },
170         { OPT,      "events/power/clock_disable/enable" },
171         { OPT,      "events/power/clock_enable/enable" },
172         { OPT,      "events/clk/clk_set_rate/enable" },
173         { OPT,      "events/clk/clk_disable/enable" },
174         { OPT,      "events/clk/clk_enable/enable" },
175         { OPT,      "events/power/cpu_frequency_limits/enable" },
176         { OPT,      "events/power/suspend_resume/enable" },
177         { OPT,      "events/cpuhp/cpuhp_enter/enable" },
178         { OPT,      "events/cpuhp/cpuhp_exit/enable" },
179         { OPT,      "events/cpuhp/cpuhp_pause/enable" },
180     } },
181     { "membus",     "Memory Bus Utilization", 0, {
182         { REQ,      "events/memory_bus/enable" },
183     } },
184     { "idle",       "CPU Idle",         0, {
185         { REQ,      "events/power/cpu_idle/enable" },
186     } },
187     { "disk",       "Disk I/O",         0, {
188         { OPT,      "events/f2fs/f2fs_sync_file_enter/enable" },
189         { OPT,      "events/f2fs/f2fs_sync_file_exit/enable" },
190         { OPT,      "events/f2fs/f2fs_write_begin/enable" },
191         { OPT,      "events/f2fs/f2fs_write_end/enable" },
192         { OPT,      "events/f2fs/f2fs_iostat/enable" },
193         { OPT,      "events/f2fs/f2fs_iostat_latency/enable" },
194         { OPT,      "events/ext4/ext4_da_write_begin/enable" },
195         { OPT,      "events/ext4/ext4_da_write_end/enable" },
196         { OPT,      "events/ext4/ext4_sync_file_enter/enable" },
197         { OPT,      "events/ext4/ext4_sync_file_exit/enable" },
198         { OPT,      "events/block/block_bio_queue/enable" },
199         { OPT,      "events/block/block_bio_complete/enable" },
200         { OPT,      "events/ufs/ufshcd_command/enable" },
201     } },
202     { "mmc",        "eMMC commands",    0, {
203         { REQ,      "events/mmc/enable" },
204     } },
205     { "load",       "CPU Load",         0, {
206         { REQ,      "events/cpufreq_interactive/enable" },
207     } },
208     { "sync",       "Synchronization",  0, {
209         // linux kernel < 4.9
210         { OPT,      "events/sync/enable" },
211         // linux kernel == 4.9.x
212         { OPT,      "events/fence/enable" },
213         // linux kernel > 4.9
214         { OPT,      "events/dma_fence/enable" },
215     } },
216     { "workq",      "Kernel Workqueues", 0, {
217         { REQ,      "events/workqueue/enable" },
218     } },
219     { "memreclaim", "Kernel Memory Reclaim", 0, {
220         { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_begin/enable" },
221         { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
222         { REQ,      "events/vmscan/mm_vmscan_kswapd_wake/enable" },
223         { REQ,      "events/vmscan/mm_vmscan_kswapd_sleep/enable" },
224         { OPT,      "events/lowmemorykiller/enable" },
225     } },
226     { "regulators",  "Voltage and Current Regulators", 0, {
227         { REQ,      "events/regulator/enable" },
228     } },
229     { "binder_driver", "Binder Kernel driver", 0, {
230         { REQ,      "events/binder/binder_transaction/enable" },
231         { REQ,      "events/binder/binder_transaction_received/enable" },
232         { REQ,      "events/binder/binder_transaction_alloc_buf/enable" },
233         { OPT,      "events/binder/binder_set_priority/enable" },
234     } },
235     { "binder_lock", "Binder global lock trace", 0, {
236         { OPT,      "events/binder/binder_lock/enable" },
237         { OPT,      "events/binder/binder_locked/enable" },
238         { OPT,      "events/binder/binder_unlock/enable" },
239     } },
240     { "pagecache",  "Page cache", 0, {
241         { REQ,      "events/filemap/enable" },
242     } },
243     { "memory",  "Memory", 0, {
244         { OPT,      "events/mm_event/mm_event_record/enable" },
245         { OPT,      "events/synthetic/rss_stat_throttled/enable" },
246         { OPT,      "events/kmem/ion_heap_grow/enable" },
247         { OPT,      "events/kmem/ion_heap_shrink/enable" },
248         { OPT,      "events/ion/ion_stat/enable" },
249         { OPT,      "events/gpu_mem/gpu_mem_total/enable" },
250         { OPT,      "events/fastrpc/fastrpc_dma_stat/enable" },
251     } },
252     { "thermal",  "Thermal event", ATRACE_TAG_THERMAL, {
253         { REQ,      "events/thermal/thermal_temperature/enable" },
254         { OPT,      "events/thermal/cdev_update/enable" },
255     } },
256 };
257 
258 // A category in the vendor categories file.
259 struct TracingVendorFileCategory {
260     // The name identifying the category.
261     std::string name;
262 
263     // If the category is enabled through command.
264     bool enabled = false;
265 
266     // Paths to the ftrace enable files (relative to g_traceFolder).
267     std::vector<std::string> ftrace_enable_paths;
268 };
269 
270 // A category in the vendor HIDL HAL.
271 struct TracingVendorHalCategory {
272     // The name identifying the category.
273     std::string name;
274 
275     // A longer description of the category.
276     std::string description;
277 
278     // If the category is enabled through command.
279     bool enabled;
280 
TracingVendorHalCategoryTracingVendorHalCategory281     TracingVendorHalCategory(string&& name, string&& description, bool enabled)
282           : name(std::move(name)), description(std::move(description)), enabled(enabled) {}
283 };
284 
285 /* Command line options */
286 static int g_traceDurationSeconds = 5;
287 static bool g_traceOverwrite = false;
288 static int g_traceBufferSizeKB = 2048;
289 static bool g_compress = false;
290 static bool g_nohup = false;
291 static int g_initialSleepSecs = 0;
292 static const char* g_categoriesFile = nullptr;
293 static const char* g_kernelTraceFuncs = nullptr;
294 static const char* g_debugAppCmdLine = "";
295 static const char* g_outputFile = nullptr;
296 
297 /* Global state */
298 static bool g_traceAborted = false;
299 static bool g_categoryEnables[arraysize(k_categories)] = {};
300 static std::string g_traceFolder;
301 static std::vector<TracingVendorFileCategory> g_vendorFileCategories;
302 static sp<IAtraceDevice> g_atraceHal;
303 static std::vector<TracingVendorHalCategory> g_vendorHalCategories;
304 
305 /* Sys file paths */
306 static const char* k_traceClockPath =
307     "trace_clock";
308 
309 static const char* k_traceBufferSizePath =
310     "buffer_size_kb";
311 
312 static const char* k_tracingOverwriteEnablePath =
313     "options/overwrite";
314 
315 static const char* k_currentTracerPath =
316     "current_tracer";
317 
318 static const char* k_printTgidPath =
319     "options/print-tgid";
320 
321 static const char* k_recordTgidPath =
322     "options/record-tgid";
323 
324 static const char* k_funcgraphAbsTimePath =
325     "options/funcgraph-abstime";
326 
327 static const char* k_funcgraphCpuPath =
328     "options/funcgraph-cpu";
329 
330 static const char* k_funcgraphProcPath =
331     "options/funcgraph-proc";
332 
333 static const char* k_ftraceFilterPath =
334     "set_ftrace_filter";
335 
336 static const char* k_tracingOnPath =
337     "tracing_on";
338 
339 static const char* k_tracePath =
340     "trace";
341 
342 static const char* k_traceStreamPath =
343     "trace_pipe";
344 
345 static const char* k_traceMarkerPath =
346     "trace_marker";
347 
348 // Check whether a file exists.
fileExists(const char * filename)349 static bool fileExists(const char* filename) {
350     return access((g_traceFolder + filename).c_str(), F_OK) != -1;
351 }
352 
353 // Check whether a file is writable.
fileIsWritable(const char * filename)354 static bool fileIsWritable(const char* filename) {
355     return access((g_traceFolder + filename).c_str(), W_OK) != -1;
356 }
357 
358 // Truncate a file.
truncateFile(const char * path)359 static bool truncateFile(const char* path)
360 {
361     // This uses creat rather than truncate because some of the debug kernel
362     // device nodes (e.g. k_ftraceFilterPath) currently aren't changed by
363     // calls to truncate, but they are cleared by calls to creat.
364     int traceFD = creat((g_traceFolder + path).c_str(), 0);
365     if (traceFD == -1) {
366         fprintf(stderr, "error truncating %s: %s (%d)\n", (g_traceFolder + path).c_str(),
367             strerror(errno), errno);
368         return false;
369     }
370 
371     close(traceFD);
372 
373     return true;
374 }
375 
_writeStr(const char * filename,const char * str,int flags)376 static bool _writeStr(const char* filename, const char* str, int flags)
377 {
378     std::string fullFilename = g_traceFolder + filename;
379     int fd = open(fullFilename.c_str(), flags);
380     if (fd == -1) {
381         fprintf(stderr, "error opening %s: %s (%d)\n", fullFilename.c_str(),
382                 strerror(errno), errno);
383         return false;
384     }
385 
386     bool ok = true;
387     ssize_t len = strlen(str);
388     if (write(fd, str, len) != len) {
389         fprintf(stderr, "error writing to %s: %s (%d)\n", fullFilename.c_str(),
390                 strerror(errno), errno);
391         ok = false;
392     }
393 
394     close(fd);
395 
396     return ok;
397 }
398 
399 // Write a string to a file, returning true if the write was successful.
writeStr(const char * filename,const char * str)400 static bool writeStr(const char* filename, const char* str)
401 {
402     return _writeStr(filename, str, O_WRONLY);
403 }
404 
405 // Append a string to a file, returning true if the write was successful.
appendStr(const char * filename,const char * str)406 static bool appendStr(const char* filename, const char* str)
407 {
408     return _writeStr(filename, str, O_APPEND|O_WRONLY);
409 }
410 
writeClockSyncMarker()411 static void writeClockSyncMarker()
412 {
413   char buffer[128];
414   int len = 0;
415   int fd = open((g_traceFolder + k_traceMarkerPath).c_str(), O_WRONLY);
416   if (fd == -1) {
417       fprintf(stderr, "error opening %s: %s (%d)\n", k_traceMarkerPath,
418               strerror(errno), errno);
419       return;
420   }
421   float now_in_seconds = systemTime(CLOCK_MONOTONIC) / 1000000000.0f;
422 
423   len = snprintf(buffer, 128, "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
424   if (write(fd, buffer, len) != len) {
425       fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
426   }
427 
428   int64_t realtime_in_ms = systemTime(CLOCK_REALTIME) / 1000000;
429   len = snprintf(buffer, 128, "trace_event_clock_sync: realtime_ts=%" PRId64 "\n", realtime_in_ms);
430   if (write(fd, buffer, len) != len) {
431       fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
432   }
433 
434   close(fd);
435 }
436 
437 // Enable or disable a kernel option by writing a "1" or a "0" into a /sys
438 // file.
setKernelOptionEnable(const char * filename,bool enable)439 static bool setKernelOptionEnable(const char* filename, bool enable)
440 {
441     return writeStr(filename, enable ? "1" : "0");
442 }
443 
444 // Check whether the category is supported on the device with the current
445 // rootness.  A category is supported only if all its required /sys/ files are
446 // writable and if enabling the category will enable one or more tracing tags
447 // or /sys/ files.
isCategorySupported(const TracingCategory & category)448 static bool isCategorySupported(const TracingCategory& category)
449 {
450     if (strcmp(category.name, k_coreServiceCategory) == 0) {
451         return !android::base::GetProperty(k_coreServicesProp, "").empty();
452     }
453 
454     bool ok = category.tags != 0;
455     for (int i = 0; i < MAX_SYS_FILES; i++) {
456         const char* path = category.sysfiles[i].path;
457         bool req = category.sysfiles[i].required == REQ;
458         if (path != nullptr) {
459             if (fileIsWritable(path)) {
460                 ok = true;
461             } else if (req) {
462                 return false;
463             }
464         }
465     }
466     return ok;
467 }
468 
469 // Check whether the category would be supported on the device if the user
470 // were root.  This function assumes that root is able to write to any file
471 // that exists.  It performs the same logic as isCategorySupported, but it
472 // uses file existence rather than writability in the /sys/ file checks.
isCategorySupportedForRoot(const TracingCategory & category)473 static bool isCategorySupportedForRoot(const TracingCategory& category)
474 {
475     bool ok = category.tags != 0;
476     for (int i = 0; i < MAX_SYS_FILES; i++) {
477         const char* path = category.sysfiles[i].path;
478         bool req = category.sysfiles[i].required == REQ;
479         if (path != nullptr) {
480             if (req) {
481                 if (!fileExists(path)) {
482                     return false;
483                 } else {
484                     ok = true;
485                 }
486             } else {
487                 ok |= fileExists(path);
488             }
489         }
490     }
491     return ok;
492 }
493 
494 // Enable or disable overwriting of the kernel trace buffers.  Disabling this
495 // will cause tracing to stop once the trace buffers have filled up.
setTraceOverwriteEnable(bool enable)496 static bool setTraceOverwriteEnable(bool enable)
497 {
498     return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
499 }
500 
501 // Set the user initiated trace property
setUserInitiatedTraceProperty(bool enable)502 static bool setUserInitiatedTraceProperty(bool enable)
503 {
504     if (!android::base::SetProperty(k_userInitiatedTraceProperty, enable ? "1" : "")) {
505         fprintf(stderr, "error setting user initiated strace system property\n");
506         return false;
507     }
508     return true;
509 }
510 
511 // Enable or disable kernel tracing.
setTracingEnabled(bool enable)512 static bool setTracingEnabled(bool enable)
513 {
514     return setKernelOptionEnable(k_tracingOnPath, enable);
515 }
516 
517 // Clear the contents of the kernel trace.
clearTrace()518 static bool clearTrace()
519 {
520     return truncateFile(k_tracePath);
521 }
522 
523 // Set the size of the kernel's trace buffer in kilobytes.
setTraceBufferSizeKB(int size)524 static bool setTraceBufferSizeKB(int size)
525 {
526     char str[32] = "1";
527     if (size < 1) {
528         size = 1;
529     }
530     snprintf(str, 32, "%d", size);
531     return writeStr(k_traceBufferSizePath, str);
532 }
533 
534 // Set the clock to the best available option while tracing. Use 'boot' if it's
535 // available; otherwise, use 'mono'. If neither are available use 'global'.
536 // Any write to the trace_clock sysfs file will reset the buffer, so only
537 // update it if the requested value is not the current value.
setClock()538 static bool setClock()
539 {
540     std::ifstream clockFile((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
541     std::string clockStr((std::istreambuf_iterator<char>(clockFile)),
542         std::istreambuf_iterator<char>());
543 
544     std::string newClock;
545     if (clockStr.find("boot") != std::string::npos) {
546         newClock = "boot";
547     } else if (clockStr.find("mono") != std::string::npos) {
548         newClock = "mono";
549     } else {
550         newClock = "global";
551     }
552 
553     size_t begin = clockStr.find('[') + 1;
554     size_t end = clockStr.find(']');
555     if (newClock.compare(0, std::string::npos, clockStr, begin, end-begin) == 0) {
556         return true;
557     }
558     return writeStr(k_traceClockPath, newClock.c_str());
559 }
560 
setPrintTgidEnableIfPresent(bool enable)561 static bool setPrintTgidEnableIfPresent(bool enable)
562 {
563     // Pre-4.13 this was options/print-tgid as an android-specific option.
564     // In 4.13+ this is an upstream option called options/record-tgid
565     // Both options produce the same ftrace format change
566     if (fileExists(k_printTgidPath)) {
567         return setKernelOptionEnable(k_printTgidPath, enable);
568     }
569     if (fileExists(k_recordTgidPath)) {
570         return setKernelOptionEnable(k_recordTgidPath, enable);
571     }
572     return true;
573 }
574 
575 // Set the trace tags that userland tracing uses, and poke the running
576 // processes to pick up the new value.
setTagsProperty(uint64_t tags)577 static bool setTagsProperty(uint64_t tags)
578 {
579     std::string value = android::base::StringPrintf("%#" PRIx64, tags);
580     if (!android::base::SetProperty(k_traceTagsProperty, value)) {
581         fprintf(stderr, "error setting trace tags system property\n");
582         return false;
583     }
584     return true;
585 }
586 
clearAppProperties()587 static void clearAppProperties()
588 {
589     if (!android::base::SetProperty(k_traceAppsNumberProperty, "")) {
590         fprintf(stderr, "failed to clear system property: %s",
591               k_traceAppsNumberProperty);
592     }
593 }
594 
595 // Set the property that's read by userspace to prefer the perfetto SDK.
setPreferSdkProperty(uint64_t tags)596 static bool setPreferSdkProperty(uint64_t tags)
597 {
598     std::string value = android::base::StringPrintf("%#" PRIx64, tags);
599     if (!android::base::SetProperty(k_tracePreferSdkProperty, value)) {
600         fprintf(stderr, "error setting prefer_sdk system property\n");
601         return false;
602     }
603     return true;
604 }
605 
606 // Set the system property that indicates which apps should perform
607 // application-level tracing.
setAppCmdlineProperty(char * cmdline)608 static bool setAppCmdlineProperty(char* cmdline)
609 {
610     int i = 0;
611     char* start = cmdline;
612     while (start != nullptr) {
613         char* end = strchr(start, ',');
614         if (end != nullptr) {
615             *end = '\0';
616             end++;
617         }
618         std::string key = android::base::StringPrintf(k_traceAppsPropertyTemplate, i);
619         if (!android::base::SetProperty(key, start)) {
620             fprintf(stderr, "error setting trace app %d property to %s\n", i, key.c_str());
621             clearAppProperties();
622             return false;
623         }
624         start = end;
625         i++;
626     }
627 
628     std::string value = android::base::StringPrintf("%d", i);
629     if (!android::base::SetProperty(k_traceAppsNumberProperty, value)) {
630         fprintf(stderr, "error setting trace app number property to %s\n", value.c_str());
631         clearAppProperties();
632         return false;
633     }
634     return true;
635 }
636 
637 // Disable all /sys/ enable files.
disableKernelTraceEvents()638 static bool disableKernelTraceEvents() {
639     bool ok = true;
640     for (size_t i = 0; i < arraysize(k_categories); i++) {
641         const TracingCategory &c = k_categories[i];
642         for (int j = 0; j < MAX_SYS_FILES; j++) {
643             const char* path = c.sysfiles[j].path;
644             if (path != nullptr && fileIsWritable(path)) {
645                 ok &= setKernelOptionEnable(path, false);
646             }
647         }
648     }
649     for (const TracingVendorFileCategory& c : g_vendorFileCategories) {
650         for (const std::string& path : c.ftrace_enable_paths) {
651             if (fileIsWritable(path.c_str())) {
652                 ok &= setKernelOptionEnable(path.c_str(), false);
653             }
654         }
655     }
656     return ok;
657 }
658 
659 // Verify that the comma separated list of functions are being traced by the
660 // kernel.
verifyKernelTraceFuncs(const char * funcs)661 static bool verifyKernelTraceFuncs(const char* funcs)
662 {
663     std::string buf;
664     if (!android::base::ReadFileToString(g_traceFolder + k_ftraceFilterPath, &buf)) {
665          fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
666             strerror(errno), errno);
667          return false;
668     }
669 
670     String8 funcList = String8::format("\n%s",buf.c_str());
671 
672     // Make sure that every function listed in funcs is in the list we just
673     // read from the kernel, except for wildcard inputs.
674     bool ok = true;
675     char* myFuncs = strdup(funcs);
676     char* func = strtok(myFuncs, ",");
677     while (func) {
678         if (!strchr(func, '*')) {
679             String8 fancyFunc = String8::format("\n%s\n", func);
680             bool found = funcList.find(fancyFunc.c_str(), 0) >= 0;
681             if (!found || func[0] == '\0') {
682                 fprintf(stderr, "error: \"%s\" is not a valid kernel function "
683                         "to trace.\n", func);
684                 ok = false;
685             }
686         }
687         func = strtok(nullptr, ",");
688     }
689     free(myFuncs);
690     return ok;
691 }
692 
693 // Set the comma separated list of functions that the kernel is to trace.
setKernelTraceFuncs(const char * funcs)694 static bool setKernelTraceFuncs(const char* funcs)
695 {
696     bool ok = true;
697 
698     if (funcs == nullptr || funcs[0] == '\0') {
699         // Disable kernel function tracing.
700         if (fileIsWritable(k_currentTracerPath)) {
701             ok &= writeStr(k_currentTracerPath, "nop");
702         }
703         if (fileIsWritable(k_ftraceFilterPath)) {
704             ok &= truncateFile(k_ftraceFilterPath);
705         }
706     } else {
707         // Enable kernel function tracing.
708         ok &= writeStr(k_currentTracerPath, "function_graph");
709         ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
710         ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
711         ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
712 
713         // Set the requested filter functions.
714         ok &= truncateFile(k_ftraceFilterPath);
715         char* myFuncs = strdup(funcs);
716         char* func = strtok(myFuncs, ",");
717         while (func) {
718             ok &= appendStr(k_ftraceFilterPath, func);
719             func = strtok(nullptr, ",");
720         }
721         free(myFuncs);
722 
723         // Verify that the set functions are being traced.
724         if (ok) {
725             ok &= verifyKernelTraceFuncs(funcs);
726         }
727     }
728 
729     return ok;
730 }
731 
setCategoryEnable(const char * name)732 static bool setCategoryEnable(const char* name)
733 {
734     bool vendor_found = false;
735     for (auto& c : g_vendorFileCategories) {
736         if (strcmp(name, c.name.c_str()) == 0) {
737             c.enabled = true;
738             vendor_found = true;
739         }
740     }
741     for (auto& c : g_vendorHalCategories) {
742         if (strcmp(name, c.name.c_str()) == 0) {
743             c.enabled = true;
744             vendor_found = true;
745         }
746     }
747     for (size_t i = 0; i < arraysize(k_categories); i++) {
748         const TracingCategory& c = k_categories[i];
749         if (strcmp(name, c.name) == 0) {
750             if (isCategorySupported(c)) {
751                 g_categoryEnables[i] = true;
752                 return true;
753             } else {
754                 if (isCategorySupportedForRoot(c)) {
755                     fprintf(stderr, "error: category \"%s\" requires root "
756                             "privileges.\n", name);
757                 } else {
758                     fprintf(stderr, "error: category \"%s\" is not supported "
759                             "on this device.\n", name);
760                 }
761                 return false;
762             }
763         }
764     }
765     if (vendor_found) {
766         return true;
767     }
768     fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
769     return false;
770 }
771 
setCategoriesEnableFromFile(const char * categories_file)772 static bool setCategoriesEnableFromFile(const char* categories_file)
773 {
774     if (!categories_file) {
775         return true;
776     }
777     Tokenizer* tokenizer = nullptr;
778     if (Tokenizer::open(String8(categories_file), &tokenizer) != NO_ERROR) {
779         return false;
780     }
781     bool ok = true;
782     while (!tokenizer->isEol()) {
783         String8 token = tokenizer->nextToken(" ");
784         if (token.empty()) {
785             tokenizer->skipDelimiters(" ");
786             continue;
787         }
788         ok &= setCategoryEnable(token.c_str());
789     }
790     delete tokenizer;
791     return ok;
792 }
793 
setUpUserspaceTracing()794 static bool setUpUserspaceTracing()
795 {
796     bool ok = true;
797 
798     // Set up the tags property.
799     uint64_t tags = 0;
800     for (size_t i = 0; i < arraysize(k_categories); i++) {
801         if (g_categoryEnables[i]) {
802             const TracingCategory &c = k_categories[i];
803             tags |= c.tags;
804         }
805     }
806 
807     bool coreServicesTagEnabled = false;
808     for (size_t i = 0; i < arraysize(k_categories); i++) {
809         if (strcmp(k_categories[i].name, k_coreServiceCategory) == 0) {
810             coreServicesTagEnabled = g_categoryEnables[i];
811         }
812     }
813 
814     std::string packageList(g_debugAppCmdLine);
815     if (coreServicesTagEnabled) {
816         if (!packageList.empty()) {
817             packageList += ",";
818         }
819         packageList += android::base::GetProperty(k_coreServicesProp, "");
820     }
821     ok &= setAppCmdlineProperty(&packageList[0]);
822     ok &= setTagsProperty(tags);
823 
824     return ok;
825 }
826 
cleanUpUserspaceTracing()827 static void cleanUpUserspaceTracing()
828 {
829     setTagsProperty(0);
830     clearAppProperties();
831 }
832 
833 
834 // Set all the kernel tracing settings to the desired state for this trace
835 // capture.
setUpKernelTracing()836 static bool setUpKernelTracing()
837 {
838     bool ok = true;
839 
840     ok &= setUserInitiatedTraceProperty(true);
841 
842     // Set up the tracing options.
843     ok &= setCategoriesEnableFromFile(g_categoriesFile);
844     ok &= setTraceOverwriteEnable(g_traceOverwrite);
845     ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
846     ok &= setClock();
847     ok &= setPrintTgidEnableIfPresent(true);
848     ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
849 
850     // Disable all the sysfs enables.  This is done as a separate loop from
851     // the enables to allow the same enable to exist in multiple categories.
852     ok &= disableKernelTraceEvents();
853 
854     // Enable all the sysfs enables that are in an enabled category.
855     for (size_t i = 0; i < arraysize(k_categories); i++) {
856         if (g_categoryEnables[i]) {
857             const TracingCategory &c = k_categories[i];
858             for (int j = 0; j < MAX_SYS_FILES; j++) {
859                 const char* path = c.sysfiles[j].path;
860                 bool required = c.sysfiles[j].required == REQ;
861                 if (path != nullptr) {
862                     if (fileIsWritable(path)) {
863                         ok &= setKernelOptionEnable(path, true);
864                     } else if (required) {
865                         fprintf(stderr, "error writing file %s\n", path);
866                         ok = false;
867                     }
868                 }
869             }
870         }
871     }
872 
873     for (const TracingVendorFileCategory& c : g_vendorFileCategories) {
874         if (c.enabled) {
875             for (const std::string& path : c.ftrace_enable_paths) {
876                 if (fileIsWritable(path.c_str())) {
877                     ok &= setKernelOptionEnable(path.c_str(), true);
878                 }
879             }
880         }
881     }
882 
883     return ok;
884 }
885 
886 // Reset all the kernel tracing settings to their default state.
cleanUpKernelTracing()887 static void cleanUpKernelTracing()
888 {
889     // Disable all tracing that we're able to.
890     disableKernelTraceEvents();
891 
892     // Set the options back to their defaults.
893     setTraceOverwriteEnable(true);
894     setTraceBufferSizeKB(1);
895     setPrintTgidEnableIfPresent(false);
896     setKernelTraceFuncs(nullptr);
897     setUserInitiatedTraceProperty(false);
898 }
899 
900 // Enable tracing in the kernel.
startTrace()901 static bool startTrace()
902 {
903     return setTracingEnabled(true);
904 }
905 
906 // Disable tracing in the kernel.
stopTrace()907 static void stopTrace()
908 {
909     setTracingEnabled(false);
910 }
911 
preferSdkCategories()912 static bool preferSdkCategories() {
913     uint64_t tags = 0;
914     for (size_t i = 0; i < arraysize(k_categories); i++) {
915         if (g_categoryEnables[i]) {
916             const TracingCategory& c = k_categories[i];
917             tags |= c.tags;
918         }
919     }
920     return setPreferSdkProperty(tags);
921 }
922 
923 // Read data from the tracing pipe and forward to stdout
streamTrace()924 static void streamTrace()
925 {
926     char trace_data[4096];
927     int traceFD = open((g_traceFolder + k_traceStreamPath).c_str(), O_RDWR);
928     if (traceFD == -1) {
929         fprintf(stderr, "error opening %s: %s (%d)\n", k_traceStreamPath,
930                 strerror(errno), errno);
931         return;
932     }
933     while (!g_traceAborted) {
934         ssize_t bytes_read = read(traceFD, trace_data, 4096);
935         if (bytes_read > 0) {
936             write(STDOUT_FILENO, trace_data, bytes_read);
937             fflush(stdout);
938         } else {
939             if (!g_traceAborted) {
940                 fprintf(stderr, "read returned %zd bytes err %d (%s)\n",
941                         bytes_read, errno, strerror(errno));
942             }
943             break;
944         }
945     }
946 }
947 
948 // Read the current kernel trace and write it to stdout.
dumpTrace(int outFd)949 static void dumpTrace(int outFd)
950 {
951     ALOGI("Dumping trace");
952     int traceFD = open((g_traceFolder + k_tracePath).c_str(), O_RDWR);
953     if (traceFD == -1) {
954         fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
955                 strerror(errno), errno);
956         return;
957     }
958 
959     if (g_compress) {
960         z_stream zs;
961         memset(&zs, 0, sizeof(zs));
962 
963         int result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
964         if (result != Z_OK) {
965             fprintf(stderr, "error initializing zlib: %d\n", result);
966             close(traceFD);
967             return;
968         }
969 
970         constexpr size_t bufSize = 64*1024;
971         std::unique_ptr<uint8_t> in(new uint8_t[bufSize]);
972         std::unique_ptr<uint8_t> out(new uint8_t[bufSize]);
973         if (!in || !out) {
974             fprintf(stderr, "couldn't allocate buffers\n");
975             close(traceFD);
976             return;
977         }
978 
979         int flush = Z_NO_FLUSH;
980 
981         zs.next_out = reinterpret_cast<Bytef*>(out.get());
982         zs.avail_out = bufSize;
983 
984         do {
985 
986             if (zs.avail_in == 0) {
987                 // More input is needed.
988                 result = read(traceFD, in.get(), bufSize);
989                 if (result < 0) {
990                     fprintf(stderr, "error reading trace: %s (%d)\n",
991                             strerror(errno), errno);
992                     result = Z_STREAM_END;
993                     break;
994                 } else if (result == 0) {
995                     flush = Z_FINISH;
996                 } else {
997                     zs.next_in = reinterpret_cast<Bytef*>(in.get());
998                     zs.avail_in = result;
999                 }
1000             }
1001 
1002             if (zs.avail_out == 0) {
1003                 // Need to write the output.
1004                 result = write(outFd, out.get(), bufSize);
1005                 if ((size_t)result < bufSize) {
1006                     fprintf(stderr, "error writing deflated trace: %s (%d)\n",
1007                             strerror(errno), errno);
1008                     result = Z_STREAM_END; // skip deflate error message
1009                     zs.avail_out = bufSize; // skip the final write
1010                     break;
1011                 }
1012                 zs.next_out = reinterpret_cast<Bytef*>(out.get());
1013                 zs.avail_out = bufSize;
1014             }
1015 
1016         } while ((result = deflate(&zs, flush)) == Z_OK);
1017 
1018         if (result != Z_STREAM_END) {
1019             fprintf(stderr, "error deflating trace: %s\n", zs.msg);
1020         }
1021 
1022         if (zs.avail_out < bufSize) {
1023             size_t bytes = bufSize - zs.avail_out;
1024             result = write(outFd, out.get(), bytes);
1025             if ((size_t)result < bytes) {
1026                 fprintf(stderr, "error writing deflated trace: %s (%d)\n",
1027                         strerror(errno), errno);
1028             }
1029         }
1030 
1031         result = deflateEnd(&zs);
1032         if (result != Z_OK) {
1033             fprintf(stderr, "error cleaning up zlib: %d\n", result);
1034         }
1035     } else {
1036         char buf[4096];
1037         ssize_t rc;
1038         while ((rc = TEMP_FAILURE_RETRY(read(traceFD, buf, sizeof(buf)))) > 0) {
1039             if (!android::base::WriteFully(outFd, buf, rc)) {
1040                 fprintf(stderr, "error writing trace: %s\n", strerror(errno));
1041                 break;
1042             }
1043         }
1044         if (rc == -1) {
1045             fprintf(stderr, "error dumping trace: %s\n", strerror(errno));
1046         }
1047     }
1048 
1049     close(traceFD);
1050 }
1051 
handleSignal(int)1052 static void handleSignal(int /*signo*/)
1053 {
1054     if (!g_nohup) {
1055         g_traceAborted = true;
1056     }
1057 }
1058 
registerSigHandler()1059 static void registerSigHandler()
1060 {
1061     struct sigaction sa;
1062     sigemptyset(&sa.sa_mask);
1063     sa.sa_flags = 0;
1064     sa.sa_handler = handleSignal;
1065     sigaction(SIGHUP, &sa, nullptr);
1066     sigaction(SIGINT, &sa, nullptr);
1067     sigaction(SIGQUIT, &sa, nullptr);
1068     sigaction(SIGTERM, &sa, nullptr);
1069 }
1070 
listSupportedCategories()1071 static void listSupportedCategories()
1072 {
1073     for (size_t i = 0; i < arraysize(k_categories); i++) {
1074         const TracingCategory& c = k_categories[i];
1075         if (isCategorySupported(c)) {
1076             printf("  %10s - %s\n", c.name, c.longname);
1077         }
1078     }
1079     for (const auto& c : g_vendorFileCategories) {
1080         printf("  %10s - (VENDOR)\n", c.name.c_str());
1081     }
1082     for (const auto& c : g_vendorHalCategories) {
1083         printf("  %10s - %s (HAL)\n", c.name.c_str(), c.description.c_str());
1084     }
1085 }
1086 
1087 // Print the command usage help to stderr.
showHelp(const char * cmd)1088 static void showHelp(const char *cmd)
1089 {
1090     fprintf(stderr, "usage: %s [options] [categories...]\n", cmd);
1091     fprintf(stderr, "options include:\n"
1092                     "  -a appname      enable app-level tracing for a comma "
1093                         "separated list of cmdlines; * is a wildcard matching any process\n"
1094                     "  -b N            use a trace buffer size of N KB\n"
1095                     "  -c              trace into a circular buffer\n"
1096                     "  -f filename     use the categories written in a file as space-separated\n"
1097                     "                    values in a line\n"
1098                     "  -k fname,...    trace the listed kernel functions\n"
1099                     "  -n              ignore signals\n"
1100                     "  -s N            sleep for N seconds before tracing [default 0]\n"
1101                     "  -t N            trace for N seconds [default 5]\n"
1102                     "  -z              compress the trace dump\n"
1103                     "  --async_start   start circular trace and return immediately\n"
1104                     "  --async_dump    dump the current contents of circular trace buffer\n"
1105                     "  --async_stop    stop tracing and dump the current contents of circular\n"
1106                     "                    trace buffer\n"
1107                     "  --stream        stream trace to stdout as it enters the trace buffer\n"
1108                     "                    Note: this can take significant CPU time, and is best\n"
1109                     "                    used for measuring things that are not affected by\n"
1110                     "                    CPU performance, like pagecache usage.\n"
1111                     "  --list_categories\n"
1112                     "                  list the available tracing categories\n"
1113                     "  --prefer_sdk\n"
1114                     "                  prefer the perfetto sdk over legacy atrace for\n"
1115                     "                    categories and exits immediately\n"
1116                     " -o filename      write the trace to the specified file instead\n"
1117                     "                    of stdout.\n"
1118             );
1119 }
1120 
findTraceFiles()1121 bool findTraceFiles()
1122 {
1123     static const std::string debugfs_path = "/sys/kernel/debug/tracing/";
1124     static const std::string tracefs_path = "/sys/kernel/tracing/";
1125     static const std::string trace_file = "trace_marker";
1126 
1127     bool tracefs = access((tracefs_path + trace_file).c_str(), F_OK) != -1;
1128     bool debugfs = access((debugfs_path + trace_file).c_str(), F_OK) != -1;
1129 
1130     if (!tracefs && !debugfs) {
1131         fprintf(stderr, "Error: Did not find trace folder\n");
1132         return false;
1133     }
1134 
1135     if (tracefs) {
1136         g_traceFolder = tracefs_path;
1137     } else {
1138         g_traceFolder = debugfs_path;
1139     }
1140 
1141     return true;
1142 }
1143 
initVendorCategoriesFromFile()1144 void initVendorCategoriesFromFile() {
1145     std::ifstream is(kVendorCategoriesPath);
1146     for (std::string line; std::getline(is, line);) {
1147         if (line.empty()) {
1148             continue;
1149         }
1150         if (android::base::StartsWith(line, ' ') || android::base::StartsWith(line, '\t')) {
1151             if (g_vendorFileCategories.empty()) {
1152                 fprintf(stderr, "Malformed vendor categories file\n");
1153                 exit(1);
1154                 return;
1155             }
1156             std::string_view path = std::string_view(line).substr(1);
1157             while (android::base::StartsWith(path, ' ') || android::base::StartsWith(path, '\t')) {
1158                 path.remove_prefix(1);
1159             }
1160             if (path.empty()) {
1161                 continue;
1162             }
1163             std::string enable_path = "events/";
1164             enable_path += path;
1165             enable_path += "/enable";
1166             g_vendorFileCategories.back().ftrace_enable_paths.push_back(std::move(enable_path));
1167         } else {
1168             TracingVendorFileCategory cat;
1169             cat.name = line;
1170             g_vendorFileCategories.push_back(std::move(cat));
1171         }
1172     }
1173 }
1174 
initVendorCategoriesFromHal()1175 void initVendorCategoriesFromHal() {
1176     g_atraceHal = IAtraceDevice::getService();
1177 
1178     if (g_atraceHal == nullptr) {
1179         // No atrace HAL
1180         return;
1181     }
1182 
1183     Return<void> ret = g_atraceHal->listCategories([](const auto& list) {
1184         g_vendorHalCategories.reserve(list.size());
1185         for (const auto& category : list) {
1186             g_vendorHalCategories.emplace_back(category.name, category.description, false);
1187         }
1188     });
1189     if (!ret.isOk()) {
1190         fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
1191     }
1192 }
1193 
initVendorCategories()1194 void initVendorCategories() {
1195     // If kVendorCategoriesPath exists on the filesystem, do not use the HAL.
1196     if (access(kVendorCategoriesPath, F_OK) != -1) {
1197         initVendorCategoriesFromFile();
1198     } else {
1199         initVendorCategoriesFromHal();
1200     }
1201 }
1202 
setUpVendorTracingWithHal()1203 static bool setUpVendorTracingWithHal() {
1204     if (g_atraceHal == nullptr) {
1205         // No atrace HAL
1206         return true;
1207     }
1208 
1209     std::vector<hidl_string> categories;
1210     for (const auto& c : g_vendorHalCategories) {
1211         if (c.enabled) {
1212             categories.emplace_back(c.name);
1213         }
1214     }
1215 
1216     if (!categories.size()) {
1217         return true;
1218     }
1219 
1220     auto ret = g_atraceHal->enableCategories(categories);
1221     if (!ret.isOk()) {
1222         fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
1223         return false;
1224     } else if (ret != Status::SUCCESS) {
1225         fprintf(stderr, "calling atrace HAL failed: %s\n", toString(ret).c_str());
1226         return false;
1227     }
1228     return true;
1229 }
1230 
cleanUpVendorTracingWithHal()1231 static bool cleanUpVendorTracingWithHal() {
1232     if (g_atraceHal == nullptr) {
1233         // No atrace HAL
1234         return true;
1235     }
1236 
1237     if (!g_vendorHalCategories.size()) {
1238         // No vendor HAL categories
1239         return true;
1240     }
1241 
1242     auto ret = g_atraceHal->disableAllCategories();
1243     if (!ret.isOk()) {
1244         fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
1245         return false;
1246     } else if (ret != Status::SUCCESS) {
1247         fprintf(stderr, "calling atrace HAL failed: %s\n", toString(ret).c_str());
1248         return false;
1249     }
1250     return true;
1251 }
1252 
main(int argc,char ** argv)1253 int main(int argc, char **argv)
1254 {
1255     bool async = false;
1256     bool traceStart = true;
1257     bool traceStop = true;
1258     bool traceDump = true;
1259     bool traceStream = false;
1260     bool preferSdk = false;
1261     bool onlyUserspace = false;
1262 
1263     if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
1264         showHelp(argv[0]);
1265         exit(0);
1266     }
1267 
1268     if (!findTraceFiles()) {
1269         fprintf(stderr, "No trace folder found\n");
1270         exit(-1);
1271     }
1272 
1273     initVendorCategories();
1274 
1275     for (;;) {
1276         int ret;
1277         int option_index = 0;
1278         static struct option long_options[] = {
1279             {"async_start",       no_argument, nullptr,  0 },
1280             {"async_stop",        no_argument, nullptr,  0 },
1281             {"async_dump",        no_argument, nullptr,  0 },
1282             {"only_userspace",    no_argument, nullptr,  0 },
1283             {"list_categories",   no_argument, nullptr,  0 },
1284             {"stream",            no_argument, nullptr,  0 },
1285             {"prefer_sdk",        no_argument, nullptr,  0 },
1286             {nullptr,                       0, nullptr,  0 }
1287         };
1288 
1289         ret = getopt_long(argc, argv, "a:b:cf:k:ns:t:zo:",
1290                           long_options, &option_index);
1291 
1292         if (ret < 0) {
1293             for (int i = optind; i < argc; i++) {
1294                 setCategoryEnable(argv[i]);
1295             }
1296             break;
1297         }
1298 
1299         switch(ret) {
1300             case 'a':
1301                 g_debugAppCmdLine = optarg;
1302             break;
1303 
1304             case 'b':
1305                 g_traceBufferSizeKB = atoi(optarg);
1306             break;
1307 
1308             case 'c':
1309                 g_traceOverwrite = true;
1310             break;
1311 
1312             case 'f':
1313                 g_categoriesFile = optarg;
1314             break;
1315 
1316             case 'k':
1317                 g_kernelTraceFuncs = optarg;
1318             break;
1319 
1320             case 'n':
1321                 g_nohup = true;
1322             break;
1323 
1324             case 's':
1325                 g_initialSleepSecs = atoi(optarg);
1326             break;
1327 
1328             case 't':
1329                 g_traceDurationSeconds = atoi(optarg);
1330             break;
1331 
1332             case 'z':
1333                 g_compress = true;
1334             break;
1335 
1336             case 'o':
1337                 g_outputFile = optarg;
1338             break;
1339 
1340             case 0:
1341                 if (!strcmp(long_options[option_index].name, "async_start")) {
1342                     async = true;
1343                     traceStop = false;
1344                     traceDump = false;
1345                     g_traceOverwrite = true;
1346                 } else if (!strcmp(long_options[option_index].name, "async_stop")) {
1347                     async = true;
1348                     traceStart = false;
1349                 } else if (!strcmp(long_options[option_index].name, "async_dump")) {
1350                     async = true;
1351                     traceStart = false;
1352                     traceStop = false;
1353                 } else if (!strcmp(long_options[option_index].name, "only_userspace")) {
1354                     onlyUserspace = true;
1355                 } else if (!strcmp(long_options[option_index].name, "stream")) {
1356                     traceStream = true;
1357                     traceDump = false;
1358                 } else if (!strcmp(long_options[option_index].name, "prefer_sdk")) {
1359                     preferSdk = true;
1360                 } else if (!strcmp(long_options[option_index].name, "list_categories")) {
1361                     listSupportedCategories();
1362                     exit(0);
1363                 }
1364             break;
1365 
1366             default:
1367                 fprintf(stderr, "\n");
1368                 showHelp(argv[0]);
1369                 exit(-1);
1370             break;
1371         }
1372     }
1373 
1374     if (preferSdk) {
1375         bool res = preferSdkCategories();
1376         exit(res ? 0 : 1);
1377     }
1378 
1379     if (onlyUserspace) {
1380         if (!async || !(traceStart || traceStop)) {
1381             fprintf(stderr, "--only_userspace can only be used with "
1382                     "--async_start or --async_stop\n");
1383             exit(1);
1384         }
1385     }
1386 
1387     registerSigHandler();
1388 
1389     if (g_initialSleepSecs > 0) {
1390         sleep(g_initialSleepSecs);
1391     }
1392 
1393     bool ok = true;
1394 
1395     if (traceStart) {
1396         ok &= setUpUserspaceTracing();
1397     }
1398 
1399     if (ok && traceStart && !onlyUserspace) {
1400         ok &= setUpKernelTracing();
1401         ok &= setUpVendorTracingWithHal();
1402         ok &= startTrace();
1403     }
1404 
1405     if (ok && traceStart) {
1406 
1407         if (!traceStream && !onlyUserspace) {
1408             printf("capturing trace...");
1409             fflush(stdout);
1410         }
1411 
1412         // We clear the trace after starting it because tracing gets enabled for
1413         // each CPU individually in the kernel. Having the beginning of the trace
1414         // contain entries from only one CPU can cause "begin" entries without a
1415         // matching "end" entry to show up if a task gets migrated from one CPU to
1416         // another.
1417         if (!onlyUserspace) {
1418             ok = clearTrace();
1419             writeClockSyncMarker();
1420         }
1421         if (ok && !async && !traceStream) {
1422             // Sleep to allow the trace to be captured.
1423             struct timespec timeLeft;
1424             timeLeft.tv_sec = g_traceDurationSeconds;
1425             timeLeft.tv_nsec = 0;
1426             do {
1427                 if (g_traceAborted) {
1428                     break;
1429                 }
1430             } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
1431         }
1432 
1433         if (traceStream) {
1434             streamTrace();
1435         }
1436     }
1437 
1438     // Stop the trace and restore the default settings.
1439     if (traceStop && !onlyUserspace)
1440         stopTrace();
1441 
1442     if (ok && traceDump && !onlyUserspace) {
1443         if (!g_traceAborted) {
1444             printf(" done\n");
1445             fflush(stdout);
1446             int outFd = STDOUT_FILENO;
1447             if (g_outputFile) {
1448                 outFd = open(g_outputFile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1449             }
1450             if (outFd == -1) {
1451                 printf("Failed to open '%s', err=%d", g_outputFile, errno);
1452             } else {
1453                 dprintf(outFd, "TRACE:\n");
1454                 dumpTrace(outFd);
1455                 if (g_outputFile) {
1456                     close(outFd);
1457                 }
1458             }
1459         } else {
1460             printf("\ntrace aborted.\n");
1461             fflush(stdout);
1462         }
1463         clearTrace();
1464     } else if (!ok) {
1465         fprintf(stderr, "unable to start tracing\n");
1466     }
1467 
1468     // Reset the trace buffer size to 1.
1469     if (traceStop) {
1470         cleanUpUserspaceTracing();
1471         if (!onlyUserspace) {
1472             cleanUpVendorTracingWithHal();
1473             cleanUpKernelTracing();
1474         }
1475     }
1476 
1477     return g_traceAborted ? 1 : 0;
1478 }
1479