• 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 <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