xref: /aosp_15_r20/external/perfetto/test/android_integrationtest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2022 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 "perfetto/base/build_config.h"
18 
19 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
20 
21 #include "perfetto/base/logging.h"
22 #include "perfetto/ext/base/file_utils.h"
23 #include "perfetto/ext/base/pipe.h"
24 #include "perfetto/ext/base/scoped_file.h"
25 #include "perfetto/ext/base/string_utils.h"
26 #include "perfetto/ext/base/utils.h"
27 #include "perfetto/ext/tracing/core/commit_data_request.h"
28 #include "perfetto/ext/tracing/core/trace_packet.h"
29 #include "perfetto/ext/tracing/core/tracing_service.h"
30 #include "perfetto/protozero/scattered_heap_buffer.h"
31 #include "src/base/test/test_task_runner.h"
32 #include "src/base/test/utils.h"
33 #include "test/gtest_and_gmock.h"
34 #include "test/test_helper.h"
35 
36 #include "protos/perfetto/config/power/android_power_config.pbzero.h"
37 #include "protos/perfetto/config/test_config.gen.h"
38 #include "protos/perfetto/config/trace_config.gen.h"
39 #include "protos/perfetto/trace/ftrace/ftrace.gen.h"
40 #include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
41 #include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
42 #include "protos/perfetto/trace/ftrace/ftrace_stats.gen.h"
43 #include "protos/perfetto/trace/perfetto/tracing_service_event.gen.h"
44 #include "protos/perfetto/trace/power/battery_counters.gen.h"
45 #include "protos/perfetto/trace/test_event.gen.h"
46 #include "protos/perfetto/trace/trace.gen.h"
47 #include "protos/perfetto/trace/trace_packet.gen.h"
48 #include "protos/perfetto/trace/trace_packet.pbzero.h"
49 #include "protos/perfetto/trace/trigger.gen.h"
50 
51 #include "protos/perfetto/common/sys_stats_counters.gen.h"
52 #include "protos/perfetto/config/sys_stats/sys_stats_config.gen.h"
53 #include "protos/perfetto/trace/sys_stats/sys_stats.gen.h"
54 
55 namespace perfetto {
56 
57 namespace {
58 
59 using ::testing::ContainsRegex;
60 using ::testing::Each;
61 using ::testing::ElementsAreArray;
62 using ::testing::HasSubstr;
63 using ::testing::Property;
64 using ::testing::SizeIs;
65 
66 }  // namespace
67 
TEST(PerfettoAndroidIntegrationTest,TestKmemActivity)68 TEST(PerfettoAndroidIntegrationTest, TestKmemActivity) {
69   using C = protos::gen::VmstatCounters;
70 
71   base::TestTaskRunner task_runner;
72 
73   TestHelper helper(&task_runner);
74 
75   helper.StartServiceIfRequired();
76 
77 #if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
78   ProbesProducerThread probes(GetTestProducerSockName());
79   probes.Connect();
80 #endif
81 
82   auto* producer = helper.ConnectFakeProducer();
83   helper.ConnectConsumer();
84   helper.WaitForConsumerConnect();
85   helper.WaitForDataSourceConnected("linux.ftrace");
86 
87   TraceConfig trace_config;
88   trace_config.add_buffers()->set_size_kb(1024);
89   trace_config.set_unique_session_name("kmem_activity_test");
90 
91   auto* ftrace_ds_config = trace_config.add_data_sources()->mutable_config();
92   ftrace_ds_config->set_name("linux.ftrace");
93   protos::gen::FtraceConfig ftrace_config = CreateFtraceConfig({
94       "vmscan/mm_vmscan_kswapd_wake",
95       "vmscan/mm_vmscan_kswapd_sleep",
96       "vmscan/mm_vmscan_direct_reclaim_begin",
97       "vmscan/mm_vmscan_direct_reclaim_end",
98       "compaction/mm_compaction_begin",
99       "compaction/mm_compaction_end",
100   });
101   ftrace_ds_config->set_ftrace_config_raw(ftrace_config.SerializeAsString());
102 
103   auto* sys_stats_ds_config = trace_config.add_data_sources()->mutable_config();
104   sys_stats_ds_config->set_name("linux.sys_stats");
105   protos::gen::SysStatsConfig sys_stats_config;
106   sys_stats_config.set_vmstat_period_ms(50);
107   std::vector<C> vmstat_counters = {
108       C::VMSTAT_NR_FREE_PAGES,
109       C::VMSTAT_NR_SLAB_RECLAIMABLE,
110       C::VMSTAT_NR_SLAB_UNRECLAIMABLE,
111       C::VMSTAT_NR_ACTIVE_FILE,
112       C::VMSTAT_NR_INACTIVE_FILE,
113       C::VMSTAT_NR_ACTIVE_ANON,
114       C::VMSTAT_NR_INACTIVE_ANON,
115       C::VMSTAT_WORKINGSET_REFAULT,
116       C::VMSTAT_WORKINGSET_ACTIVATE,
117       C::VMSTAT_NR_FILE_PAGES,
118       C::VMSTAT_PGPGIN,
119       C::VMSTAT_PGPGOUT,
120       C::VMSTAT_PSWPIN,
121       C::VMSTAT_PSWPOUT,
122       C::VMSTAT_PGSTEAL_KSWAPD_DMA,
123       C::VMSTAT_PGSTEAL_KSWAPD_NORMAL,
124       C::VMSTAT_PGSTEAL_KSWAPD_MOVABLE,
125       C::VMSTAT_PGSTEAL_DIRECT_DMA,
126       C::VMSTAT_PGSTEAL_DIRECT_NORMAL,
127       C::VMSTAT_PGSTEAL_DIRECT_MOVABLE,
128       C::VMSTAT_PGSCAN_KSWAPD_DMA,
129       C::VMSTAT_PGSCAN_KSWAPD_NORMAL,
130       C::VMSTAT_PGSCAN_KSWAPD_MOVABLE,
131       C::VMSTAT_PGSCAN_DIRECT_DMA,
132       C::VMSTAT_PGSCAN_DIRECT_NORMAL,
133       C::VMSTAT_PGSCAN_DIRECT_MOVABLE,
134       C::VMSTAT_COMPACT_MIGRATE_SCANNED,
135       C::VMSTAT_COMPACT_FREE_SCANNED,
136   };
137   for (const auto& counter : vmstat_counters) {
138     sys_stats_config.add_vmstat_counters(counter);
139   }
140   sys_stats_ds_config->set_sys_stats_config_raw(
141       sys_stats_config.SerializeAsString());
142 
143   auto* trigger_cfg = trace_config.mutable_trigger_config();
144   trigger_cfg->set_trigger_mode(
145       protos::gen::TraceConfig::TriggerConfig::START_TRACING);
146   trigger_cfg->set_trigger_timeout_ms(15000);
147   auto* trigger = trigger_cfg->add_triggers();
148   trigger->set_name("kmem_activity");
149   // |stop_delay_ms| must be long enough that we can write the packets in
150   // before the trace finishes.
151   trigger->set_stop_delay_ms(1000);
152 
153   helper.StartTracing(trace_config);
154 
155   // Linearize with StartTracing. This ensures that the service has seen the
156   // StartTracing IPC and has armed the triggers.
157   helper.FlushAndWait(kDefaultTestTimeoutMs);
158 
159   // Generating synthetic memory pressure to trigger kmem activity is
160   // inherently flaky on different devices. The same goes for writing
161   // /proc/sys/vm/compact_memory to trigger compaction, since compaction is
162   // only started if needed (even if explicitly triggered from proc).
163   // Trigger kmem activity using perfetto trigger.
164   producer->ActivateTrigger("kmem_activity");
165 
166   helper.WaitForTracingDisabled();
167 
168   helper.ReadData();
169   helper.WaitForReadData();
170 
171   const auto& packets = helper.trace();
172   ASSERT_GT(packets.size(), 0u);
173 
174   bool sys_stats_captured = false;
175   for (const auto& packet : packets) {
176     for (int ev = 0; ev < packet.ftrace_events().event_size(); ev++) {
177       auto ftrace_event =
178           packet.ftrace_events().event()[static_cast<size_t>(ev)];
179       ASSERT_TRUE(ftrace_event.has_mm_vmscan_kswapd_wake() ||
180                   ftrace_event.has_mm_vmscan_kswapd_sleep() ||
181                   ftrace_event.has_mm_vmscan_direct_reclaim_begin() ||
182                   ftrace_event.has_mm_vmscan_direct_reclaim_end() ||
183                   ftrace_event.has_mm_compaction_begin() ||
184                   ftrace_event.has_mm_compaction_end());
185     }
186 
187     if (packet.has_sys_stats()) {
188       sys_stats_captured = true;
189       const auto& sys_stats = packet.sys_stats();
190       const auto& vmstat = sys_stats.vmstat();
191       ASSERT_GT(vmstat.size(), 0u);
192       for (const auto& vmstat_value : vmstat) {
193         ASSERT_NE(std::find(vmstat_counters.begin(), vmstat_counters.end(),
194                             vmstat_value.key()),
195                   vmstat_counters.end());
196       }
197     }
198   }
199 
200   // Don't explicitly check that ftrace events were captured, since this test
201   // doesn't rely on memory pressure.
202   ASSERT_TRUE(sys_stats_captured);
203 }
204 
TEST(PerfettoAndroidIntegrationTest,TestBatteryTracing)205 TEST(PerfettoAndroidIntegrationTest, TestBatteryTracing) {
206   base::TestTaskRunner task_runner;
207 
208   TestHelper helper(&task_runner);
209   helper.StartServiceIfRequired();
210 
211 #if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
212   ProbesProducerThread probes(GetTestProducerSockName());
213   probes.Connect();
214 #endif
215 
216   helper.ConnectConsumer();
217   helper.WaitForConsumerConnect();
218 
219   TraceConfig trace_config;
220   trace_config.add_buffers()->set_size_kb(128);
221   trace_config.set_duration_ms(3000);
222 
223   auto* ds_config = trace_config.add_data_sources()->mutable_config();
224   ds_config->set_name("android.power");
225   ds_config->set_target_buffer(0);
226 
227   using protos::pbzero::AndroidPowerConfig;
228   protozero::HeapBuffered<AndroidPowerConfig> power_config;
229   power_config->set_battery_poll_ms(250);
230   power_config->add_battery_counters(
231       AndroidPowerConfig::BATTERY_COUNTER_CHARGE);
232   power_config->add_battery_counters(
233       AndroidPowerConfig::BATTERY_COUNTER_CAPACITY_PERCENT);
234   ds_config->set_android_power_config_raw(power_config.SerializeAsString());
235 
236   helper.StartTracing(trace_config);
237   helper.WaitForTracingDisabled();
238 
239   helper.ReadData();
240   helper.WaitForReadData();
241 
242   const auto& packets = helper.trace();
243   ASSERT_GT(packets.size(), 0u);
244 
245   bool has_battery_packet = false;
246   for (const auto& packet : packets) {
247     if (!packet.has_battery())
248       continue;
249     has_battery_packet = true;
250     // Unfortunately we cannot make any assertions on the charge counter.
251     // On some devices it can reach negative values (b/64685329).
252     EXPECT_GE(packet.battery().capacity_percent(), 0.f);
253     EXPECT_LE(packet.battery().capacity_percent(), 100.f);
254   }
255 
256   ASSERT_TRUE(has_battery_packet);
257 }
258 
259 }  // namespace perfetto
260 
261 #endif  // PERFETTO_OS_ANDROID
262