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