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 <mutex>
17 #include <thread>
18 #include <unistd.h>
19 #include <vector>
20 #include <condition_variable>
21 #include <gtest/gtest.h>
22 #include <iservice_registry.h>
23 #include "vsync_receiver.h"
24 #include "vsync_controller.h"
25 #include "vsync_sampler.h"
26 #include "vsync_generator.h"
27 #include "vsync_distributor.h"
28 #include "accesstoken_kit.h"
29 #ifdef SUPPORT_ACCESS_TOKEN
30 #include "nativetoken_kit.h"
31 #include "token_setproc.h"
32 #endif
33
34 #include <iostream>
35
36 using namespace testing;
37 using namespace testing::ext;
38
39 namespace OHOS::Rosen {
40 namespace {
41 std::mutex g_mutex;
42 int g_counter = 0;
43 std::vector<int> datas;
44 constexpr int32_t SAMPLER_NUMBER = 6;
OnVSync(int64_t time,void * data)45 static void OnVSync(int64_t time, void *data)
46 {
47 std::unique_lock<std::mutex> locker(g_mutex);
48 if (!data) {
49 return;
50 }
51 vector<int>::iterator it = find(datas.begin(), datas.end(), *(int *)data);
52 if (it != datas.end()) {
53 datas.erase(it);
54 }
55 delete (int *)data;
56 }
57 }
58 class VSyncMultiCallbackTest : public testing::Test {
59 public:
60 void Process1();
61 void Process2();
62
63 sptr<VSyncSampler> vsyncSampler = nullptr;
64 sptr<VSyncGenerator> vsyncGenerator = nullptr;
65 sptr<VSyncController> vsyncController = nullptr;
66 sptr<VSyncDistributor> vsyncDistributor = nullptr;
67 sptr<VSyncConnection> vsyncConnection = nullptr;
68
69 static inline pid_t pid = 0;
70 static inline int pipeFd[2] = {};
71 static inline int pipe1Fd[2] = {};
72 static inline int32_t systemAbilityID = 345135;
73 };
74
InitNativeTokenInfo()75 static void InitNativeTokenInfo()
76 {
77 #ifdef SUPPORT_ACCESS_TOKEN
78 uint64_t tokenId;
79 const char *perms[2];
80 perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC";
81 perms[1] = "ohos.permission.CAMERA";
82 NativeTokenInfoParams infoInstance = {
83 .dcapsNum = 0,
84 .permsNum = 2,
85 .aclsNum = 0,
86 .dcaps = NULL,
87 .perms = perms,
88 .acls = NULL,
89 .processName = "dcamera_client_demo",
90 .aplStr = "system_basic",
91 };
92 tokenId = GetAccessTokenId(&infoInstance);
93 SetSelfTokenID(tokenId);
94 int32_t ret = Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
95 ASSERT_EQ(ret, Security::AccessToken::RET_SUCCESS);
96 std::this_thread::sleep_for(std::chrono::milliseconds(50)); // wait 50ms
97 #endif
98 }
99
Process1()100 void VSyncMultiCallbackTest::Process1()
101 {
102 #ifdef SUPPORT_ACCESS_TOKEN
103 InitNativeTokenInfo();
104 vsyncGenerator = CreateVSyncGenerator();
105 vsyncSampler = CreateVSyncSampler();
106 int32_t count = 0;
107 int64_t timestamp = 16666667; // 16666667ns
108 while (count <= SAMPLER_NUMBER) {
109 vsyncSampler->AddSample(timestamp);
110 usleep(1000); // 1000us
111 timestamp += 16666667; // 16666667ns
112 count++;
113 }
114 vsyncController = new VSyncController(vsyncGenerator, 0);
115 vsyncDistributor = new VSyncDistributor(vsyncController, "test");
116 vsyncConnection = new VSyncConnection(vsyncDistributor, "test");
117 vsyncDistributor->AddConnection(vsyncConnection);
118 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
119 sam->AddSystemAbility(systemAbilityID, vsyncConnection);
120 close(pipeFd[1]);
121 close(pipe1Fd[0]);
122 char buf[10] = "start";
123 write(pipe1Fd[1], buf, sizeof(buf));
124 read(pipeFd[0], buf, sizeof(buf));
125 sam->RemoveSystemAbility(systemAbilityID);
126 close(pipeFd[0]);
127 close(pipe1Fd[1]);
128 exit(0);
129 #endif
130 }
131
Process2()132 void VSyncMultiCallbackTest::Process2()
133 {
134 close(pipeFd[0]);
135 close(pipe1Fd[1]);
136 char buf[10];
137 read(pipe1Fd[0], buf, sizeof(buf));
138 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
139 auto robj = sam->GetSystemAbility(systemAbilityID);
140 std::cout << "(robj==nullptr):" << (robj==nullptr) << std::endl;
141 auto conn = iface_cast<IVSyncConnection>(robj);
142 sptr<VSyncReceiver> receiver = new VSyncReceiver(conn);
143 receiver->Init();
144 VSyncReceiver::FrameCallback fcb = {
145 .userData_ = nullptr,
146 .callback_ = OnVSync,
147 };
148 for (int i = 0; i < 10; i++) { // test 10 times
149 std::unique_lock<std::mutex> locker(g_mutex);
150 int *userData = new int(g_counter++);
151 fcb.userData_ = userData;
152 auto ret = receiver->RequestNextVSyncWithMultiCallback(fcb);
153 if (ret == VSYNC_ERROR_OK) {
154 datas.push_back(*userData);
155 }
156 usleep(1); // 1us
157 }
158 sleep(1);
159 EXPECT_EQ(datas.size(), 0);
160 int64_t period;
161 int64_t timeStamp;
162 EXPECT_EQ(receiver->GetVSyncPeriodAndLastTimeStamp(period, timeStamp), VSYNC_ERROR_OK);
163 }
164
165 /*
166 * Function: RequestNextVSyncWithMultiCallbackTest
167 * Type: Function
168 * Rank: Important(2)
169 * EnvConditions: N/A
170 * CaseDescription: RequestNextVSyncWithMultiCallbackTest
171 */
172 HWTEST_F(VSyncMultiCallbackTest, RequestNextVSyncWithMultiCallbackTest, Function | MediumTest | Level2)
173 {
174 if (pipe(pipeFd) < 0) {
175 exit(1);
176 }
177 if (pipe(pipe1Fd) < 0) {
178 exit(0);
179 }
180 pid = fork();
181 if (pid < 0) {
182 exit(1);
183 }
184 if (pid != 0) {
185 Process1();
186 } else {
187 Process2();
188 }
189 }
190 }
191