• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <surface.h>
21 #include "accesstoken_kit.h"
22 #include "iconsumer_surface.h"
23 #include "nativetoken_kit.h"
24 #include "token_setproc.h"
25 
26 using namespace testing;
27 using namespace testing::ext;
28 
29 namespace OHOS::Rosen {
30 class SurfaceIPCTest : public testing::Test, public IBufferConsumerListenerClazz {
31 public:
32     static void SetUpTestCase();
33     void OnBufferAvailable() override;
34     OHOS::GSError SetData(sptr<SurfaceBuffer> &buffer, sptr<Surface> &pSurface);
35     bool GetData(sptr<SurfaceBuffer> &buffer);
36     pid_t ChildProcessMain();
37     sptr<OHOS::Surface> CreateSurface();
38 
39     static inline sptr<IConsumerSurface> cSurface = nullptr;
40     static inline int32_t pipeMain[2] = {};
41     static inline int32_t pipeChild[2] = {};
42     static inline int32_t ipcSystemAbilityID = 34156;
43     static inline BufferRequestConfig requestConfig = {};
44     static inline BufferFlushConfig flushConfig = {};
45 };
46 
SetUpTestCase()47 void SurfaceIPCTest::SetUpTestCase()
48 {
49     GTEST_LOG_(INFO) << getpid();
50     requestConfig = {
51         .width = 0x100,  // small
52         .height = 0x100, // small
53         .strideAlignment = 0x8,
54         .format = GRAPHIC_PIXEL_FMT_RGBA_8888,
55         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
56         .timeout = 0,
57     };
58     flushConfig = { .damage = {
59         .w = 0x100,
60         .h = 0x100,
61     } };
62 }
63 
OnBufferAvailable()64 void SurfaceIPCTest::OnBufferAvailable()
65 {
66 }
67 
OnBufferRelease(sptr<SurfaceBuffer> & buffer)68 static inline GSError OnBufferRelease(sptr<SurfaceBuffer> &buffer)
69 {
70     return GSERROR_OK;
71 }
72 
SetData(sptr<SurfaceBuffer> & buffer,sptr<Surface> & pSurface)73 OHOS::GSError SurfaceIPCTest::SetData(sptr<SurfaceBuffer> &buffer, sptr<Surface> &pSurface)
74 {
75     buffer->GetExtraData()->ExtraSet("123", 0x123);
76     buffer->GetExtraData()->ExtraSet("345", (int64_t)0x345);
77     buffer->GetExtraData()->ExtraSet("567", "567");
78 
79     uint32_t reserveInts = 1;
80     GraphicExtDataHandle *handle = AllocExtDataHandle(reserveInts);
81     handle->reserve[0] = 1;
82     OHOS::GSError ret = pSurface->SetTunnelHandle(handle);
83     FreeExtDataHandle(handle);
84     handle = nullptr;
85     return ret;
86 }
87 
GetData(sptr<SurfaceBuffer> & buffer)88 bool SurfaceIPCTest::GetData(sptr<SurfaceBuffer> &buffer)
89 {
90     int32_t int32;
91     int64_t int64;
92     std::string str;
93     buffer->GetExtraData()->ExtraGet("123", int32);
94     buffer->GetExtraData()->ExtraGet("345", int64);
95     buffer->GetExtraData()->ExtraGet("567", str);
96     if ((int32 != 0x123) || (int64 != 0x345) || (str != "567")) {
97         return false;
98     }
99 
100     sptr<SurfaceTunnelHandle> handleGet = nullptr;
101     handleGet = cSurface->GetTunnelHandle();
102     if ((handleGet == nullptr) || (handleGet->GetHandle()->fd != -1) ||
103         (handleGet->GetHandle()->reserveInts != 1) || (handleGet->GetHandle()->reserve[0] != 1)) {
104             return false;
105     }
106 
107     GraphicPresentTimestamp timestamp = {GRAPHIC_DISPLAY_PTS_DELAY, 1};  // mock data for test
108     auto sRet = cSurface->SetPresentTimestamp(buffer->GetSeqNum(), timestamp);
109     return (sRet == OHOS::GSERROR_OK);
110 }
111 
CreateSurface()112 sptr<OHOS::Surface> SurfaceIPCTest::CreateSurface()
113 {
114     sptr<IRemoteObject> robj = nullptr;
115     while (true) {
116         auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
117         robj = sam->GetSystemAbility(ipcSystemAbilityID);
118         if (robj != nullptr) {
119             break;
120         }
121         sleep(0);
122     }
123 
124     auto producer = iface_cast<IBufferProducer>(robj);
125     return Surface::CreateSurfaceAsProducer(producer);
126 }
127 
ChildProcessMain()128 pid_t SurfaceIPCTest::ChildProcessMain()
129 {
130     pipe(pipeMain);
131     pipe(pipeChild);
132     pid_t pid = fork();
133     if (pid != 0) {
134         return pid;
135     }
136 
137     int64_t data;
138     read(pipeMain[0], &data, sizeof(data));
139 
140     auto pSurface = CreateSurface();
141     pSurface->RegisterReleaseListener(OnBufferRelease);
142     sptr<SurfaceBuffer> buffer = nullptr;
143     int releaseFence = -1;
144     auto sRet = pSurface->RequestBuffer(buffer, releaseFence, requestConfig);
145     if (sRet != OHOS::GSERROR_OK) {
146         data = sRet;
147         write(pipeChild[1], &data, sizeof(data));
148         exit(0);
149     }
150     sRet = SetData(buffer, pSurface);
151     if (sRet != OHOS::GSERROR_OK) {
152         data = sRet;
153         write(pipeChild[1], &data, sizeof(data));
154         exit(0);
155     }
156 
157     sRet = pSurface->FlushBuffer(buffer, -1, flushConfig);
158     data = sRet;
159     write(pipeChild[1], &data, sizeof(data));
160     usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds)
161     read(pipeMain[0], &data, sizeof(data));
162     usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds)
163     GraphicPresentTimestampType type = GraphicPresentTimestampType::GRAPHIC_DISPLAY_PTS_DELAY;
164     int64_t time = 0;
165     sRet = pSurface->GetPresentTimestamp(buffer->GetSeqNum(), type, time);
166     if (sRet != OHOS::GSERROR_OK || time != 1) {
167         data = sRet;
168         write(pipeChild[1], &data, sizeof(data));
169         exit(0);
170     }
171     pSurface->UnRegisterReleaseListener();
172     close(pipeMain[0]);
173     close(pipeMain[1]);
174     close(pipeChild[0]);
175     close(pipeChild[1]);
176     exit(0);
177     return 0;
178 }
179 
180 /*
181 * Function: produce and consumer surface by IPC
182 * Type: Function
183 * Rank: Important(2)
184 * EnvConditions: N/A
185 * CaseDescription: 1. produce surface, fill buffer
186 *                  2. consume surface and check buffer
187 *                  3. call RequestBuffer in this process, check sRet and buffer
188 * @tc.require: issueI5I57K issueI5GMZN issueI5IWHW
189  */
190 HWTEST_F(SurfaceIPCTest, BufferIPC001, TestSize.Level0)
191 {
192     auto pid = ChildProcessMain();
193     ASSERT_GE(pid, 0);
194 
195     uint64_t tokenId;
196     const char *perms[2];
197     perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC";
198     perms[1] = "ohos.permission.CAMERA";
199     NativeTokenInfoParams infoInstance = {
200         .dcapsNum = 0,
201         .permsNum = 2,
202         .aclsNum = 0,
203         .dcaps = NULL,
204         .perms = perms,
205         .acls = NULL,
206         .processName = "dcamera_client_demo",
207         .aplStr = "system_basic",
208     };
209     tokenId = GetAccessTokenId(&infoInstance);
210     SetSelfTokenID(tokenId);
211     int32_t rett = Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
212     ASSERT_EQ(rett, Security::AccessToken::RET_SUCCESS);
213     cSurface = IConsumerSurface::Create("test");
214     cSurface->RegisterConsumerListener(this);
215     auto producer = cSurface->GetProducer();
216     auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
217     sam->AddSystemAbility(ipcSystemAbilityID, producer->AsObject());
218 
219     int64_t data = 0;
220     write(pipeMain[1], &data, sizeof(data));
221     usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds)
222     read(pipeChild[0], &data, sizeof(data));
223     EXPECT_EQ(data, OHOS::GSERROR_OK);
224 
225     sptr<SurfaceBuffer> buffer = nullptr;
226     int32_t fence = -1;
227     int64_t timestamp;
228     Rect damage;
229     auto sRet = cSurface->AcquireBuffer(buffer, fence, timestamp, damage);
230     EXPECT_EQ(sRet, OHOS::GSERROR_OK);
231     EXPECT_NE(buffer, nullptr);
232     EXPECT_EQ(GetData(buffer), true);
233 
234     sRet = cSurface->ReleaseBuffer(buffer, -1);
235     EXPECT_EQ(sRet, OHOS::GSERROR_OK);
236 
237     // RequestBuffer cannot be called in two processes
238     auto pSurfaceSecond = Surface::CreateSurfaceAsProducer(producer);
239     sptr<SurfaceBuffer> bufferSecond = nullptr;
240     int releaseFence = -1;
241     sRet = pSurfaceSecond->RequestBuffer(bufferSecond, releaseFence, requestConfig);
242     ASSERT_EQ(sRet, GSERROR_CONSUMER_IS_CONNECTED);
243     ASSERT_EQ(bufferSecond, nullptr);
244 
245     //close resource
246     write(pipeMain[1], &data, sizeof(data));
247     close(pipeMain[0]);
248     close(pipeMain[1]);
249     close(pipeChild[0]);
250     close(pipeChild[1]);
251     sam->RemoveSystemAbility(ipcSystemAbilityID);
252     int32_t ret = 0;
253     do {
254         waitpid(pid, nullptr, 0);
255     } while (ret == -1 && errno == EINTR);
256 }
257 
258 /*
259 * Function: disconnect
260 * Type: Function
261 * Rank: Important(1)
262 * EnvConditions: N/A
263 * CaseDescription: 1. call Disconnect in other process, check sRet
264  */
265 HWTEST_F(SurfaceIPCTest, Disconnect001, TestSize.Level0)
266 {
267     cSurface->RegisterConsumerListener(this);
268     auto producer = cSurface->GetProducer();
269     auto pSurface = Surface::CreateSurfaceAsProducer(producer);
270     auto sRet = pSurface->Disconnect();
271     ASSERT_EQ(sRet, GSERROR_CONSUMER_DISCONNECTED);  // Disconnect cannot be called in two processes
272 }
273 }