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