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 
InitNativeWindowAndBuffer(sptr<IRemoteObject> robj)106 int32_t NativeWindowBufferTest::InitNativeWindowAndBuffer(sptr<IRemoteObject> robj)
107 {
108     auto producer = iface_cast<IBufferProducer>(robj);
109     sptr<Surface> pSurface = Surface::CreateSurfaceAsProducer(producer);
110 
111     struct NativeWindow *nativeWindow = OH_NativeWindow_CreateNativeWindow(&pSurface);
112     struct NativeWindowBuffer *nativeWindowBuffer = nullptr;
113 
114     int code = SET_USAGE;
115     uint64_t usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
116     OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, usage);
117 
118     code = SET_BUFFER_GEOMETRY;
119     int32_t height = 0x100;
120     int32_t width = 0x100;
121     OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, height, width);
122 
123     code = SET_FORMAT;
124     int32_t format = GRAPHIC_PIXEL_FMT_RGBA_8888;
125     OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, format);
126 
127     code = SET_STRIDE;
128     int32_t stride = 0x8;
129     OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, stride);
130 
131     int32_t fenceFd = -1;
132     auto ret = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &nativeWindowBuffer, &fenceFd);
133     if (ret != OHOS::GSERROR_OK) {
134         return ret;
135     }
136     ret = SetData(nativeWindowBuffer, nativeWindow);
137     if (ret != OHOS::GSERROR_OK) {
138         return ret;
139     }
140 
141     struct Region *region = new Region();
142     struct Region::Rect *rect = new Region::Rect();
143     rect->w = 0x100;
144     rect->h = 0x100;
145     region->rects = rect;
146     region->rectNumber = 1;
147     ret = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, nativeWindowBuffer, -1, *region);
148     if (ret != OHOS::GSERROR_OK) {
149         delete rect;
150         delete region;
151         return ret;
152     }
153     delete rect;
154     delete region;
155     return OHOS::GSERROR_OK;
156 }
157 
ChildProcessMain()158 pid_t NativeWindowBufferTest::ChildProcessMain()
159 {
160     pipe(pipeFd);
161     pid_t pid = fork();
162     if (pid != 0) {
163         return pid;
164     }
165 
166     int64_t data;
167     read(pipeFd[0], &data, sizeof(data));
168 
169     sptr<IRemoteObject> robj = nullptr;
170     while (true) {
171         auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
172         robj = sam->GetSystemAbility(ipcSystemAbilityID);
173         if (robj != nullptr) {
174             break;
175         }
176         sleep(0);
177     }
178     int32_t ret = InitNativeWindowAndBuffer(robj);
179     if (ret != OHOS::GSERROR_OK) {
180         data = ret;
181         write(pipeFd[1], &data, sizeof(data));
182         exit(0);
183         return -1;
184     }
185 
186     data = ret;
187     write(pipeFd[1], &data, sizeof(data));
188     usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds)
189     read(pipeFd[0], &data, sizeof(data));
190     close(pipeFd[0]);
191     close(pipeFd[1]);
192     exit(0);
193     return 0;
194 }
195 
196 /*
197 * Function: produce and consumer surface of nativewindow
198 * Type: Function
199 * Rank: Important(2)
200 * EnvConditions: N/A
201 * CaseDescription: 1. produce surface by nativewindow interface, fill buffer
202 *                  2. consume surface and check buffer
203 * @tc.require: issueI5GMZN issueI5IWHW
204  */
HWTEST_F(NativeWindowBufferTest, Surface001, Function | MediumTest | Level2)205 HWTEST_F(NativeWindowBufferTest, Surface001, Function | MediumTest | Level2)
206 {
207     auto pid = ChildProcessMain();
208     ASSERT_GE(pid, 0);
209 
210     uint64_t tokenId;
211     const char *perms[2];
212     perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC";
213     perms[1] = "ohos.permission.CAMERA";
214     NativeTokenInfoParams infoInstance = {
215         .dcapsNum = 0,
216         .permsNum = 2,
217         .aclsNum = 0,
218         .dcaps = NULL,
219         .perms = perms,
220         .acls = NULL,
221         .processName = "dcamera_client_demo",
222         .aplStr = "system_basic",
223     };
224     tokenId = GetAccessTokenId(&infoInstance);
225     SetSelfTokenID(tokenId);
226     int32_t rett = Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
227     ASSERT_EQ(rett, Security::AccessToken::RET_SUCCESS);
228 
229     cSurface = IConsumerSurface::Create("test");
230     cSurface->RegisterConsumerListener(this);
231     auto producer = cSurface->GetProducer();
232     auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
233     sam->AddSystemAbility(ipcSystemAbilityID, producer->AsObject());
234 
235     int64_t data = 0;
236     write(pipeFd[1], &data, sizeof(data));
237     usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds)
238     read(pipeFd[0], &data, sizeof(data));
239     EXPECT_EQ(data, OHOS::GSERROR_OK);
240 
241     OHOS::sptr<SurfaceBuffer> buffer = nullptr;
242     int32_t fence = -1;
243     int64_t timestamp;
244     Rect damage;
245     auto ret = cSurface->AcquireBuffer(buffer, fence, timestamp, damage);
246     EXPECT_EQ(ret, OHOS::GSERROR_OK);
247     EXPECT_NE(buffer, nullptr);
248     EXPECT_EQ(GetData(buffer), true);
249 
250     ret = cSurface->ReleaseBuffer(buffer, -1);
251     EXPECT_EQ(ret, OHOS::GSERROR_OK);
252 
253     write(pipeFd[1], &data, sizeof(data));
254     close(pipeFd[0]);
255     close(pipeFd[1]);
256     sam->RemoveSystemAbility(ipcSystemAbilityID);
257     waitpid(pid, nullptr, 0);
258 }
259 }
260