blob: 19e894de2a8f7e54697df184f0ebf6d0ab5a773a [file] [log] [blame]
Primiano Tucci401a4732022-01-19 00:26:49 +00001/*
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
55namespace perfetto {
56
57namespace {
58
59using ::testing::ContainsRegex;
60using ::testing::Each;
61using ::testing::ElementsAreArray;
62using ::testing::HasSubstr;
63using ::testing::Property;
64using ::testing::SizeIs;
65
66// For the SaveForBugreport* tests.
67void SetTraceConfigForBugreportTest(TraceConfig* trace_config) {
68 trace_config->add_buffers()->set_size_kb(4096);
69 trace_config->set_duration_ms(60000); // Will never hit this.
70 trace_config->set_bugreport_score(10);
71 auto* ds_config = trace_config->add_data_sources()->mutable_config();
72 ds_config->set_name("android.perfetto.FakeProducer");
73 ds_config->mutable_for_testing()->set_message_count(3);
74 ds_config->mutable_for_testing()->set_message_size(10);
75 ds_config->mutable_for_testing()->set_send_batch_on_register(true);
76}
77
78// For the SaveForBugreport* tests.
79static void VerifyBugreportTraceContents() {
80 // Read the trace written in the fixed location (/data/misc/perfetto-traces/
81 // on Android, /tmp/ on Linux/Mac) and make sure it has the right contents.
82 std::string trace_str;
83 base::ReadFile(GetBugreportPath(), &trace_str);
84 ASSERT_FALSE(trace_str.empty());
85 protos::gen::Trace trace;
86 ASSERT_TRUE(trace.ParseFromString(trace_str));
87 int test_packets = 0;
88 for (const auto& p : trace.packet())
89 test_packets += p.has_for_testing() ? 1 : 0;
90 ASSERT_EQ(test_packets, 3);
91}
92
93} // namespace
94
95TEST(PerfettoAndroidIntegrationTest, TestKmemActivity) {
96 using C = protos::gen::VmstatCounters;
97
98 base::TestTaskRunner task_runner;
99
100 TestHelper helper(&task_runner);
101
102 helper.StartServiceIfRequired();
103
104#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
105 ProbesProducerThread probes(GetTestProducerSockName());
106 probes.Connect();
107#endif
108
109 auto* producer = helper.ConnectFakeProducer();
110 helper.ConnectConsumer();
111 helper.WaitForConsumerConnect();
112 helper.WaitForDataSourceConnected("linux.ftrace");
113
114 TraceConfig trace_config;
115 trace_config.add_buffers()->set_size_kb(1024);
116 trace_config.set_unique_session_name("kmem_activity_test");
117
118 auto* ftrace_ds_config = trace_config.add_data_sources()->mutable_config();
119 ftrace_ds_config->set_name("linux.ftrace");
120 protos::gen::FtraceConfig ftrace_config = CreateFtraceConfig({
121 "vmscan/mm_vmscan_kswapd_wake",
122 "vmscan/mm_vmscan_kswapd_sleep",
123 "vmscan/mm_vmscan_direct_reclaim_begin",
124 "vmscan/mm_vmscan_direct_reclaim_end",
125 "compaction/mm_compaction_begin",
126 "compaction/mm_compaction_end",
127 });
128 ftrace_ds_config->set_ftrace_config_raw(ftrace_config.SerializeAsString());
129
130 auto* sys_stats_ds_config = trace_config.add_data_sources()->mutable_config();
131 sys_stats_ds_config->set_name("linux.sys_stats");
132 protos::gen::SysStatsConfig sys_stats_config;
133 sys_stats_config.set_vmstat_period_ms(50);
134 std::vector<C> vmstat_counters = {
135 C::VMSTAT_NR_FREE_PAGES,
136 C::VMSTAT_NR_SLAB_RECLAIMABLE,
137 C::VMSTAT_NR_SLAB_UNRECLAIMABLE,
138 C::VMSTAT_NR_ACTIVE_FILE,
139 C::VMSTAT_NR_INACTIVE_FILE,
140 C::VMSTAT_NR_ACTIVE_ANON,
141 C::VMSTAT_NR_INACTIVE_ANON,
142 C::VMSTAT_WORKINGSET_REFAULT,
143 C::VMSTAT_WORKINGSET_ACTIVATE,
144 C::VMSTAT_NR_FILE_PAGES,
145 C::VMSTAT_PGPGIN,
146 C::VMSTAT_PGPGOUT,
147 C::VMSTAT_PSWPIN,
148 C::VMSTAT_PSWPOUT,
149 C::VMSTAT_PGSTEAL_KSWAPD_DMA,
150 C::VMSTAT_PGSTEAL_KSWAPD_NORMAL,
151 C::VMSTAT_PGSTEAL_KSWAPD_MOVABLE,
152 C::VMSTAT_PGSTEAL_DIRECT_DMA,
153 C::VMSTAT_PGSTEAL_DIRECT_NORMAL,
154 C::VMSTAT_PGSTEAL_DIRECT_MOVABLE,
155 C::VMSTAT_PGSCAN_KSWAPD_DMA,
156 C::VMSTAT_PGSCAN_KSWAPD_NORMAL,
157 C::VMSTAT_PGSCAN_KSWAPD_MOVABLE,
158 C::VMSTAT_PGSCAN_DIRECT_DMA,
159 C::VMSTAT_PGSCAN_DIRECT_NORMAL,
160 C::VMSTAT_PGSCAN_DIRECT_MOVABLE,
161 C::VMSTAT_COMPACT_MIGRATE_SCANNED,
162 C::VMSTAT_COMPACT_FREE_SCANNED,
163 };
164 for (const auto& counter : vmstat_counters) {
165 sys_stats_config.add_vmstat_counters(counter);
166 }
167 sys_stats_ds_config->set_sys_stats_config_raw(
168 sys_stats_config.SerializeAsString());
169
170 auto* trigger_cfg = trace_config.mutable_trigger_config();
171 trigger_cfg->set_trigger_mode(
172 protos::gen::TraceConfig::TriggerConfig::START_TRACING);
173 trigger_cfg->set_trigger_timeout_ms(15000);
174 auto* trigger = trigger_cfg->add_triggers();
175 trigger->set_name("kmem_activity");
176 // |stop_delay_ms| must be long enough that we can write the packets in
177 // before the trace finishes.
178 trigger->set_stop_delay_ms(1000);
179
180 helper.StartTracing(trace_config);
181
182 // Linearize with StartTracing. This ensures that the service has seen the
183 // StartTracing IPC and has armed the triggers.
184 helper.FlushAndWait(kDefaultTestTimeoutMs);
185
186 // Generating synthetic memory pressure to trigger kmem activity is
187 // inherently flaky on different devices. The same goes for writing
188 // /proc/sys/vm/compact_memory to trigger compaction, since compaction is
189 // only started if needed (even if explicitly triggered from proc).
190 // Trigger kmem activity using perfetto trigger.
191 producer->ActivateTrigger("kmem_activity");
192
193 helper.WaitForTracingDisabled();
194
195 helper.ReadData();
196 helper.WaitForReadData();
197
198 const auto& packets = helper.trace();
199 ASSERT_GT(packets.size(), 0u);
200
201 bool sys_stats_captured = false;
202 for (const auto& packet : packets) {
203 for (int ev = 0; ev < packet.ftrace_events().event_size(); ev++) {
204 auto ftrace_event =
205 packet.ftrace_events().event()[static_cast<size_t>(ev)];
206 ASSERT_TRUE(ftrace_event.has_mm_vmscan_kswapd_wake() ||
207 ftrace_event.has_mm_vmscan_kswapd_sleep() ||
208 ftrace_event.has_mm_vmscan_direct_reclaim_begin() ||
209 ftrace_event.has_mm_vmscan_direct_reclaim_end() ||
210 ftrace_event.has_mm_compaction_begin() ||
211 ftrace_event.has_mm_compaction_end());
212 }
213
214 if (packet.has_sys_stats()) {
215 sys_stats_captured = true;
216 const auto& sys_stats = packet.sys_stats();
217 const auto& vmstat = sys_stats.vmstat();
218 ASSERT_GT(vmstat.size(), 0u);
219 for (const auto& vmstat_value : vmstat) {
220 ASSERT_NE(std::find(vmstat_counters.begin(), vmstat_counters.end(),
221 vmstat_value.key()),
222 vmstat_counters.end());
223 }
224 }
225 }
226
227 // Don't explicitly check that ftrace events were captured, since this test
228 // doesn't rely on memory pressure.
229 ASSERT_TRUE(sys_stats_captured);
230}
231
232TEST(PerfettoAndroidIntegrationTest, TestBatteryTracing) {
233 base::TestTaskRunner task_runner;
234
235 TestHelper helper(&task_runner);
236 helper.StartServiceIfRequired();
237
238#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
239 ProbesProducerThread probes(GetTestProducerSockName());
240 probes.Connect();
241#endif
242
243 helper.ConnectConsumer();
244 helper.WaitForConsumerConnect();
245
246 TraceConfig trace_config;
247 trace_config.add_buffers()->set_size_kb(128);
248 trace_config.set_duration_ms(3000);
249
250 auto* ds_config = trace_config.add_data_sources()->mutable_config();
251 ds_config->set_name("android.power");
252 ds_config->set_target_buffer(0);
253
254 using protos::pbzero::AndroidPowerConfig;
255 protozero::HeapBuffered<AndroidPowerConfig> power_config;
256 power_config->set_battery_poll_ms(250);
257 power_config->add_battery_counters(
258 AndroidPowerConfig::BATTERY_COUNTER_CHARGE);
259 power_config->add_battery_counters(
260 AndroidPowerConfig::BATTERY_COUNTER_CAPACITY_PERCENT);
261 ds_config->set_android_power_config_raw(power_config.SerializeAsString());
262
263 helper.StartTracing(trace_config);
264 helper.WaitForTracingDisabled();
265
266 helper.ReadData();
267 helper.WaitForReadData();
268
269 const auto& packets = helper.trace();
270 ASSERT_GT(packets.size(), 0u);
271
272 bool has_battery_packet = false;
273 for (const auto& packet : packets) {
274 if (!packet.has_battery())
275 continue;
276 has_battery_packet = true;
277 // Unfortunately we cannot make any assertions on the charge counter.
278 // On some devices it can reach negative values (b/64685329).
279 EXPECT_GE(packet.battery().capacity_percent(), 0.f);
280 EXPECT_LE(packet.battery().capacity_percent(), 100.f);
281 }
282
283 ASSERT_TRUE(has_battery_packet);
284}
285
286TEST(PerfettoAndroidIntegrationTest, SaveForBugreport) {
287 base::TestTaskRunner task_runner;
288
289 TestHelper helper(&task_runner);
290 helper.StartServiceIfRequired();
291 helper.ConnectFakeProducer();
292 helper.ConnectConsumer();
293 helper.WaitForConsumerConnect();
294
295 TraceConfig trace_config;
296 SetTraceConfigForBugreportTest(&trace_config);
297
298 helper.StartTracing(trace_config);
299 helper.WaitForProducerEnabled();
300
301 EXPECT_TRUE(helper.SaveTraceForBugreportAndWait());
302 helper.WaitForTracingDisabled();
303
304 VerifyBugreportTraceContents();
305
306 // Now read the trace returned to the consumer via ReadBuffers. This should
307 // be always empty because --save-for-bugreport takes it over and makes the
308 // buffers unreadable by the consumer (by virtue of force-setting
309 // write_into_file, which is incompatible with ReadBuffers()). The only
310 // content should be the |seized_for_bugreport| flag.
311 helper.ReadData();
312 helper.WaitForReadData();
313 const auto& packets = helper.full_trace();
314 ASSERT_EQ(packets.size(), 1u);
315 for (const auto& p : packets) {
316 ASSERT_TRUE(p.has_service_event());
317 ASSERT_TRUE(p.service_event().seized_for_bugreport());
318 }
319}
320
321// Tests that the SaveForBugreport logic works also for traces with
322// write_into_file = true (with a passed file descriptor).
323TEST(PerfettoAndroidIntegrationTest, SaveForBugreport_WriteIntoFile) {
324 base::TestTaskRunner task_runner;
325
326 TestHelper helper(&task_runner);
327 helper.StartServiceIfRequired();
328 helper.ConnectFakeProducer();
329 helper.ConnectConsumer();
330 helper.WaitForConsumerConnect();
331
332 TraceConfig trace_config;
333 SetTraceConfigForBugreportTest(&trace_config);
334 trace_config.set_file_write_period_ms(60000); // Will never hit this.
335 trace_config.set_write_into_file(true);
336
337 auto pipe_pair = base::Pipe::Create();
338 helper.StartTracing(trace_config, std::move(pipe_pair.wr));
339 helper.WaitForProducerEnabled();
340
341 EXPECT_TRUE(helper.SaveTraceForBugreportAndWait());
342 helper.WaitForTracingDisabled();
343
344 VerifyBugreportTraceContents();
345
346 // Now read the original file descriptor passed in.
347 std::string trace_bytes;
348 ASSERT_TRUE(base::ReadPlatformHandle(*pipe_pair.rd, &trace_bytes));
349 protos::gen::Trace trace;
350 ASSERT_TRUE(trace.ParseFromString(trace_bytes));
351 ASSERT_EQ(trace.packet().size(), 1u);
352 for (const auto& p : trace.packet()) {
353 ASSERT_TRUE(p.has_service_event());
354 ASSERT_TRUE(p.service_event().seized_for_bugreport());
355 }
356}
357
358// Tests that SaveTraceForBugreport() works also if the trace has triggers
359// defined and those triggers have not been hit. This is a regression test for
360// b/188008375 .
361#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
362// Disabled due to b/191940560
363#define MAYBE_SaveForBugreport_Triggers DISABLED_SaveForBugreport_Triggers
364#else
365#define MAYBE_SaveForBugreport_Triggers SaveForBugreport_Triggers
366#endif
367TEST(PerfettoAndroidIntegrationTest, MAYBE_SaveForBugreport_Triggers) {
368 base::TestTaskRunner task_runner;
369
370 TestHelper helper(&task_runner);
371 helper.StartServiceIfRequired();
372 helper.ConnectFakeProducer();
373 helper.ConnectConsumer();
374 helper.WaitForConsumerConnect();
375
376 TraceConfig trace_config;
377 SetTraceConfigForBugreportTest(&trace_config);
378 trace_config.set_duration_ms(0); // set_trigger_timeout_ms is used instead.
379 auto* trigger_config = trace_config.mutable_trigger_config();
380 trigger_config->set_trigger_timeout_ms(8.64e+7);
381 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
382 auto* trigger = trigger_config->add_triggers();
383 trigger->set_name("trigger_name");
384 trigger->set_stop_delay_ms(1);
385
386 helper.StartTracing(trace_config);
387 helper.WaitForProducerEnabled();
388
389 EXPECT_TRUE(helper.SaveTraceForBugreportAndWait());
390 helper.WaitForTracingDisabled();
391
392 VerifyBugreportTraceContents();
393
394 // Now read the original trace.
395 helper.ReadData();
396 helper.WaitForReadData();
397 const auto& packets = helper.full_trace();
398 ASSERT_EQ(packets.size(), 1u);
399 for (const auto& p : packets) {
400 ASSERT_TRUE(p.has_service_event());
401 ASSERT_TRUE(p.service_event().seized_for_bugreport());
402 }
403}
404
405} // namespace perfetto
406
407#endif // PERFETTO_OS_ANDROID