diff --git a/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h index 24c6ae629..97e93f861 100644 --- a/libcutils/include/cutils/trace.h +++ b/libcutils/include/cutils/trace.h @@ -207,6 +207,39 @@ static inline void atrace_async_end(uint64_t tag, const char* name, int32_t cook } } +/** + * Trace an instantaneous context. name is used to identify the context. + * + * An "instant" is an event with no defined duration. Visually is displayed like a single marker + * in the timeline (rather than a span, in the case of begin/end events). + * + * By default, instant events are added into a dedicated track that has the same name of the event. + * Use atrace_instant_for_track to put different instant events into the same timeline track/row. + */ +#define ATRACE_INSTANT(name) atrace_instant(ATRACE_TAG, name) +static inline void atrace_instant(uint64_t tag, const char* name) { + if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) { + void atrace_instant_body(const char*); + atrace_instant_body(name); + } +} + +/** + * Trace an instantaneous context. name is used to identify the context. + * trackName is the name of the row where the event should be recorded. + * + * An "instant" is an event with no defined duration. Visually is displayed like a single marker + * in the timeline (rather than a span, in the case of begin/end events). + */ +#define ATRACE_INSTANT_FOR_TRACK(trackName, name) \ + atrace_instant_for_track(ATRACE_TAG, trackName, name) +static inline void atrace_instant_for_track(uint64_t tag, const char* trackName, const char* name) { + if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) { + void atrace_instant_for_track_body(const char*, const char*); + atrace_instant_for_track_body(trackName, name); + } +} + /** * Traces an integer counter value. name is used to identify the counter. * This can be used to track how a value changes over time. diff --git a/libcutils/trace-container.cpp b/libcutils/trace-container.cpp index f7eed48aa..ef7c72d1d 100644 --- a/libcutils/trace-container.cpp +++ b/libcutils/trace-container.cpp @@ -217,6 +217,28 @@ void atrace_async_end_body(const char* name, int32_t cookie) WRITE_MSG("F|%d|", "|%" PRId32, name, cookie); } +void atrace_instant_body(const char* name) { + if (CC_LIKELY(atrace_use_container_sock)) { + WRITE_MSG_IN_CONTAINER("I", "|", "%s", name, ""); + return; + } + + if (atrace_marker_fd < 0) return; + + WRITE_MSG("I|%d|", "%s", name, ""); +} + +void atrace_instant_for_track_body(const char* trackName, const char* name) { + if (CC_LIKELY(atrace_use_container_sock)) { + WRITE_MSG_IN_CONTAINER("N", "|", "|%s", trackName, name); + return; + } + + if (atrace_marker_fd < 0) return; + + WRITE_MSG("N|%d|", "|%s", name, trackName); +} + void atrace_int_body(const char* name, int32_t value) { if (CC_LIKELY(atrace_use_container_sock)) { diff --git a/libcutils/trace-dev.cpp b/libcutils/trace-dev.cpp index 1ab63dc2f..25c86f436 100644 --- a/libcutils/trace-dev.cpp +++ b/libcutils/trace-dev.cpp @@ -89,6 +89,14 @@ void atrace_async_end_body(const char* name, int32_t cookie) WRITE_MSG("F|%d|", "|%" PRId32, name, cookie); } +void atrace_instant_body(const char* name) { + WRITE_MSG("I|%d|", "%s", name, ""); +} + +void atrace_instant_for_track_body(const char* trackName, const char* name) { + WRITE_MSG("N|%d|", "|%s", trackName, name); +} + void atrace_int_body(const char* name, int32_t value) { WRITE_MSG("C|%d|", "|%" PRId32, name, value); diff --git a/libcutils/trace-dev_test.cpp b/libcutils/trace-dev_test.cpp index 832b36a0c..ff6d20231 100644 --- a/libcutils/trace-dev_test.cpp +++ b/libcutils/trace-dev_test.cpp @@ -195,6 +195,106 @@ TEST_F(TraceDevTest, atrace_async_end_body_truncated) { ASSERT_STREQ(expected.c_str(), actual.c_str()); } +TEST_F(TraceDevTest, atrace_instant_body_normal) { + atrace_instant_body("fake_name"); + + ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET)); + + std::string actual; + ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual)); + std::string expected = android::base::StringPrintf("I|%d|fake_name", getpid()); + ASSERT_STREQ(expected.c_str(), actual.c_str()); +} + +TEST_F(TraceDevTest, atrace_instant_body_exact) { + std::string expected = android::base::StringPrintf("I|%d|", getpid()); + std::string name = MakeName(ATRACE_MESSAGE_LENGTH - expected.length() - 1); + atrace_instant_body(name.c_str()); + + ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR)); + ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET)); + + std::string actual; + ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual)); + expected += name; + ASSERT_STREQ(expected.c_str(), actual.c_str()); + + // Add a single character and verify we get the exact same value as before. + ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET)); + name += '*'; + atrace_instant_body(name.c_str()); + EXPECT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR)); + ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET)); + ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual)); + ASSERT_STREQ(expected.c_str(), actual.c_str()); +} + +TEST_F(TraceDevTest, atrace_instant_body_truncated) { + std::string expected = android::base::StringPrintf("I|%d|", getpid()); + std::string name = MakeName(2 * ATRACE_MESSAGE_LENGTH); + atrace_instant_body(name.c_str()); + + ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR)); + ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET)); + + std::string actual; + ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual)); + int expected_len = ATRACE_MESSAGE_LENGTH - expected.length() - 1; + expected += android::base::StringPrintf("%.*s", expected_len, name.c_str()); + ASSERT_STREQ(expected.c_str(), actual.c_str()); +} + +TEST_F(TraceDevTest, atrace_instant_for_track_body_normal) { + atrace_instant_for_track_body("fake_track", "fake_name"); + + ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET)); + + std::string actual; + ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual)); + std::string expected = android::base::StringPrintf("N|%d|fake_track|fake_name", getpid()); + ASSERT_STREQ(expected.c_str(), actual.c_str()); +} + +TEST_F(TraceDevTest, atrace_instant_for_track_body_exact) { + const int nameSize = 5; + std::string expected = android::base::StringPrintf("N|%d|", getpid()); + std::string trackName = MakeName(ATRACE_MESSAGE_LENGTH - expected.length() - 1 - nameSize); + atrace_instant_for_track_body(trackName.c_str(), "name"); + + ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR)); + ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET)); + + std::string actual; + ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual)); + expected += trackName + "|name"; + ASSERT_STREQ(expected.c_str(), actual.c_str()); + + // Add a single character and verify we get the exact same value as before. + ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET)); + trackName += '*'; + atrace_instant_for_track_body(trackName.c_str(), "name"); + EXPECT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR)); + ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET)); + ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual)); + ASSERT_STREQ(expected.c_str(), actual.c_str()); +} + +TEST_F(TraceDevTest, atrace_instant_for_track_body_truncated) { + const int nameSize = 5; + std::string expected = android::base::StringPrintf("N|%d|", getpid()); + std::string trackName = MakeName(2 * ATRACE_MESSAGE_LENGTH); + atrace_instant_for_track_body(trackName.c_str(), "name"); + + ASSERT_EQ(ATRACE_MESSAGE_LENGTH - 1, lseek(atrace_marker_fd, 0, SEEK_CUR)); + ASSERT_EQ(0, lseek(atrace_marker_fd, 0, SEEK_SET)); + + std::string actual; + ASSERT_TRUE(android::base::ReadFdToString(atrace_marker_fd, &actual)); + int expected_len = ATRACE_MESSAGE_LENGTH - expected.length() - 1 - nameSize; + expected += android::base::StringPrintf("%.*s|name", expected_len, trackName.c_str()); + ASSERT_STREQ(expected.c_str(), actual.c_str()); +} + TEST_F(TraceDevTest, atrace_int_body_normal) { atrace_int_body("fake_name", 12345); diff --git a/libcutils/trace-host.cpp b/libcutils/trace-host.cpp index 9781ad3e4..b01a0ecba 100644 --- a/libcutils/trace-host.cpp +++ b/libcutils/trace-host.cpp @@ -28,6 +28,9 @@ void atrace_begin_body(const char* /*name*/) {} void atrace_end_body() { } void atrace_async_begin_body(const char* /*name*/, int32_t /*cookie*/) {} void atrace_async_end_body(const char* /*name*/, int32_t /*cookie*/) {} +void atrace_instant_body(const char* /*name*/) {} +void atrace_instant_for_track_body(const char* /*trackName*/, + const char* /*name*/) {} void atrace_int_body(const char* /*name*/, int32_t /*value*/) {} void atrace_int64_body(const char* /*name*/, int64_t /*value*/) {} void atrace_init() {}