Mobile Development 11 min read

Enable On‑Device Systrace for Android Without a PC and Capture Full Call Traces

This article explains how Android's built‑in Trace infrastructure can be leveraged on the device itself—by modifying native tag variables and hooking write calls—to run systrace without a PC, automatically instrument methods, and export data for Perfetto analysis.

NetEase Cloud Music Tech Team
NetEase Cloud Music Tech Team
NetEase Cloud Music Tech Team
Enable On‑Device Systrace for Android Without a PC and Capture Full Call Traces

Background

Android processes UI events on a single UI thread. Any long‑running operation blocks subsequent work, causing the app to appear frozen. Identifying slow methods is essential for performance debugging.

Simple timing and its limits

Adding timestamps at method entry and exit (e.g., System.currentTimeMillis()) measures only application‑level code and cannot capture Android system calls. Android already provides trace points via the Trace class, which can be collected with the systrace tool to produce an HTML timeline.

Drawbacks of traditional systrace

Requires a PC connection and command‑line invocation.

Developers must manually insert Trace.beginSection and Trace.endSection, which is impractical for production where hot spots are unknown.

Running systrace on the device

Systrace gathers two kinds of data:

Java and native function calls recorded by the Trace class (written to trace_marker).

Kernel‑level events collected via ftrace.

By setting the appropriate trace tag directly on the device, the need for a PC is eliminated.

Enabling tags without source changes

The Trace.beginSection implementation checks sEnabledTags via nativeGetEnabledTags(). To enable a tag, the native variable atrace_enabled_tags in libcutils.so (or libutils.so on older Android versions) must be modified. The following code loads the library with dlopen, locates the symbol, and writes the desired tag value.

std::string lib_name("libcutils.so");
std::string enabled_tags_sym("atrace_enabled_tags");
if (sdk < 18) {
    lib_name = "libutils.so";
    enabled_tags_sym = "_ZN7android6Tracer12sEnabledTagsE";
}
void* handle;
if (sdk < 21) {
    handle = dlopen(lib_name.c_str(), RTLD_LOCAL);
} else {
    handle = dlopen(nullptr, RTLD_GLOBAL);
}
// reinterpret_cast to a pointer to std::atomic<uint64_t>
atrace_enabled_tags = reinterpret_cast<std::atomic<uint64_t>*>(dlsym(handle, enabled_tags_sym.c_str()));

Retrieving trace data

The native side writes to trace_marker via the write system call. By obtaining the file‑descriptor pointer ( atrace_marker_fd) and hooking write, raw strings such as "B|pid|name" can be captured, expanded to the full systrace line format, and saved to a file. The file can then be fed to systrace or Perfetto with the --from-file option to generate an HTML view.

void atrace_begin_body(const char* name) {
    char buf[ATRACE_MESSAGE_LENGTH];
    int len = snprintf(buf, sizeof(buf), "B|%d|%s", getpid(), name);
    if (len >= (int)sizeof(buf)) {
        ALOGW("Truncated name in %s: %s
", __FUNCTION__, name);
        len = sizeof(buf) - 1;
    }
    write(atrace_marker_fd, buf, len);
}

Automatic instrumentation

Manually inserting sections for every method is infeasible in large projects. The approach used by Tencent Matrix generates a compact methodId and passes it to Trace.beginSection, staying within the length limit. Exceptions must also call Trace.endSection to avoid unmatched sections, which would appear as “Did not Finish” entries in the trace.

Conclusion

By leveraging Android’s built‑in Trace mechanism, enabling tags on‑device, and hooking the write path, developers can capture complete call‑chain timelines without a PC. This makes it possible to diagnose intermittent or hidden performance stalls in production environments.

References

https://github.com/facebookincubator/profilo.git

https://github.com/Tencent/matrix.git

https://linux.cn/article-9838-1.html

https://segmentfault.com/a/1190000021327942

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Androidperformance profilingNative HooktraceSystraceMethod Instrumentation
NetEase Cloud Music Tech Team
Written by

NetEase Cloud Music Tech Team

Official account of NetEase Cloud Music Tech Team

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.