1 /*
2 * Copyright (c) 2021 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
30 #include <iostream>
31
32 using namespace testing;
33 using namespace testing::ext;
34
35 namespace OHOS::Rosen {
36 namespace {
37 int32_t appVSyncFlag = 0;
38 constexpr int32_t SOFT_VSYNC_PERIOD = 16;
39 constexpr int32_t SAMPLER_NUMBER = 6;
OnVSyncApp(int64_t time,void * data)40 static void OnVSyncApp(int64_t time, void *data)
41 {
42 std::cout << "OnVSyncApp in\n";
43 appVSyncFlag = 1;
44 }
45 }
46 class VSyncTest : public testing::Test {
47 public:
48 static void SetUpTestCase();
49 static void TearDownTestCase();
50 void SetUp();
51 void TearDown();
52 pid_t ChildProcessMain();
53 static void ThreadMain();
54
55 sptr<VSyncController> appController = nullptr;
56 sptr<VSyncController> rsController = nullptr;
57 sptr<VSyncDistributor> appDistributor = nullptr;
58 sptr<VSyncDistributor> rsDistributor = nullptr;
59 sptr<VSyncGenerator> vsyncGenerator = nullptr;
60 static inline sptr<VSyncSampler> vsyncSampler = nullptr;
61 std::thread samplerThread;
62
63 static inline int32_t pipeFd[2] = {};
64 static inline int32_t ipcSystemAbilityID = 34156;
65 };
66
SetUpTestCase()67 void VSyncTest::SetUpTestCase()
68 {
69 vsyncSampler = CreateVSyncSampler();
70 }
71
TearDownTestCase()72 void VSyncTest::TearDownTestCase()
73 {
74 vsyncSampler = nullptr;
75 }
76
SetUp()77 void VSyncTest::SetUp()
78 {
79 vsyncGenerator = CreateVSyncGenerator();
80 appController = new VSyncController(vsyncGenerator, 0);
81 rsController = new VSyncController(vsyncGenerator, 0);
82
83 appDistributor = new VSyncDistributor(appController, "appController");
84 rsDistributor = new VSyncDistributor(rsController, "rsController");
85
86 samplerThread = std::thread(std::bind(&VSyncTest::ThreadMain));
87 samplerThread.join();
88 }
89
TearDown()90 void VSyncTest::TearDown()
91 {
92 vsyncGenerator = nullptr;
93 appController = nullptr;
94 rsController = nullptr;
95 appDistributor = nullptr;
96 rsDistributor = nullptr;
97
98 if (samplerThread.joinable()) {
99 samplerThread.join();
100 }
101 }
102
ChildProcessMain()103 pid_t VSyncTest::ChildProcessMain()
104 {
105 std::cout << "ChildProcessMain in\n";
106 pipe(pipeFd);
107 pid_t pid = fork();
108 if (pid != 0) {
109 return pid;
110 }
111
112 sptr<IRemoteObject> robj = nullptr;
113 while (true) {
114 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
115 robj = sam->GetSystemAbility(ipcSystemAbilityID);
116 if (robj != nullptr) {
117 break;
118 }
119 sleep(0);
120 }
121
122 auto conn = iface_cast<IVSyncConnection>(robj);
123 sptr<VSyncReceiver> receiver = new VSyncReceiver(conn);
124 receiver->Init();
125
126 VSyncReceiver::FrameCallback fcb = {
127 .userData_ = nullptr,
128 .callback_ = OnVSyncApp,
129 };
130 std::cout << "RequestNextVSync\n";
131 receiver->RequestNextVSync(fcb);
132 while (appVSyncFlag == 0) {
133 sleep(1);
134 std::cout << "ChildProcessMain appVSyncFlag is " << appVSyncFlag << std::endl;
135 }
136 EXPECT_EQ(appVSyncFlag, 1);
137 int64_t period;
138 int64_t timeStamp;
139 EXPECT_EQ(receiver->GetVSyncPeriodAndLastTimeStamp(period, timeStamp), VSYNC_ERROR_OK);
140 std::cout << "period = " << period << ",timeStamp = " << timeStamp << std::endl;
141 write(pipeFd[1], &appVSyncFlag, sizeof(appVSyncFlag));
142 close(pipeFd[0]);
143 close(pipeFd[1]);
144 exit(0);
145 return 0;
146 }
147
ThreadMain()148 void VSyncTest::ThreadMain()
149 {
150 bool ret = true;
151 std::condition_variable con;
152 std::mutex mtx;
153 std::unique_lock<std::mutex> locker(mtx);
154 int32_t count = 0;
155 while (count <= SAMPLER_NUMBER) {
156 const auto &now = std::chrono::steady_clock::now().time_since_epoch();
157 int64_t timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
158 ret = vsyncSampler->AddSample(timestamp);
159 con.wait_for(locker, std::chrono::milliseconds(SOFT_VSYNC_PERIOD));
160 count++;
161 }
162 }
163
164 /*
165 * Function: RequestNextVSync001
166 * Type: Function
167 * Rank: Important(2)
168 * EnvConditions: N/A
169 * CaseDescription: 1. RequestNextVSync by IPC
170 */
171 HWTEST_F(VSyncTest, RequestNextVSync001, Function | MediumTest | Level2)
172 {
173 auto pid = ChildProcessMain();
174 ASSERT_GE(pid, 0);
175
176 uint64_t tokenId;
177 const char *perms[2];
178 perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC";
179 perms[1] = "ohos.permission.CAMERA";
180 NativeTokenInfoParams infoInstance = {
181 .dcapsNum = 0,
182 .permsNum = 2,
183 .aclsNum = 0,
184 .dcaps = NULL,
185 .perms = perms,
186 .acls = NULL,
187 .processName = "dcamera_client_demo",
188 .aplStr = "system_basic",
189 };
190 tokenId = GetAccessTokenId(&infoInstance);
191 SetSelfTokenID(tokenId);
192 int32_t ret = Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
193 ASSERT_EQ(ret, Security::AccessToken::RET_SUCCESS);
194
195 sptr<VSyncConnection> connServer = new VSyncConnection(appDistributor, "app");
196 appDistributor->AddConnection(connServer);
197 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
198 sam->AddSystemAbility(ipcSystemAbilityID, connServer->AsObject());
199 read(pipeFd[0], &appVSyncFlag, sizeof(appVSyncFlag));
200 while (appVSyncFlag == 0) {
201 std::cout << "RequestNextVSync001 appVSyncFlag is " << appVSyncFlag << std::endl;
202 }
203 close(pipeFd[0]);
204 close(pipeFd[1]);
205 sam->RemoveSystemAbility(ipcSystemAbilityID);
206 waitpid(pid, nullptr, 0);
207 }
208 }
209