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