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