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