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