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