• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "test/gtest_and_gmock.h"
18 
19 #include "src/android_sdk/perfetto_sdk_for_jni/tracing_sdk.h"
20 #include "src/shared_lib/test/utils.h"
21 
22 #include "perfetto/ext/base/string_utils.h"
23 
24 #include "protos/perfetto/trace/interned_data/interned_data.gen.h"
25 #include "protos/perfetto/trace/trace.gen.h"
26 #include "protos/perfetto/trace/trace_packet.gen.h"
27 #include "protos/perfetto/trace/track_event/debug_annotation.gen.h"
28 #include "protos/perfetto/trace/track_event/track_event.gen.h"
29 
30 namespace perfetto {
31 namespace {
32 using namespace perfetto::shlib::test_utils;
33 
34 using protos::gen::DebugAnnotation;
35 using protos::gen::EventCategory;
36 using protos::gen::EventName;
37 using protos::gen::InternedData;
38 using protos::gen::Trace;
39 using protos::gen::TracePacket;
40 using protos::gen::TrackEvent;
41 
StartTracing()42 sdk_for_jni::Session StartTracing() {
43   std::vector<uint8_t> build_proto_config =
44       TracingSession::Builder()
45           .set_data_source_name("track_event")
46           .add_enabled_category("*")  // enable everything
47           .BuildProtoConfig();
48   return sdk_for_jni::Session(true, build_proto_config.data(),
49                               build_proto_config.size());
50 }
51 
StopTracing(sdk_for_jni::Session & tracing_session)52 Trace StopTracing(sdk_for_jni::Session& tracing_session) {
53   tracing_session.FlushBlocking(5000);
54   tracing_session.StopBlocking();
55   std::vector trace_data(tracing_session.ReadBlocking());
56   Trace trace;
57   trace.ParseFromArray(trace_data.data(), trace_data.size());
58   return trace;
59 }
60 
61 template <class T>
GetNames(const std::vector<T> & items)62 std::vector<std::string> GetNames(const std::vector<T>& items) {
63   std::vector<std::string> names;
64   names.reserve(items.size());
65   for (const auto& item : items) {
66     names.push_back(item.name());
67   }
68   return names;
69 }
70 
DebugAnnotationToString(const DebugAnnotation & annotation)71 std::string DebugAnnotationToString(const DebugAnnotation& annotation) {
72   std::stringstream ss;
73   if (annotation.has_int_value()) {
74     ss << "int: " << annotation.int_value();
75   } else if (annotation.has_bool_value()) {
76     ss << "bool: " << annotation.bool_value();
77   } else {
78     ss << "unexpected";
79   }
80   return ss.str();
81 }
82 
packet_to_string(const TracePacket & packet)83 std::string packet_to_string(const TracePacket& packet) {
84   std::stringstream ss;
85   ss << "packet {\n";
86   if (packet.has_interned_data()) {
87     ss << "data {";
88     const InternedData& interned_data = packet.interned_data();
89     ss << " categories: ["
90        << base::Join(GetNames(interned_data.event_categories()), ", ") << "]";
91     ss << " names: [" << base::Join(GetNames(interned_data.event_names()), ", ")
92        << "],";
93     ss << " debug_annotation_names: ["
94        << base::Join(GetNames(interned_data.debug_annotation_names()), ", ")
95        << "]";
96     ss << " }\n";
97   }
98   if (packet.has_track_event()) {
99     const TrackEvent& track_event = packet.track_event();
100     ss << "event {";
101     ss << " type: " << track_event.type() << ", ";
102     std::vector<std::string> annotation_values;
103     for (const auto& annotation : track_event.debug_annotations()) {
104       annotation_values.push_back(DebugAnnotationToString(annotation));
105     }
106     ss << "debug_annotations: [" << base::Join(annotation_values, ", ") << "]";
107     ss << " }\n";
108   }
109   ss << "}\n";
110   return ss.str();
111 }
112 
TEST(TracingSdkForJniTest,mySimpleTest)113 TEST(TracingSdkForJniTest, mySimpleTest) {
114   sdk_for_jni::register_perfetto(true);
115   sdk_for_jni::Category category("rendering", "", "");
116   category.register_category();
117 
118   auto tracing_session = StartTracing();
119 
120   // In this test we generate a named slice with an additional payload
121 
122   sdk_for_jni::DebugArg<int64_t> player_number_extra("player_number");
123   player_number_extra.set_value(42);
124   sdk_for_jni::DebugArg<bool> player_alive_extra("player_alive");
125   player_alive_extra.set_value(true);
126 
127   sdk_for_jni::Extra extra;
128   extra.push_extra(reinterpret_cast<PerfettoTeHlExtra*>(
129       const_cast<PerfettoTeHlExtraDebugArgInt64*>(player_number_extra.get())));
130   extra.push_extra(reinterpret_cast<PerfettoTeHlExtra*>(
131       const_cast<PerfettoTeHlExtraDebugArgBool*>(player_alive_extra.get())));
132   trace_event(PERFETTO_TE_TYPE_SLICE_BEGIN, category.get(), "DrawPlayer",
133               &extra);
134 
135   sdk_for_jni::Extra empty_extra;
136   trace_event(PERFETTO_TE_TYPE_SLICE_END, category.get(), "DrawPlayer",
137               &empty_extra);
138 
139   Trace trace = StopTracing(tracing_session);
140 
141   std::string result;
142   for (const TracePacket& packet : trace.packet()) {
143     if (packet.has_interned_data() || packet.has_track_event()) {
144       result += packet_to_string(packet);
145     }
146   }
147 
148   const char* actual = R"(packet {
149 data { categories: [rendering] names: [DrawPlayer], debug_annotation_names: [player_number, player_alive] }
150 event { type: 1, debug_annotations: [int: 42, bool: 1] }
151 }
152 packet {
153 event { type: 2, debug_annotations: [] }
154 }
155 )";
156 
157   EXPECT_STREQ(result.c_str(), actual);
158 }
159 }  // namespace
160 }  // namespace perfetto
161