1 /*
2 * Copyright (c) 2025 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 <surface.h>
21 #include "accesstoken_kit.h"
22 #include "iconsumer_surface.h"
23 #include "nativetoken_kit.h"
24 #include "token_setproc.h"
25 #include "sync_fence.h"
26 #include "external_window.h"
27 #include "native_window.h"
28
29 using namespace testing;
30 using namespace testing::ext;
31
32 namespace OHOS::Rosen {
33 class NativeWindowCleanCacheTest : public testing::Test, public IBufferConsumerListenerClazz {
34 public:
35 static void SetUpTestCase();
36 void OnBufferAvailable() override;
37 OHOS::GSError SetData(sptr<SurfaceBuffer> &buffer, sptr<Surface> &pSurface);
38 bool GetData(sptr<SurfaceBuffer> &buffer);
39 pid_t ChildProcessMain();
40 sptr<OHOS::Surface> CreateSurface();
41
42 static inline sptr<IConsumerSurface> cSurface = nullptr;
43 static inline int32_t pipeMain[2] = {};
44 static inline int32_t pipeChild[2] = {};
45 static inline int32_t ipcSystemAbilityID = 34156;
46 static inline BufferRequestConfig requestConfig = {};
47 static inline BufferFlushConfig flushConfig = {};
48
49 static constexpr const int32_t WAIT_SYSTEM_ABILITY_GET_PRODUCER_TIMES = 1000;
50 };
51
SetUpTestCase()52 void NativeWindowCleanCacheTest::SetUpTestCase()
53 {
54 GTEST_LOG_(INFO) << getpid();
55 requestConfig = {
56 .width = 0x100, // small
57 .height = 0x100, // small
58 .strideAlignment = 0x8,
59 .format = GRAPHIC_PIXEL_FMT_RGBA_8888,
60 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
61 .timeout = 0,
62 };
63
64 flushConfig = {
65 .damage = {
66 .w = 0x100,
67 .h = 0x100,
68 }
69 };
70 }
71
OnBufferAvailable()72 void NativeWindowCleanCacheTest::OnBufferAvailable()
73 {
74 }
75
OnBufferRelease(sptr<SurfaceBuffer> & buffer)76 static inline GSError OnBufferRelease(sptr<SurfaceBuffer> &buffer)
77 {
78 return GSERROR_OK;
79 }
80
CreateSurface()81 sptr<OHOS::Surface> NativeWindowCleanCacheTest::CreateSurface()
82 {
83 sptr<IRemoteObject> robj = nullptr;
84 int i = 0;
85 while (i++ < WAIT_SYSTEM_ABILITY_GET_PRODUCER_TIMES) {
86 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
87 robj = sam->GetSystemAbility(ipcSystemAbilityID);
88 if (robj != nullptr) {
89 break;
90 }
91 usleep(1);
92 }
93
94 auto producer = iface_cast<IBufferProducer>(robj);
95 return Surface::CreateSurfaceAsProducer(producer);
96 }
97
ChildProcessMain()98 pid_t NativeWindowCleanCacheTest::ChildProcessMain()
99 {
100 pipe(pipeMain);
101 pipe(pipeChild);
102 pid_t pid = fork();
103 if (pid != 0) {
104 return pid;
105 }
106
107 int64_t data;
108 int64_t bufferNum;
109 read(pipeMain[0], &bufferNum, sizeof(bufferNum));
110
111 auto pSurface = CreateSurface();
112 auto nativeWindow = OH_NativeWindow_CreateNativeWindow(&pSurface);
113 int32_t code = SET_BUFFER_GEOMETRY;
114 int32_t height = 0x100;
115 int32_t weight = 0x100;
116 OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, height, weight);
117 code = SET_FORMAT;
118 int32_t format = GRAPHIC_PIXEL_FMT_RGBA_8888;
119 OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, format);
120 pSurface->RegisterReleaseListener(OnBufferRelease);
121
122 struct NativeWindowBuffer *nativeWindowBuffer = nullptr;
123 int32_t sRet;
124 int fenceFd = -1;
125 for (int i = 0; i < bufferNum; i++) {
126 sRet = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &nativeWindowBuffer, &fenceFd);
127 if (sRet != OHOS::GSERROR_OK) {
128 std::cout<<"OH_NativeWindow_NativeWindowRequestBuffer ret:"<<sRet<<std::endl;
129 data = sRet;
130 write(pipeChild[1], &data, sizeof(data));
131 exit(0);
132 }
133 struct Region *region = new Region();
134 struct Region::Rect *rect = new Region::Rect();
135 rect->w = 0x100;
136 rect->h = 0x100;
137 region->rects = rect;
138 region->rectNumber = 1;
139 sRet = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, nativeWindowBuffer, -1, *region);
140 if (sRet != OHOS::GSERROR_OK) {
141 std::cout<<"OH_NativeWindow_NativeWindowFlushBuffer ret:"<<sRet<<std::endl;
142 data = sRet;
143 write(pipeChild[1], &data, sizeof(data));
144 exit(0);
145 }
146 }
147 sRet = OH_NativeWindow_CleanCache(nativeWindow);
148
149 data = sRet;
150 write(pipeChild[1], &data, sizeof(data));
151 usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds)
152 read(pipeMain[0], &data, sizeof(data));
153 usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds)
154 pSurface->UnRegisterReleaseListener();
155 close(pipeMain[0]);
156 close(pipeMain[1]);
157 close(pipeChild[0]);
158 close(pipeChild[1]);
159 exit(0);
160 return 0;
161 }
162
163 /*
164 * Function: NativeWindowCleanCache
165 * Type: Function
166 * Rank: Important(2)
167 * EnvConditions: N/A
168 * CaseDescription: 1. preSetUp: native window flush 2 buffer
169 * 2. operation: native window clean cache success
170 * 3. result: consumer surface acquire buffer failed and no buffer in cache
171 */
172 HWTEST_F(NativeWindowCleanCacheTest, CleanCache001, TestSize.Level0)
173 {
174 //生产者生产buffer
175 auto pid = ChildProcessMain();
176 ASSERT_GE(pid, 0);
177
178 uint64_t tokenId;
179 const char *perms[2];
180 perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC";
181 perms[1] = "ohos.permission.CAMERA";
182 NativeTokenInfoParams infoInstance = {
183 .dcapsNum = 0,
184 .permsNum = 2,
185 .aclsNum = 0,
186 .dcaps = NULL,
187 .perms = perms,
188 .acls = NULL,
189 .processName = "dcamera_client_demo",
190 .aplStr = "system_basic",
191 };
192 tokenId = GetAccessTokenId(&infoInstance);
193 SetSelfTokenID(tokenId);
194 int32_t rett = Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
195 ASSERT_EQ(rett, Security::AccessToken::RET_SUCCESS);
196 cSurface = IConsumerSurface::Create("test");
197 cSurface->RegisterConsumerListener(this);
198 auto producer = cSurface->GetProducer();
199 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
200 sam->AddSystemAbility(ipcSystemAbilityID, producer->AsObject());
201
202 int64_t data = 2;
203 write(pipeMain[1], &data, sizeof(data));
204 usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds)
205 read(pipeChild[0], &data, sizeof(data));
206 EXPECT_EQ(data, OHOS::GSERROR_OK);
207
208 //消费者消费buffer
209 IConsumerSurface::AcquireBufferReturnValue returnValue = {
210 .buffer =nullptr,
211 .fence = new SyncFence(-1),
212 };
213 //Branch1 - No buffer after clean cache
214 auto sRet = cSurface->AcquireBuffer(returnValue, 0, false);
215 EXPECT_EQ(sRet, GSERROR_NO_BUFFER);
216
217
218 //close resource
219 write(pipeMain[1], &data, sizeof(data));
220 close(pipeMain[0]);
221 close(pipeMain[1]);
222 close(pipeChild[0]);
223 close(pipeChild[1]);
224 sam->RemoveSystemAbility(ipcSystemAbilityID);
225 int32_t ret = 0;
226 do {
227 waitpid(pid, nullptr, 0);
228 } while (ret == -1 && errno == EINTR);
229 }
230
231 /*
232 * Function: NativeWindowCleanCache
233 * Type: Function
234 * Rank: Important(2)
235 * EnvConditions: N/A
236 * CaseDescription: 1. preSetUp: native window has no connect to comsumer
237 * 2. operation: native window clean cache failed
238 * 3. result: failed and return error code GSERROR_CONSUMER_DISCONNECTED
239 */
240 HWTEST_F(NativeWindowCleanCacheTest, CleanCache002, TestSize.Level0)
241 {
242 auto cSurface = IConsumerSurface::Create("test");
243 cSurface->RegisterConsumerListener(this);
244 auto producer = cSurface->GetProducer();
245 auto pSurface = Surface::CreateSurfaceAsProducer(producer);
246 NativeWindow* nativeWindow = nullptr;
247 auto ret = OH_NativeWindow_CreateNativeWindowFromSurfaceId(pSurface->GetUniqueId(), &nativeWindow);
248 ret = OH_NativeWindow_CleanCache(nativeWindow);
249
250 ASSERT_EQ(ret, OHOS::GSERROR_CONSUMER_DISCONNECTED);
251 }
252 }
253