Search code examples
androidcandroid-ndktracesystrace

Is logging Android systrace events directly from native code possible, without JNI?


The Android systrace logging system is fantastic, but it only works in the Java portion of the code, through Trace.beginSection() and Trace.endSection(). In a C/C++ NDK (native) portion of the code it can only be used through JNI, which is slow or unavailable in threads without a Java environment...

Is there any way of either adding events to the main systrace trace buffer, or even generating a separate log, from native C code?

This older question mentions atrace/ftrace as being the internal system Android's systrace uses. Can this be tapped into (easily)?

BONUS TWIST: Since tracing calls would often be in performance-critical sections, it should ideally be possible to run the calls after the actual event time. i.e. I for one would prefer to be able to specify the times to log, instead of the calls polling for it themselves. But that would just be icing on the cake.


Solution

  • I don't think it's exposed from the NDK.

    If you look at the sources, you can see that the android.os.Trace class calls into native code to do the actual work. That code calls atrace_begin() and atrace_end(), which are declared in a header in the cutils library.

    You may be able to use the atrace functions directly if you extract the headers from the full source tree and link against the internal libraries. However, you can see from the header that atrace_begin() is simply:

    static inline void atrace_begin(uint64_t tag, const char* name)
    {
        if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
            char buf[ATRACE_MESSAGE_LENGTH];
            size_t len;
            len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "B|%d|%s", getpid(), name);
            write(atrace_marker_fd, buf, len);
        }
    }
    

    Events are written directly to the trace file descriptor. (Note that the timestamp is not part of the event; that's added automatically.) You could do something similar in your code; see atrace_init_once() in the .c file to see how the file is opened.

    Bear in mind that, unless atrace is published as part of the NDK, any code using it would be non-portable and likely to fail in past or future versions of Android. However, as systrace is a debugging tool and not something you'd actually want to ship enabled in an app, compatibility is probably not a concern.