1 /*
2 * Copyright (C) 2018 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 "src/traced/service/builtin_producer.h"
18
19 #include "perfetto/tracing/core/data_source_config.h"
20 #include "src/base/test/test_task_runner.h"
21 #include "test/gtest_and_gmock.h"
22
23 #include "protos/perfetto/config/android/android_sdk_sysprop_guard_config.gen.h"
24
25 namespace perfetto {
26 namespace {
27
28 constexpr char kHeapprofdDataSourceName[] = "android.heapprofd";
29 constexpr char kTracedPerfDataSourceName[] = "linux.perf";
30 constexpr char kLazyHeapprofdPropertyName[] = "traced.lazy.heapprofd";
31 constexpr char kLazyTracedPerfPropertyName[] = "traced.lazy.traced_perf";
32
33 constexpr char kAndroidSdkSyspropGuardDataSourceName[] =
34 "android.sdk_sysprop_guard";
35 constexpr char kPerfettoSdkSyspropGuardGenerationPropertyName[] =
36 "debug.tracing.ctl.perfetto.sdk_sysprop_guard_generation";
37 constexpr char kHwuiSkiaBroadTracingPropertyName[] =
38 "debug.tracing.ctl.hwui.skia_tracing_enabled";
39 constexpr char kHwuiSkiaUsePerfettoPropertyName[] =
40 "debug.tracing.ctl.hwui.skia_use_perfetto_track_events";
41 constexpr char kHwuiSkiaPropertyPackageSeparator[] = ".";
42 constexpr char kSurfaceFlingerSkiaBroadTracingPropertyName[] =
43 "debug.tracing.ctl.renderengine.skia_tracing_enabled";
44 constexpr char kSurfaceFlingerSkiaUsePerfettoPropertyName[] =
45 "debug.tracing.ctl.renderengine.skia_use_perfetto_track_events";
46
47 using ::testing::_;
48 using ::testing::InvokeWithoutArgs;
49 using ::testing::Mock;
50 using ::testing::Return;
51 using ::testing::StrictMock;
52
53 class MockBuiltinProducer : public BuiltinProducer {
54 public:
MockBuiltinProducer(base::TaskRunner * task_runner)55 MockBuiltinProducer(base::TaskRunner* task_runner)
56 : BuiltinProducer(task_runner, /*lazy_stop_delay_ms=*/0) {}
57
58 MOCK_METHOD(bool,
59 SetAndroidProperty,
60 (const std::string&, const std::string&),
61 (override));
62 };
63
TEST(BuiltinProducerTest,LazyHeapprofdSimple)64 TEST(BuiltinProducerTest, LazyHeapprofdSimple) {
65 DataSourceConfig cfg;
66 cfg.set_name(kHeapprofdDataSourceName);
67 base::TestTaskRunner task_runner;
68 auto done = task_runner.CreateCheckpoint("done");
69 StrictMock<MockBuiltinProducer> p(&task_runner);
70 testing::InSequence s;
71 EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "1"))
72 .WillOnce(Return(true));
73 EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, ""))
74 .WillOnce(InvokeWithoutArgs([&done]() {
75 done();
76 return true;
77 }));
78 p.SetupDataSource(1, cfg);
79 p.StopDataSource(1);
80 task_runner.RunUntilCheckpoint("done");
81 }
82
TEST(BuiltinProducerTest,LazyTracedPerfSimple)83 TEST(BuiltinProducerTest, LazyTracedPerfSimple) {
84 DataSourceConfig cfg;
85 cfg.set_name(kTracedPerfDataSourceName);
86 base::TestTaskRunner task_runner;
87 auto done = task_runner.CreateCheckpoint("done");
88 StrictMock<MockBuiltinProducer> p(&task_runner);
89 testing::InSequence s;
90 EXPECT_CALL(p, SetAndroidProperty(kLazyTracedPerfPropertyName, "1"))
91 .WillOnce(Return(true));
92 EXPECT_CALL(p, SetAndroidProperty(kLazyTracedPerfPropertyName, ""))
93 .WillOnce(InvokeWithoutArgs([&done]() {
94 done();
95 return true;
96 }));
97 p.SetupDataSource(1, cfg);
98 p.StopDataSource(1);
99 task_runner.RunUntilCheckpoint("done");
100 }
101
TEST(BuiltinProducerTest,LazyHeapprofdRefCount)102 TEST(BuiltinProducerTest, LazyHeapprofdRefCount) {
103 DataSourceConfig cfg;
104 cfg.set_name(kHeapprofdDataSourceName);
105 base::TestTaskRunner task_runner;
106 auto done = task_runner.CreateCheckpoint("done");
107 StrictMock<MockBuiltinProducer> p(&task_runner);
108 testing::InSequence s;
109 EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "1"))
110 .WillRepeatedly(Return(true));
111 p.SetupDataSource(1, cfg);
112 p.SetupDataSource(2, cfg);
113 p.StopDataSource(2);
114 task_runner.RunUntilIdle();
115 EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, ""))
116 .WillOnce(InvokeWithoutArgs([&done]() {
117 done();
118 return true;
119 }));
120 p.StopDataSource(1);
121 task_runner.RunUntilCheckpoint("done");
122 }
123
TEST(BuiltinProducerTest,LazyHeapprofdNoFlap)124 TEST(BuiltinProducerTest, LazyHeapprofdNoFlap) {
125 DataSourceConfig cfg;
126 cfg.set_name(kHeapprofdDataSourceName);
127 base::TestTaskRunner task_runner;
128 auto done = task_runner.CreateCheckpoint("done");
129 StrictMock<MockBuiltinProducer> p(&task_runner);
130 testing::InSequence s;
131 EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "1"))
132 .WillRepeatedly(Return(true));
133 p.SetupDataSource(1, cfg);
134 p.StopDataSource(1);
135 p.SetupDataSource(2, cfg);
136 task_runner.RunUntilIdle();
137 p.StopDataSource(2);
138 EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, ""))
139 .WillOnce(InvokeWithoutArgs([&done]() {
140 done();
141 return true;
142 }));
143 task_runner.RunUntilCheckpoint("done");
144 }
145
TEST(BuiltinProducerTest,LazyRefCountsIndependent)146 TEST(BuiltinProducerTest, LazyRefCountsIndependent) {
147 DataSourceConfig cfg_perf;
148 cfg_perf.set_name(kTracedPerfDataSourceName);
149 DataSourceConfig cfg_heap;
150 cfg_heap.set_name(kHeapprofdDataSourceName);
151
152 base::TestTaskRunner task_runner;
153 StrictMock<MockBuiltinProducer> p(&task_runner);
154 testing::InSequence s;
155
156 // start one instance of both types of sources
157 EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "1"))
158 .WillOnce(Return(true));
159 EXPECT_CALL(p, SetAndroidProperty(kLazyTracedPerfPropertyName, "1"))
160 .WillOnce(Return(true));
161 p.SetupDataSource(1, cfg_heap);
162 p.SetupDataSource(2, cfg_perf);
163 task_runner.RunUntilIdle();
164 Mock::VerifyAndClearExpectations(&p);
165
166 // stop heapprofd source
167 EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, ""))
168 .WillOnce(Return(true));
169 p.StopDataSource(1);
170 task_runner.RunUntilIdle();
171 Mock::VerifyAndClearExpectations(&p);
172
173 // stop traced_perf source
174 EXPECT_CALL(p, SetAndroidProperty(kLazyTracedPerfPropertyName, ""))
175 .WillOnce(Return(true));
176 p.StopDataSource(2);
177 task_runner.RunUntilIdle();
178 Mock::VerifyAndClearExpectations(&p);
179 }
180
181 class AndroidSdkSyspropGuardParameterizedTestFixture
182 : public ::testing::TestWithParam<bool> {
183 public:
184 static constexpr int ITERATIONS = 3;
185 };
186
TEST_P(AndroidSdkSyspropGuardParameterizedTestFixture,SurfaceFlinger)187 TEST_P(AndroidSdkSyspropGuardParameterizedTestFixture, SurfaceFlinger) {
188 bool should_enable = GetParam();
189
190 // Set SF flag in config
191 protos::gen::AndroidSdkSyspropGuardConfig sysprop_guard;
192 sysprop_guard.set_surfaceflinger_skia_track_events(should_enable);
193
194 base::TestTaskRunner task_runner;
195 StrictMock<MockBuiltinProducer> p(&task_runner);
196 DataSourceConfig cfg;
197 cfg.set_name(kAndroidSdkSyspropGuardDataSourceName);
198 cfg.set_android_sdk_sysprop_guard_config_raw(
199 sysprop_guard.SerializeAsString());
200
201 // Expect SF props set
202 EXPECT_CALL(p, SetAndroidProperty(kSurfaceFlingerSkiaBroadTracingPropertyName,
203 "true"))
204 .Times(should_enable ? 1 : 0)
205 .WillOnce(Return(true));
206 EXPECT_CALL(
207 p, SetAndroidProperty(kSurfaceFlingerSkiaUsePerfettoPropertyName, "true"))
208 .Times(should_enable ? 1 : 0)
209 .WillOnce(Return(true));
210 EXPECT_CALL(p, SetAndroidProperty(
211 kPerfettoSdkSyspropGuardGenerationPropertyName, "1"))
212 .Times(should_enable ? 1 : 0)
213 .WillOnce(Return(true));
214
215 // Sysprops should only be set once given the same config
216 for (int i = 0; i < ITERATIONS; i++) {
217 p.SetupDataSource(1, cfg);
218 p.StopDataSource(1);
219 task_runner.RunUntilIdle();
220 }
221 Mock::VerifyAndClearExpectations(&p);
222 }
223
TEST_P(AndroidSdkSyspropGuardParameterizedTestFixture,HwuiGlobal)224 TEST_P(AndroidSdkSyspropGuardParameterizedTestFixture, HwuiGlobal) {
225 bool should_enable = GetParam();
226
227 // Set HWUI flag in config.
228 // The package filter is left BLANK so this applies GLOBALLY.
229 protos::gen::AndroidSdkSyspropGuardConfig sysprop_guard;
230 sysprop_guard.set_hwui_skia_track_events(should_enable);
231
232 base::TestTaskRunner task_runner;
233 StrictMock<MockBuiltinProducer> p(&task_runner);
234 DataSourceConfig cfg;
235 cfg.set_name(kAndroidSdkSyspropGuardDataSourceName);
236 cfg.set_android_sdk_sysprop_guard_config_raw(
237 sysprop_guard.SerializeAsString());
238
239 // Expect GLOBAL props set for HWUI.
240 EXPECT_CALL(p, SetAndroidProperty(kHwuiSkiaBroadTracingPropertyName, "true"))
241 .Times(should_enable ? 1 : 0)
242 .WillOnce(Return(true));
243 EXPECT_CALL(p, SetAndroidProperty(kHwuiSkiaUsePerfettoPropertyName, "true"))
244 .Times(should_enable ? 1 : 0)
245 .WillOnce(Return(true));
246 EXPECT_CALL(p, SetAndroidProperty(
247 kPerfettoSdkSyspropGuardGenerationPropertyName, "1"))
248 .Times(should_enable ? 1 : 0)
249 .WillOnce(Return(true));
250
251 // Sysprops should only be set once given the same config
252 for (int i = 0; i < ITERATIONS; i++) {
253 p.SetupDataSource(1, cfg);
254 p.StopDataSource(1);
255 task_runner.RunUntilIdle();
256 }
257 Mock::VerifyAndClearExpectations(&p);
258 }
259
TEST_P(AndroidSdkSyspropGuardParameterizedTestFixture,HwuiPackageFiltered)260 TEST_P(AndroidSdkSyspropGuardParameterizedTestFixture, HwuiPackageFiltered) {
261 bool should_enable = GetParam();
262
263 std::string packages[] = {"test1", "com.android.systemui", "test3"};
264 // Set HWUI flag in config. Package filter left blank.
265 // The package filter is SET so this applies SELECTIVELY.
266 protos::gen::AndroidSdkSyspropGuardConfig sysprop_guard;
267 sysprop_guard.set_hwui_skia_track_events(should_enable);
268 for (std::string package : packages) {
269 sysprop_guard.add_hwui_package_name_filter(package);
270 }
271
272 base::TestTaskRunner task_runner;
273 StrictMock<MockBuiltinProducer> p(&task_runner);
274 DataSourceConfig cfg;
275 cfg.set_name(kAndroidSdkSyspropGuardDataSourceName);
276 cfg.set_android_sdk_sysprop_guard_config_raw(
277 sysprop_guard.SerializeAsString());
278
279 // Expect APP-SPECIFIC props set for HWUI.
280 for (std::string package : packages) {
281 EXPECT_CALL(
282 p, SetAndroidProperty(kHwuiSkiaBroadTracingPropertyName +
283 (kHwuiSkiaPropertyPackageSeparator + package),
284 "true"))
285 .Times(should_enable ? 1 : 0)
286 .WillOnce(Return(true));
287 EXPECT_CALL(
288 p, SetAndroidProperty(kHwuiSkiaUsePerfettoPropertyName +
289 (kHwuiSkiaPropertyPackageSeparator + package),
290 "true"))
291 .Times(should_enable ? 1 : 0)
292 .WillOnce(Return(true));
293 }
294 EXPECT_CALL(p, SetAndroidProperty(
295 kPerfettoSdkSyspropGuardGenerationPropertyName, "1"))
296 .Times(should_enable ? 1 : 0)
297 .WillOnce(Return(true));
298
299 // Sysprops should only be set once given the same config
300 for (int i = 0; i < ITERATIONS; i++) {
301 p.SetupDataSource(1, cfg);
302 p.StopDataSource(1);
303 task_runner.RunUntilIdle();
304 }
305 Mock::VerifyAndClearExpectations(&p);
306 }
307
308 INSTANTIATE_TEST_SUITE_P(BuiltinProducerTest,
309 AndroidSdkSyspropGuardParameterizedTestFixture,
310 testing::Values(true, false));
311
312 } // namespace
313 } // namespace perfetto
314