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 <gtest/gtest.h>
19 #include <iservice_registry.h>
20 #include <securec.h>
21 #include <native_window.h>
22 #include "accesstoken_kit.h"
23 #include "nativetoken_kit.h"
24 #include "token_setproc.h"
25 #include "external_window.h"
26 #include "iconsumer_surface.h"
27
28 using namespace testing;
29 using namespace testing::ext;
30
31 namespace OHOS::Rosen {
32 class NativeWindowBufferTest : public testing::Test, public IBufferConsumerListenerClazz {
33 public:
34 static void SetUpTestCase();
35 void OnBufferAvailable() override;
36 int32_t SetData(NativeWindowBuffer *nativeWindowBuffer, NativeWindow *nativeWindow);
37 bool GetData(sptr<SurfaceBuffer> &buffer);
38 pid_t ChildProcessMain();
39 int32_t InitNativeWindowAndBuffer(sptr<IRemoteObject> robj);
40
41 static inline sptr<OHOS::IConsumerSurface> cSurface = nullptr;
42 static inline int32_t pipeFd[2] = {};
43 static inline int32_t ipcSystemAbilityID = 34156;
44 };
45
SetUpTestCase()46 void NativeWindowBufferTest::SetUpTestCase() {}
47
OnBufferAvailable()48 void NativeWindowBufferTest::OnBufferAvailable() {}
49
SetData(NativeWindowBuffer * nativeWindowBuffer,NativeWindow * nativeWindow)50 int32_t NativeWindowBufferTest::SetData(NativeWindowBuffer *nativeWindowBuffer, NativeWindow *nativeWindow)
51 {
52 nativeWindowBuffer->sfbuffer->GetExtraData()->ExtraSet("123", 0x123);
53 nativeWindowBuffer->sfbuffer->GetExtraData()->ExtraSet("345", (int64_t)0x345);
54 nativeWindowBuffer->sfbuffer->GetExtraData()->ExtraSet("567", "567");
55
56 // alloc OHExtDataHandle
57 uint32_t reserveInts = 1;
58 size_t handleSize = sizeof(OHExtDataHandle) + (sizeof(int32_t) * reserveInts);
59 OHExtDataHandle *handle = static_cast<OHExtDataHandle *>(malloc(handleSize));
60 if (handle == nullptr) {
61 return -1;
62 }
63 int32_t ret = memset_s(handle, handleSize, 0, handleSize);
64 if (ret != EOK) {
65 free(handle);
66 return -1;
67 }
68 handle->fd = -1;
69 handle->reserveInts = reserveInts;
70 for (uint32_t i = 0; i < reserveInts; i++) {
71 handle->reserve[i] = 1;
72 }
73
74 ret = OH_NativeWindow_NativeWindowSetTunnelHandle(nativeWindow, handle);
75 // free OHExtDataHandle
76 if (handle->fd >= 0) {
77 close(handle->fd);
78 handle->fd = -1;
79 }
80 free(handle);
81 handle = nullptr;
82 return ret;
83 }
84
GetData(sptr<SurfaceBuffer> & buffer)85 bool NativeWindowBufferTest::GetData(sptr<SurfaceBuffer> &buffer)
86 {
87 int32_t int32;
88 int64_t int64;
89 std::string str;
90 buffer->GetExtraData()->ExtraGet("123", int32);
91 buffer->GetExtraData()->ExtraGet("345", int64);
92 buffer->GetExtraData()->ExtraGet("567", str);
93 if ((int32 != 0x123) || (int64 != 0x345) || (str != "567")) {
94 return false;
95 }
96
97 sptr<SurfaceTunnelHandle> handleGet = nullptr;
98 handleGet = cSurface->GetTunnelHandle();
99 if ((handleGet == nullptr) || (handleGet->GetHandle()->fd != -1) ||
100 (handleGet->GetHandle()->reserveInts != 1) || (handleGet->GetHandle()->reserve[0] != 1)) {
101 return false;
102 }
103 return true;
104 }
105
106 /*
107 * Function: produce and consumer surface of nativewindow
108 * Type: Function
109 * Rank: Important(2)
110 * EnvConditions: N/A
111 * CaseDescription: 1. produce surface by nativewindow interface, fill buffer
112 * 2. consume surface and check buffer
113 * @tc.require: issueI5GMZN issueI5IWHW
114 */
115 HWTEST_F(NativeWindowBufferTest, Surface001, Function | MediumTest | Level2)
116 {
117 auto pid = ChildProcessMain();
118 ASSERT_GE(pid, 0);
119
120 uint64_t tokenId;
121 const char *perms[2];
122 perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC";
123 perms[1] = "ohos.permission.CAMERA";
124 NativeTokenInfoParams infoInstance = {
125 .dcapsNum = 0,
126 .permsNum = 2,
127 .aclsNum = 0,
128 .dcaps = NULL,
129 .perms = perms,
130 .acls = NULL,
131 .processName = "dcamera_client_demo",
132 .aplStr = "system_basic",
133 };
134 tokenId = GetAccessTokenId(&infoInstance);
135 SetSelfTokenID(tokenId);
136 int32_t rett = Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
137 ASSERT_EQ(rett, Security::AccessToken::RET_SUCCESS);
138
139 cSurface = IConsumerSurface::Create("test");
140 cSurface->RegisterConsumerListener(this);
141 auto producer = cSurface->GetProducer();
142 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
143 sam->AddSystemAbility(ipcSystemAbilityID, producer->AsObject());
144
145 int64_t data = 0;
146 write(pipeFd[1], &data, sizeof(data));
147 usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds)
148 read(pipeFd[0], &data, sizeof(data));
149 EXPECT_EQ(data, OHOS::GSERROR_OK);
150
151 OHOS::sptr<SurfaceBuffer> buffer = nullptr;
152 int32_t fence = -1;
153 int64_t timestamp;
154 Rect damage;
155 auto ret = cSurface->AcquireBuffer(buffer, fence, timestamp, damage);
156 EXPECT_EQ(ret, OHOS::GSERROR_OK);
157 EXPECT_NE(buffer, nullptr);
158 EXPECT_EQ(GetData(buffer), true);
159
160 ret = cSurface->ReleaseBuffer(buffer, -1);
161 EXPECT_EQ(ret, OHOS::GSERROR_OK);
162
163 write(pipeFd[1], &data, sizeof(data));
164 close(pipeFd[0]);
165 close(pipeFd[1]);
166 sam->RemoveSystemAbility(ipcSystemAbilityID);
167 waitpid(pid, nullptr, 0);
168 }
169
ChildProcessMain()170 pid_t NativeWindowBufferTest::ChildProcessMain()
171 {
172 pipe(pipeFd);
173 pid_t pid = fork();
174 if (pid != 0) {
175 return pid;
176 }
177
178 int64_t data;
179 read(pipeFd[0], &data, sizeof(data));
180
181 sptr<IRemoteObject> robj = nullptr;
182 while (true) {
183 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
184 robj = sam->GetSystemAbility(ipcSystemAbilityID);
185 if (robj != nullptr) {
186 break;
187 }
188 sleep(0);
189 }
190 int32_t ret = InitNativeWindowAndBuffer(robj);
191 if (ret != OHOS::GSERROR_OK) {
192 data = ret;
193 write(pipeFd[1], &data, sizeof(data));
194 exit(0);
195 return -1;
196 }
197
198 data = ret;
199 write(pipeFd[1], &data, sizeof(data));
200 usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds)
201 read(pipeFd[0], &data, sizeof(data));
202 close(pipeFd[0]);
203 close(pipeFd[1]);
204 exit(0);
205 return 0;
206 }
207
InitNativeWindowAndBuffer(sptr<IRemoteObject> robj)208 int32_t NativeWindowBufferTest::InitNativeWindowAndBuffer(sptr<IRemoteObject> robj)
209 {
210 auto producer = iface_cast<IBufferProducer>(robj);
211 sptr<Surface> pSurface = Surface::CreateSurfaceAsProducer(producer);
212
213 struct NativeWindow *nativeWindow = OH_NativeWindow_CreateNativeWindow(&pSurface);
214 struct NativeWindowBuffer *nativeWindowBuffer = nullptr;
215
216 int code = SET_USAGE;
217 uint64_t usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
218 OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, usage);
219
220 code = SET_BUFFER_GEOMETRY;
221 int32_t height = 0x100;
222 int32_t width = 0x100;
223 OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, height, width);
224
225 code = SET_FORMAT;
226 int32_t format = GRAPHIC_PIXEL_FMT_RGBA_8888;
227 OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, format);
228
229 code = SET_STRIDE;
230 int32_t stride = 0x8;
231 OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, stride);
232
233 int32_t fenceFd = -1;
234 auto ret = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &nativeWindowBuffer, &fenceFd);
235 if (ret != OHOS::GSERROR_OK) {
236 return ret;
237 }
238 ret = SetData(nativeWindowBuffer, nativeWindow);
239 if (ret != OHOS::GSERROR_OK) {
240 return ret;
241 }
242
243 struct Region *region = new Region();
244 struct Region::Rect *rect = new Region::Rect();
245 rect->w = 0x100;
246 rect->h = 0x100;
247 region->rects = rect;
248 region->rectNumber = 1;
249 ret = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, nativeWindowBuffer, -1, *region);
250 if (ret != OHOS::GSERROR_OK) {
251 delete rect;
252 delete region;
253 return ret;
254 }
255 delete rect;
256 delete region;
257 return OHOS::GSERROR_OK;
258 }
259 }