1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <chrono>
16 #include <thread>
17 #include <unistd.h>
18 #include <condition_variable>
19 #include <gtest/gtest.h>
20 #include <iservice_registry.h>
21 #include "vsync_receiver.h"
22 #include "vsync_controller.h"
23 #include "vsync_sampler.h"
24 #include "vsync_generator.h"
25 #include "vsync_distributor.h"
26 #include "accesstoken_kit.h"
27 #include "nativetoken_kit.h"
28 #include "token_setproc.h"
29 #include "vsync_type.h"
30
31 #include <iostream>
32
33 using namespace testing;
34 using namespace testing::ext;
35
36 namespace OHOS::Rosen {
37 namespace {
38 constexpr int32_t MAX_SIZE = 32;
39 typedef struct VSyncTimeStamps {
40 int64_t appTimestamps[MAX_SIZE] = {0};
41 int32_t appIndex = 0;
42 int64_t rsTimestamps[MAX_SIZE] = {0};
43 int32_t rsIndex = 0;
44 } VSyncTimeStamps;
45 VSyncTimeStamps g_timeStamps = {};
46 int32_t g_appVSyncFlag = 0;
47 int32_t g_rsVSyncFlag = 0;
48 constexpr int32_t SAMPLER_NUMBER = 6;
OnVSyncApp(int64_t time,void * data)49 static void OnVSyncApp(int64_t time, void *data)
50 {
51 g_appVSyncFlag = 1;
52 g_timeStamps.appTimestamps[g_timeStamps.appIndex++] = time;
53 g_timeStamps.appIndex %= MAX_SIZE;
54 }
OnVSyncRs(int64_t time,void * data)55 static void OnVSyncRs(int64_t time, void *data)
56 {
57 g_rsVSyncFlag = 1;
58 g_timeStamps.rsTimestamps[g_timeStamps.rsIndex++] = time;
59 g_timeStamps.rsIndex %= MAX_SIZE;
60 }
61 }
62 class VSyncLTPOTest : public testing::Test {
63 public:
64 int32_t JudgeRefreshRate(int64_t period);
65 void Process1();
66 void Process2();
67
68 sptr<VSyncSampler> vsyncSampler = nullptr;
69 sptr<VSyncController> appController = nullptr;
70 sptr<VSyncController> rsController = nullptr;
71 sptr<VSyncDistributor> appDistributor = nullptr;
72 sptr<VSyncDistributor> rsDistributor = nullptr;
73 sptr<VSyncGenerator> vsyncGenerator = nullptr;
74 sptr<VSyncReceiver> receiverApp = nullptr;
75 sptr<VSyncReceiver> receiverRs = nullptr;
76
77 static inline pid_t pid = 0;
78 static inline int pipeFd[2] = {};
79 static inline int pipe1Fd[2] = {};
80 static inline int32_t ipcSystemAbilityIDApp = 34156;
81 static inline int32_t ipcSystemAbilityIDRs = 34157;
82 };
83
InitNativeTokenInfo()84 static void InitNativeTokenInfo()
85 {
86 uint64_t tokenId;
87 const char *perms[2];
88 perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC";
89 perms[1] = "ohos.permission.CAMERA";
90 NativeTokenInfoParams infoInstance = {
91 .dcapsNum = 0,
92 .permsNum = 2,
93 .aclsNum = 0,
94 .dcaps = NULL,
95 .perms = perms,
96 .acls = NULL,
97 .processName = "dcamera_client_demo",
98 .aplStr = "system_basic",
99 };
100 tokenId = GetAccessTokenId(&infoInstance);
101 SetSelfTokenID(tokenId);
102 int32_t ret = Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
103 ASSERT_EQ(ret, Security::AccessToken::RET_SUCCESS);
104 std::this_thread::sleep_for(std::chrono::milliseconds(50)); // wait 50ms
105 }
106
JudgeRefreshRate(int64_t period)107 int32_t VSyncLTPOTest::JudgeRefreshRate(int64_t period)
108 {
109 if (period <= 0) {
110 return 0;
111 }
112 int32_t actualRefreshRate = round(1.0 / (static_cast<double>(period) / 1000000000.0)); // 1.0s == 1000000000.0ns
113 int32_t refreshRate = actualRefreshRate;
114 int32_t diff = 0;
115 while ((abs(refreshRate - actualRefreshRate) < 5) && // ±5Hz
116 (VSYNC_MAX_REFRESHRATE % refreshRate != 0)) {
117 if (diff < 0) {
118 diff = -diff;
119 } else {
120 diff = -diff - 1;
121 }
122 refreshRate = actualRefreshRate + diff;
123 }
124 return refreshRate;
125 }
126
Process1()127 void VSyncLTPOTest::Process1()
128 {
129 InitNativeTokenInfo();
130 vsyncGenerator = CreateVSyncGenerator();
131 vsyncSampler = CreateVSyncSampler();
132 int32_t count = 0;
133 int64_t timestamp = 16666667; // 16666667ns
134 while (count <= SAMPLER_NUMBER) {
135 vsyncSampler->AddSample(timestamp);
136 usleep(1000); // 1000us
137 timestamp += 16666667; // 16666667ns
138 count++;
139 }
140 vsyncGenerator->SetVSyncMode(VSYNC_MODE_LTPO);
141 std::cout << "pulse:" << vsyncGenerator->GetVSyncPulse() << std::endl;
142 appController = new VSyncController(vsyncGenerator, 0);
143 rsController = new VSyncController(vsyncGenerator, 0);
144 appDistributor = new VSyncDistributor(appController, "app");
145 rsDistributor = new VSyncDistributor(rsController, "rs");
146 sptr<VSyncConnection> connServerApp = new VSyncConnection(appDistributor, "app", nullptr, 1); // id:1
147 sptr<VSyncConnection> connServerRs = new VSyncConnection(rsDistributor, "rs", nullptr, 2); // id:2
148 appDistributor->AddConnection(connServerApp);
149 rsDistributor->AddConnection(connServerRs);
150 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
151 sam->AddSystemAbility(ipcSystemAbilityIDApp, connServerApp->AsObject());
152 sam->AddSystemAbility(ipcSystemAbilityIDRs, connServerRs->AsObject());
153 VSyncTimeStamps timeStamps = {};
154 vsyncGenerator->SetRSDistributor(rsDistributor);
155 vsyncGenerator->SetAppDistributor(appDistributor);
156
157 close(pipeFd[1]);
158 close(pipe1Fd[0]);
159 char buf[10] = "start";
160 write(pipe1Fd[1], buf, sizeof(buf));
161
162 // change refresh rate to 120hz
163 int changeRefreshRate = 0;
164 read(pipeFd[0], &changeRefreshRate, sizeof(changeRefreshRate));
165 std::vector<std::pair<uint64_t, uint32_t>> refreshRates = {{1, 120}}; // 120hz
166 VSyncGenerator::ListenerRefreshRateData listenerRefreshRates = {
167 .cb = appController,
168 .refreshRates = refreshRates
169 };
170 VSyncGenerator::ListenerPhaseOffsetData listenerPhaseOffset = {
171 .cb = appController,
172 .phaseByPulseNum = 0
173 };
174 uint32_t generatorRefreshRate = 120; // 120hz
175 vsyncGenerator->ChangeGeneratorRefreshRateModel(listenerRefreshRates, listenerPhaseOffset, generatorRefreshRate);
176 // checkout 120hz
177 read(pipeFd[0], &timeStamps, sizeof(timeStamps));
178 int64_t appTimestampPrev = timeStamps.appTimestamps[(timeStamps.appIndex - 2) % MAX_SIZE]; // prev should minus 2
179 int64_t appTimestampCur = timeStamps.appTimestamps[(timeStamps.appIndex - 1) % MAX_SIZE]; // cur should minus 1
180 int64_t rsTimestampPrev = timeStamps.rsTimestamps[(timeStamps.rsIndex - 2) % MAX_SIZE]; // prev should minus 2
181 int64_t rsTimestampCur = timeStamps.rsTimestamps[(timeStamps.rsIndex - 1) % MAX_SIZE]; // cur should minus 1
182 int64_t appPeriod = appTimestampCur - appTimestampPrev;
183 int64_t rsPeriod = rsTimestampCur - rsTimestampPrev;
184 int32_t appRefreshRate = JudgeRefreshRate(appPeriod);
185 int32_t rsRefreshRate = JudgeRefreshRate(rsPeriod);
186 EXPECT_EQ(appRefreshRate, 120); // 120hz
187 EXPECT_EQ(rsRefreshRate, 120); // 120hz
188 if (appRefreshRate != 120) { // 120hz
189 std::string appTimestamps = "appTimestamps:[";
190 for (int i = 0; i < 15; i++) { // check last 15 samples
191 appTimestamps += std::to_string(g_timeStamps.appTimestamps[i]) + ",";
192 }
193 appTimestamps += "]";
194 std::cout << appTimestamps << std::endl;
195 }
196 if (rsRefreshRate != 120) { // 120hz
197 std::string rsTimestamps = "rsTimestamps:[";
198 for (int i = 0; i < 15; i++) { // check last 15 samples
199 rsTimestamps += std::to_string(g_timeStamps.rsTimestamps[i]) + ",";
200 }
201 rsTimestamps += "]";
202 std::cout << rsTimestamps << std::endl;
203 }
204 std::cout << "appPeriod:" << appPeriod <<
205 ", appRefreshRate:" << appRefreshRate <<
206 ", rsPeriod:" << rsPeriod <<
207 ", rsRefreshRate:" << rsRefreshRate << std::endl;
208
209 // change refresh rate to 90hz
210 changeRefreshRate = 0;
211 read(pipeFd[0], &changeRefreshRate, sizeof(changeRefreshRate));
212 refreshRates = {{1, 90}}; // 90hz
213 listenerRefreshRates = {
214 .cb = appController,
215 .refreshRates = refreshRates
216 };
217 listenerPhaseOffset = {
218 .cb = appController,
219 .phaseByPulseNum = 1 // phase is 1 pulse
220 };
221 generatorRefreshRate = 90; // 90hz
222 vsyncGenerator->ChangeGeneratorRefreshRateModel(listenerRefreshRates, listenerPhaseOffset, generatorRefreshRate);
223 // checkout 90hz
224 read(pipeFd[0], &timeStamps, sizeof(timeStamps));
225 appTimestampPrev = timeStamps.appTimestamps[(timeStamps.appIndex - 2) % MAX_SIZE]; // prev should minus 2
226 appTimestampCur = timeStamps.appTimestamps[(timeStamps.appIndex - 1) % MAX_SIZE]; // cur should minus 1
227 rsTimestampPrev = timeStamps.rsTimestamps[(timeStamps.rsIndex - 2) % MAX_SIZE]; // prev should minus 2
228 rsTimestampCur = timeStamps.rsTimestamps[(timeStamps.rsIndex - 1) % MAX_SIZE]; // cur should minus 1
229 appPeriod = appTimestampCur - appTimestampPrev;
230 rsPeriod = rsTimestampCur - rsTimestampPrev;
231 appRefreshRate = JudgeRefreshRate(appPeriod);
232 rsRefreshRate = JudgeRefreshRate(rsPeriod);
233 EXPECT_EQ(appRefreshRate, 90); // 90hz
234 EXPECT_EQ(rsRefreshRate, 90); // 90hz
235 if (appRefreshRate != 90) { // 90hz
236 std::string appTimestamps = "appTimestamps:[";
237 for (int i = 0; i < 15; i++) { // check last 15 samples
238 appTimestamps += std::to_string(g_timeStamps.appTimestamps[i]) + ",";
239 }
240 appTimestamps += "]";
241 std::cout << appTimestamps << std::endl;
242 }
243 if (rsRefreshRate != 90) { // 90hz
244 std::string rsTimestamps = "rsTimestamps:[";
245 for (int i = 0; i < 15; i++) { // check last 15 samples
246 rsTimestamps += std::to_string(g_timeStamps.rsTimestamps[i]) + ",";
247 }
248 rsTimestamps += "]";
249 std::cout << rsTimestamps << std::endl;
250 }
251 std::cout << "appPeriod:" << appPeriod <<
252 ", appRefreshRate:" << appRefreshRate <<
253 ", rsPeriod:" << rsPeriod <<
254 ", rsRefreshRate:" << rsRefreshRate << std::endl;
255
256 // change refresh rate to 60hz
257 changeRefreshRate = 0;
258 read(pipeFd[0], &changeRefreshRate, sizeof(changeRefreshRate));
259 refreshRates = {{1, 60}}; // 60hz
260 listenerRefreshRates = {
261 .cb = appController,
262 .refreshRates = refreshRates
263 };
264 listenerPhaseOffset = {
265 .cb = appController,
266 .phaseByPulseNum = 3 // phase is 3 pulse
267 };
268 generatorRefreshRate = 60; // 60hz
269 vsyncGenerator->ChangeGeneratorRefreshRateModel(listenerRefreshRates, listenerPhaseOffset, generatorRefreshRate);
270 // checkout 60hz
271 read(pipeFd[0], &timeStamps, sizeof(timeStamps));
272 appTimestampPrev = timeStamps.appTimestamps[(timeStamps.appIndex - 2) % MAX_SIZE]; // prev should minus 2
273 appTimestampCur = timeStamps.appTimestamps[(timeStamps.appIndex - 1) % MAX_SIZE]; // cur should minus 1
274 rsTimestampPrev = timeStamps.rsTimestamps[(timeStamps.rsIndex - 2) % MAX_SIZE]; // prev should minus 2
275 rsTimestampCur = timeStamps.rsTimestamps[(timeStamps.rsIndex - 1) % MAX_SIZE]; // cur should minus 1
276 appPeriod = appTimestampCur - appTimestampPrev;
277 rsPeriod = rsTimestampCur - rsTimestampPrev;
278 appRefreshRate = JudgeRefreshRate(appPeriod);
279 rsRefreshRate = JudgeRefreshRate(rsPeriod);
280 EXPECT_EQ(appRefreshRate, 60); // 60hz
281 EXPECT_EQ(rsRefreshRate, 60); // 60hz
282 if (appRefreshRate != 60) { // 60hz
283 std::string appTimestamps = "appTimestamps:[";
284 for (int i = 0; i < 15; i++) { // check last 15 samples
285 appTimestamps += std::to_string(g_timeStamps.appTimestamps[i]) + ",";
286 }
287 appTimestamps += "]";
288 std::cout << appTimestamps << std::endl;
289 }
290 if (rsRefreshRate != 60) { // 60hz
291 std::string rsTimestamps = "rsTimestamps:[";
292 for (int i = 0; i < 15; i++) { // check last 15 samples
293 rsTimestamps += std::to_string(g_timeStamps.rsTimestamps[i]) + ",";
294 }
295 rsTimestamps += "]";
296 std::cout << rsTimestamps << std::endl;
297 }
298 std::cout << "appPeriod:" << appPeriod <<
299 ", appRefreshRate:" << appRefreshRate <<
300 ", rsPeriod:" << rsPeriod <<
301 ", rsRefreshRate:" << rsRefreshRate << std::endl;
302
303 // change refresh rate to 30hz
304 changeRefreshRate = 0;
305 read(pipeFd[0], &changeRefreshRate, sizeof(changeRefreshRate));
306 refreshRates = {{1, 30}}; // 30hz
307 listenerRefreshRates = {
308 .cb = appController,
309 .refreshRates = refreshRates
310 };
311 listenerPhaseOffset = {
312 .cb = appController,
313 .phaseByPulseNum = 9 // phase is 9 pulse
314 };
315 generatorRefreshRate = 30; // 30hz
316 vsyncGenerator->ChangeGeneratorRefreshRateModel(listenerRefreshRates, listenerPhaseOffset, generatorRefreshRate);
317 // checkout 30hz
318 read(pipeFd[0], &timeStamps, sizeof(timeStamps));
319 appTimestampPrev = timeStamps.appTimestamps[(timeStamps.appIndex - 2) % MAX_SIZE]; // prev should minus 2
320 appTimestampCur = timeStamps.appTimestamps[(timeStamps.appIndex - 1) % MAX_SIZE]; // cur should minus 1
321 rsTimestampPrev = timeStamps.rsTimestamps[(timeStamps.rsIndex - 2) % MAX_SIZE]; // prev should minus 2
322 rsTimestampCur = timeStamps.rsTimestamps[(timeStamps.rsIndex - 1) % MAX_SIZE]; // cur should minus 1
323 appPeriod = appTimestampCur - appTimestampPrev;
324 rsPeriod = rsTimestampCur - rsTimestampPrev;
325 appRefreshRate = JudgeRefreshRate(appPeriod);
326 rsRefreshRate = JudgeRefreshRate(rsPeriod);
327 EXPECT_EQ(appRefreshRate, 30); // 30hz
328 EXPECT_EQ(rsRefreshRate, 30); // 30hz
329 if (appRefreshRate != 30) { // 30hz
330 std::string appTimestamps = "appTimestamps:[";
331 for (int i = 0; i < 15; i++) { // check last 15 samples
332 appTimestamps += std::to_string(g_timeStamps.appTimestamps[i]) + ",";
333 }
334 appTimestamps += "]";
335 std::cout << appTimestamps << std::endl;
336 }
337 if (rsRefreshRate != 30) { // 30hz
338 std::string rsTimestamps = "rsTimestamps:[";
339 for (int i = 0; i < 15; i++) { // check last 15 samples
340 rsTimestamps += std::to_string(g_timeStamps.rsTimestamps[i]) + ",";
341 }
342 rsTimestamps += "]";
343 std::cout << rsTimestamps << std::endl;
344 }
345 std::cout << "appPeriod:" << appPeriod <<
346 ", appRefreshRate:" << appRefreshRate <<
347 ", rsPeriod:" << rsPeriod <<
348 ", rsRefreshRate:" << rsRefreshRate << std::endl;
349
350 read(pipeFd[0], buf, sizeof(buf));
351 sam->RemoveSystemAbility(ipcSystemAbilityIDApp);
352 sam->RemoveSystemAbility(ipcSystemAbilityIDRs);
353 close(pipeFd[0]);
354 close(pipe1Fd[1]);
355 exit(0);
356 }
357
Process2()358 void VSyncLTPOTest::Process2()
359 {
360 close(pipeFd[0]);
361 close(pipe1Fd[1]);
362 char buf[10];
363 read(pipe1Fd[0], buf, sizeof(buf));
364 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
365 auto robjApp = sam->GetSystemAbility(ipcSystemAbilityIDApp);
366 auto robjRs = sam->GetSystemAbility(ipcSystemAbilityIDRs);
367 std::cout << "(robjApp == nullptr):" << (robjApp == nullptr) << std::endl;
368 std::cout << "(robjRs == nullptr):" << (robjRs == nullptr) << std::endl;
369 auto connApp = iface_cast<IVSyncConnection>(robjApp);
370 auto connRs = iface_cast<IVSyncConnection>(robjRs);
371 receiverApp = new VSyncReceiver(connApp);
372 receiverRs = new VSyncReceiver(connRs);
373 receiverApp->Init();
374 receiverRs->Init();
375 VSyncReceiver::FrameCallback fcbApp = {
376 .userData_ = nullptr,
377 .callback_ = OnVSyncApp,
378 };
379 VSyncReceiver::FrameCallback fcbRs = {
380 .userData_ = nullptr,
381 .callback_ = OnVSyncRs,
382 };
383
384 // change refresh rate to 120hz
385 int changeRefreshRate = 0;
386 write(pipeFd[1], &changeRefreshRate, sizeof(changeRefreshRate));
387 int num = 3; // RequestNextVSync 3 times
388 while (num--) {
389 receiverApp->RequestNextVSync(fcbApp);
390 receiverRs->RequestNextVSync(fcbRs);
391 while (g_appVSyncFlag == 0 || g_rsVSyncFlag == 0) {
392 usleep(100); // 100us
393 }
394 g_appVSyncFlag = 0;
395 g_rsVSyncFlag = 0;
396 }
397 write(pipeFd[1], &g_timeStamps, sizeof(g_timeStamps));
398
399 // change refresh rate to 90hz
400 changeRefreshRate = 0;
401 write(pipeFd[1], &changeRefreshRate, sizeof(changeRefreshRate));
402 num = 3; // RequestNextVSync 3 times
403 while (num--) {
404 receiverApp->RequestNextVSync(fcbApp);
405 receiverRs->RequestNextVSync(fcbRs);
406 while (g_appVSyncFlag == 0 || g_rsVSyncFlag == 0) {
407 usleep(100); // 100us
408 }
409 g_appVSyncFlag = 0;
410 g_rsVSyncFlag = 0;
411 }
412 write(pipeFd[1], &g_timeStamps, sizeof(g_timeStamps));
413
414 // change refresh rate to 60hz
415 changeRefreshRate = 0;
416 write(pipeFd[1], &changeRefreshRate, sizeof(changeRefreshRate));
417 num = 3; // RequestNextVSync 3 times
418 while (num--) {
419 receiverApp->RequestNextVSync(fcbApp);
420 receiverRs->RequestNextVSync(fcbRs);
421 while (g_appVSyncFlag == 0 || g_rsVSyncFlag == 0) {
422 usleep(100); // 100us
423 }
424 g_appVSyncFlag = 0;
425 g_rsVSyncFlag = 0;
426 }
427 write(pipeFd[1], &g_timeStamps, sizeof(g_timeStamps));
428
429 // change refresh rate to 30hz
430 changeRefreshRate = 0;
431 write(pipeFd[1], &changeRefreshRate, sizeof(changeRefreshRate));
432 num = 3; // RequestNextVSync 3 times
433 while (num--) {
434 receiverApp->RequestNextVSync(fcbApp);
435 receiverRs->RequestNextVSync(fcbRs);
436 while (g_appVSyncFlag == 0 || g_rsVSyncFlag == 0) {
437 usleep(100); // 100us
438 }
439 g_appVSyncFlag = 0;
440 g_rsVSyncFlag = 0;
441 }
442 write(pipeFd[1], &g_timeStamps, sizeof(g_timeStamps));
443 }
444
445 HWTEST_F(VSyncLTPOTest, ChangeRefreshRateTest, Function | MediumTest | Level2)
446 {
447 if (pipe(pipeFd) < 0) {
448 exit(1);
449 }
450 if (pipe(pipe1Fd) < 0) {
451 exit(0);
452 }
453 pid = fork();
454 if (pid < 0) {
455 exit(1);
456 }
457 if (pid != 0) {
458 Process1();
459 } else {
460 Process2();
461 }
462 }
463 }
464