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