• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #ifdef SUPPORT_ACCESS_TOKEN
28 #include "nativetoken_kit.h"
29 #include "token_setproc.h"
30 #endif
31 #include "vsync_type.h"
32 
33 #include <iostream>
34 
35 using namespace testing;
36 using namespace testing::ext;
37 
38 namespace OHOS::Rosen {
SystemTime()39 static int64_t SystemTime()
40 {
41     timespec t = {};
42     clock_gettime(CLOCK_MONOTONIC, &t);
43     return int64_t(t.tv_sec) * 1000000000LL + t.tv_nsec; // 1000000000ns == 1s
44 }
45 
46 namespace {
47 constexpr int32_t MAX_SIZE = 128;
48 typedef struct VSyncTimeStamps {
49     int64_t appTimestamps[MAX_SIZE] = {0};
50     int32_t appIndex = 0;
51     int64_t rsTimestamps[MAX_SIZE] = {0};
52     int32_t rsIndex = 0;
53 } VSyncTimeStamps;
54 VSyncTimeStamps g_timeStamps = {};
55 int32_t g_appVSyncFlag = 0;
56 int32_t g_rsVSyncFlag = 0;
57 constexpr int32_t SAMPLER_NUMBER = 6;
OnVSyncApp(int64_t time,void * data)58 static void OnVSyncApp(int64_t time, void *data)
59 {
60     g_appVSyncFlag = 1;
61     g_timeStamps.appTimestamps[g_timeStamps.appIndex++] = time;
62     g_timeStamps.appIndex %= MAX_SIZE;
63 }
OnVSyncRs(int64_t time,void * data)64 static void OnVSyncRs(int64_t time, void *data)
65 {
66     g_rsVSyncFlag = 1;
67     g_timeStamps.rsTimestamps[g_timeStamps.rsIndex++] = time;
68     g_timeStamps.rsIndex %= MAX_SIZE;
69 }
70 }
71 class VSync30To60Test : public testing::Test {
72 public:
73     int32_t JudgeRefreshRate(int64_t period);
74     void Process1();
75     void Process2();
76 
77     sptr<VSyncSampler> vsyncSampler = nullptr;
78     sptr<VSyncController> appController = nullptr;
79     sptr<VSyncController> rsController = nullptr;
80     sptr<VSyncDistributor> appDistributor = nullptr;
81     sptr<VSyncDistributor> rsDistributor = nullptr;
82     sptr<VSyncGenerator> vsyncGenerator = nullptr;
83     sptr<VSyncReceiver> receiverApp = nullptr;
84     sptr<VSyncReceiver> receiverRs = nullptr;
85 
86     static inline pid_t pid = 0;
87     static inline int pipeFd[2] = {};
88     static inline int pipe1Fd[2] = {};
89     static inline int32_t ipcSystemAbilityIDApp = 34156;
90     static inline int32_t ipcSystemAbilityIDRs = 34157;
91 };
92 
InitNativeTokenInfo()93 static void InitNativeTokenInfo()
94 {
95 #ifdef SUPPORT_ACCESS_TOKEN
96     uint64_t tokenId;
97     const char *perms[2];
98     perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC";
99     perms[1] = "ohos.permission.CAMERA";
100     NativeTokenInfoParams infoInstance = {
101         .dcapsNum = 0,
102         .permsNum = 2,
103         .aclsNum = 0,
104         .dcaps = NULL,
105         .perms = perms,
106         .acls = NULL,
107         .processName = "dcamera_client_demo",
108         .aplStr = "system_basic",
109     };
110     tokenId = GetAccessTokenId(&infoInstance);
111     SetSelfTokenID(tokenId);
112     int32_t ret = Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
113     ASSERT_EQ(ret, Security::AccessToken::RET_SUCCESS);
114     std::this_thread::sleep_for(std::chrono::milliseconds(50));  // wait 50ms
115 #endif
116 }
117 
JudgeRefreshRate(int64_t period)118 int32_t VSync30To60Test::JudgeRefreshRate(int64_t period)
119 {
120     if (period <= 0) {
121         return 0;
122     }
123     int32_t actualRefreshRate = round(1.0 / (static_cast<double>(period) / 1000000000.0)); // 1.0s == 1000000000.0ns
124     int32_t refreshRate = actualRefreshRate;
125     int32_t diff = 0;
126     while ((abs(refreshRate - actualRefreshRate) < 5) && // ±5Hz
127            (CreateVSyncGenerator()->GetVSyncMaxRefreshRate() % refreshRate != 0)) {
128         if (diff < 0) {
129             diff = -diff;
130         } else {
131             diff = -diff - 1;
132         }
133         refreshRate = actualRefreshRate + diff;
134     }
135     return refreshRate;
136 }
137 
Process1()138 void VSync30To60Test::Process1()
139 {
140 #ifdef SUPPORT_ACCESS_TOKEN
141     InitNativeTokenInfo();
142     vsyncGenerator = CreateVSyncGenerator();
143     vsyncSampler = CreateVSyncSampler();
144     int32_t count = 0;
145     int64_t timestamp = 16666667; // 16666667ns
146     while (count <= SAMPLER_NUMBER) {
147         vsyncSampler->AddSample(timestamp);
148         usleep(1000); // 1000us
149         timestamp += 16666667; // 16666667ns
150         count++;
151     }
152     vsyncGenerator->SetVSyncMode(VSYNC_MODE_LTPO);
153     std::cout << "pulse:" << vsyncGenerator->GetVSyncPulse() << std::endl;
154     appController = new VSyncController(vsyncGenerator, 0);
155     rsController = new VSyncController(vsyncGenerator, 0);
156     appDistributor = new VSyncDistributor(appController, "appTest");
157     rsDistributor = new VSyncDistributor(rsController, "rsTest");
158     sptr<VSyncConnection> connServerApp = new VSyncConnection(appDistributor, "appTest", nullptr, 1); // id:1
159     sptr<VSyncConnection> connServerRs = new VSyncConnection(rsDistributor, "rsTest", nullptr, 2); // id:2
160     appDistributor->AddConnection(connServerApp);
161     rsDistributor->AddConnection(connServerRs);
162     auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
163     sam->AddSystemAbility(ipcSystemAbilityIDApp, connServerApp->AsObject());
164     sam->AddSystemAbility(ipcSystemAbilityIDRs, connServerRs->AsObject());
165     VSyncTimeStamps timeStamps = {};
166     vsyncGenerator->SetRSDistributor(rsDistributor);
167     vsyncGenerator->SetAppDistributor(appDistributor);
168 
169     close(pipeFd[1]);
170     close(pipe1Fd[0]);
171     char buf[10] = "start";
172     write(pipe1Fd[1], buf, sizeof(buf));
173 
174     int changeRefreshRate;
175     std::vector<std::pair<uint64_t, uint32_t>> refreshRates;
176     VSyncGenerator::ListenerRefreshRateData listenerRefreshRates;
177     VSyncGenerator::ListenerPhaseOffsetData listenerPhaseOffset;
178     int64_t rsVsyncCount;
179     uint32_t generatorRefreshRate;
180     int64_t appTimestampPrev;
181     int64_t appTimestampCur;
182     int64_t rsTimestampPrev;
183     int64_t rsTimestampCur;
184     int64_t appPeriod;
185     int64_t rsPeriod;
186     int32_t appRefreshRate;
187     int32_t rsRefreshRate;
188 
189     int testTimes = 3; // test 3 times
190     while (testTimes--) {
191         // change refresh rate to 30hz
192         changeRefreshRate = 0;
193         read(pipeFd[0], &changeRefreshRate, sizeof(changeRefreshRate));
194         refreshRates = {{1, 30}}; // 30hz
195         listenerRefreshRates = {
196             .cb = appController,
197             .refreshRates = refreshRates
198         };
199         listenerPhaseOffset = {
200             .cb = appController,
201             .phaseByPulseNum = 9 // phase is 9 pulse
202         };
203         generatorRefreshRate = 30; // 30hz
204         vsyncGenerator->ChangeGeneratorRefreshRateModel(
205             listenerRefreshRates, listenerPhaseOffset, generatorRefreshRate, rsVsyncCount);
206         // checkout 30hz
207         read(pipeFd[0], &timeStamps, sizeof(timeStamps));
208         appTimestampPrev = timeStamps.appTimestamps[(timeStamps.appIndex - 2) % MAX_SIZE]; // prev should minus 2
209         appTimestampCur = timeStamps.appTimestamps[(timeStamps.appIndex - 1) % MAX_SIZE]; // cur should minus 1
210         rsTimestampPrev = timeStamps.rsTimestamps[(timeStamps.rsIndex - 2) % MAX_SIZE]; // prev should minus 2
211         rsTimestampCur = timeStamps.rsTimestamps[(timeStamps.rsIndex - 1) % MAX_SIZE]; // cur should minus 1
212         appPeriod = appTimestampCur - appTimestampPrev;
213         rsPeriod = rsTimestampCur - rsTimestampPrev;
214         appRefreshRate = JudgeRefreshRate(appPeriod);
215         rsRefreshRate = JudgeRefreshRate(rsPeriod);
216         EXPECT_EQ(appRefreshRate, 30); // 30hz
217         EXPECT_EQ(rsRefreshRate, 30); // 30hz
218         if (appRefreshRate != 30) { // 30hz
219             std::string appTimestamps = "appTimestamps:[";
220             for (int i = 0; i < 15; i++) { // check last 15 samples
221                 appTimestamps += std::to_string(g_timeStamps.appTimestamps[i]) + ",";
222             }
223             appTimestamps += "]";
224             std::cout << appTimestamps << std::endl;
225         }
226         if (rsRefreshRate != 30) { // 30hz
227             std::string rsTimestamps = "rsTimestamps:[";
228             for (int i = 0; i < 15; i++) { // check last 15 samples
229                 rsTimestamps += std::to_string(g_timeStamps.rsTimestamps[i]) + ",";
230             }
231             rsTimestamps += "]";
232             std::cout << rsTimestamps << std::endl;
233         }
234         std::cout << "appPeriod:" << appPeriod <<
235                 ", appRefreshRate:" << appRefreshRate <<
236                 ", rsPeriod:" << rsPeriod <<
237                 ", rsRefreshRate:" << rsRefreshRate << std::endl;
238 
239         // change refresh rate to 60hz
240         changeRefreshRate = 0;
241         read(pipeFd[0], &changeRefreshRate, sizeof(changeRefreshRate));
242         refreshRates = {{1, 60}}; // 60hz
243         listenerRefreshRates = {
244             .cb = appController,
245             .refreshRates = refreshRates
246         };
247         listenerPhaseOffset = {
248             .cb = appController,
249             .phaseByPulseNum = 3 // phase is 3 pulse
250         };
251         generatorRefreshRate = 60; // 60hz
252         int64_t systemTime = SystemTime();
253         vsyncGenerator->ChangeGeneratorRefreshRateModel(
254             listenerRefreshRates, listenerPhaseOffset, generatorRefreshRate,
255             rsVsyncCount, systemTime + 3000000); // 3000000==3ms
256         // checkout 60hz
257         read(pipeFd[0], &timeStamps, sizeof(timeStamps));
258         appTimestampPrev = timeStamps.appTimestamps[(timeStamps.appIndex - 2) % MAX_SIZE]; // prev should minus 2
259         appTimestampCur = timeStamps.appTimestamps[(timeStamps.appIndex - 1) % MAX_SIZE]; // cur should minus 1
260         rsTimestampPrev = timeStamps.rsTimestamps[(timeStamps.rsIndex - 2) % MAX_SIZE]; // prev should minus 2
261         rsTimestampCur = timeStamps.rsTimestamps[(timeStamps.rsIndex - 1) % MAX_SIZE]; // cur should minus 1
262         appPeriod = appTimestampCur - appTimestampPrev;
263         rsPeriod = rsTimestampCur - rsTimestampPrev;
264         appRefreshRate = JudgeRefreshRate(appPeriod);
265         rsRefreshRate = JudgeRefreshRate(rsPeriod);
266         EXPECT_EQ(appRefreshRate, 60); // 60hz
267         EXPECT_EQ(rsRefreshRate, 60); // 60hz
268         if (appRefreshRate != 60) { // 60hz
269             std::string appTimestamps = "appTimestamps:[";
270             for (int i = 0; i < 15; i++) { // check last 15 samples
271                 appTimestamps += std::to_string(g_timeStamps.appTimestamps[i]) + ",";
272             }
273             appTimestamps += "]";
274             std::cout << appTimestamps << std::endl;
275         }
276         if (rsRefreshRate != 60) { // 60hz
277             std::string rsTimestamps = "rsTimestamps:[";
278             for (int i = 0; i < 15; i++) { // check last 15 samples
279                 rsTimestamps += std::to_string(g_timeStamps.rsTimestamps[i]) + ",";
280             }
281             rsTimestamps += "]";
282             std::cout << rsTimestamps << std::endl;
283         }
284         std::cout << "appPeriod:" << appPeriod <<
285                 ", appRefreshRate:" << appRefreshRate <<
286                 ", rsPeriod:" << rsPeriod <<
287                 ", rsRefreshRate:" << rsRefreshRate << std::endl;
288     }
289 
290     read(pipeFd[0], buf, sizeof(buf));
291     sam->RemoveSystemAbility(ipcSystemAbilityIDApp);
292     sam->RemoveSystemAbility(ipcSystemAbilityIDRs);
293     close(pipeFd[0]);
294     close(pipe1Fd[1]);
295     exit(0);
296 #endif
297 }
298 
Process2()299 void VSync30To60Test::Process2()
300 {
301     close(pipeFd[0]);
302     close(pipe1Fd[1]);
303     char buf[10];
304     read(pipe1Fd[0], buf, sizeof(buf));
305     auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
306     auto robjApp = sam->GetSystemAbility(ipcSystemAbilityIDApp);
307     auto robjRs = sam->GetSystemAbility(ipcSystemAbilityIDRs);
308     std::cout << "(robjApp == nullptr):" << (robjApp == nullptr) << std::endl;
309     std::cout << "(robjRs == nullptr):" << (robjRs == nullptr) << std::endl;
310     auto connApp = iface_cast<IVSyncConnection>(robjApp);
311     auto connRs = iface_cast<IVSyncConnection>(robjRs);
312     receiverApp = new VSyncReceiver(connApp);
313     receiverRs = new VSyncReceiver(connRs);
314     receiverApp->Init();
315     receiverRs->Init();
316     VSyncReceiver::FrameCallback fcbApp = {
317         .userData_ = nullptr,
318         .callback_ = OnVSyncApp,
319     };
320     VSyncReceiver::FrameCallback fcbRs = {
321         .userData_ = nullptr,
322         .callback_ = OnVSyncRs,
323     };
324 
325     int testTimes = 3; // test 3 times
326     while (testTimes--) {
327         // change refresh rate to 30hz
328         int changeRefreshRate = 0;
329         write(pipeFd[1], &changeRefreshRate, sizeof(changeRefreshRate));
330         int appNum = 3; // RequestNextVSync 3 times
331         int rsNum = 4; // RequestNextVSync 4 times
332         while (appNum > 0 || rsNum > 0) {
333             if (appNum > 0) {
334                 receiverApp->RequestNextVSync(fcbApp);
335             }
336             if (rsNum > 0) {
337                 receiverRs->RequestNextVSync(fcbRs);
338             }
339             while (g_appVSyncFlag == 0 && g_rsVSyncFlag == 0) {
340                 usleep(100); // 100us
341             }
342             if (g_appVSyncFlag) {
343                 appNum--;
344                 g_appVSyncFlag = 0;
345             }
346             if (g_rsVSyncFlag) {
347                 rsNum--;
348                 g_rsVSyncFlag = 0;
349             }
350         }
351         write(pipeFd[1], &g_timeStamps, sizeof(g_timeStamps));
352 
353         // change refresh rate to 60hz
354         changeRefreshRate = 0;
355         write(pipeFd[1], &changeRefreshRate, sizeof(changeRefreshRate));
356         appNum = 3; // RequestNextVSync 3 times
357         rsNum = 3; // RequestNextVSync 4 times
358         while (appNum > 0 || rsNum > 0) {
359             if (appNum > 0) {
360                 receiverApp->RequestNextVSync(fcbApp);
361             }
362             if (rsNum > 0) {
363                 receiverRs->RequestNextVSync(fcbRs);
364             }
365             while (g_appVSyncFlag == 0 && g_rsVSyncFlag == 0) {
366                 usleep(100); // 100us
367             }
368             if (g_appVSyncFlag) {
369                 appNum--;
370                 g_appVSyncFlag = 0;
371             }
372             if (g_rsVSyncFlag) {
373                 rsNum--;
374                 g_rsVSyncFlag = 0;
375             }
376         }
377         write(pipeFd[1], &g_timeStamps, sizeof(g_timeStamps));
378     }
379 }
380 
381 HWTEST_F(VSync30To60Test, ChangeRefreshRateTest, Function | MediumTest | Level2)
382 {
383     if (pipe(pipeFd) < 0) {
384         exit(1);
385     }
386     if (pipe(pipe1Fd) < 0) {
387         exit(0);
388     }
389     pid = fork();
390     if (pid < 0) {
391         exit(1);
392     }
393     if (pid != 0) {
394         Process1();
395     } else {
396         Process2();
397     }
398 }
399 }
400