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