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