132a6e48fSopenharmony_ci/* 232a6e48fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 332a6e48fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 432a6e48fSopenharmony_ci * you may not use this file except in compliance with the License. 532a6e48fSopenharmony_ci * You may obtain a copy of the License at 632a6e48fSopenharmony_ci * 732a6e48fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 832a6e48fSopenharmony_ci * 932a6e48fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1032a6e48fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1132a6e48fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1232a6e48fSopenharmony_ci * See the License for the specific language governing permissions and 1332a6e48fSopenharmony_ci * limitations under the License. 1432a6e48fSopenharmony_ci */ 1532a6e48fSopenharmony_ci#include <chrono> 1632a6e48fSopenharmony_ci#include <thread> 1732a6e48fSopenharmony_ci#include <unistd.h> 1832a6e48fSopenharmony_ci#include <gtest/gtest.h> 1932a6e48fSopenharmony_ci#include <iservice_registry.h> 2032a6e48fSopenharmony_ci#include <surface.h> 2132a6e48fSopenharmony_ci#include "accesstoken_kit.h" 2232a6e48fSopenharmony_ci#include "iconsumer_surface.h" 2332a6e48fSopenharmony_ci#include "nativetoken_kit.h" 2432a6e48fSopenharmony_ci#include "token_setproc.h" 2532a6e48fSopenharmony_ci 2632a6e48fSopenharmony_ciusing namespace testing; 2732a6e48fSopenharmony_ciusing namespace testing::ext; 2832a6e48fSopenharmony_ci 2932a6e48fSopenharmony_cinamespace OHOS::Rosen { 3032a6e48fSopenharmony_ciclass SurfaceIPCTest : public testing::Test, public IBufferConsumerListenerClazz { 3132a6e48fSopenharmony_cipublic: 3232a6e48fSopenharmony_ci static void SetUpTestCase(); 3332a6e48fSopenharmony_ci void OnBufferAvailable() override; 3432a6e48fSopenharmony_ci OHOS::GSError SetData(sptr<SurfaceBuffer> &buffer, sptr<Surface> &pSurface); 3532a6e48fSopenharmony_ci bool GetData(sptr<SurfaceBuffer> &buffer); 3632a6e48fSopenharmony_ci pid_t ChildProcessMain(); 3732a6e48fSopenharmony_ci sptr<OHOS::Surface> CreateSurface(); 3832a6e48fSopenharmony_ci 3932a6e48fSopenharmony_ci static inline sptr<IConsumerSurface> cSurface = nullptr; 4032a6e48fSopenharmony_ci static inline int32_t pipeFd[2] = {}; 4132a6e48fSopenharmony_ci static inline int32_t ipcSystemAbilityID = 34156; 4232a6e48fSopenharmony_ci static inline BufferRequestConfig requestConfig = {}; 4332a6e48fSopenharmony_ci static inline BufferFlushConfig flushConfig = {}; 4432a6e48fSopenharmony_ci}; 4532a6e48fSopenharmony_ci 4632a6e48fSopenharmony_civoid SurfaceIPCTest::SetUpTestCase() 4732a6e48fSopenharmony_ci{ 4832a6e48fSopenharmony_ci GTEST_LOG_(INFO) << getpid(); 4932a6e48fSopenharmony_ci requestConfig = { 5032a6e48fSopenharmony_ci .width = 0x100, // small 5132a6e48fSopenharmony_ci .height = 0x100, // small 5232a6e48fSopenharmony_ci .strideAlignment = 0x8, 5332a6e48fSopenharmony_ci .format = GRAPHIC_PIXEL_FMT_RGBA_8888, 5432a6e48fSopenharmony_ci .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA, 5532a6e48fSopenharmony_ci .timeout = 0, 5632a6e48fSopenharmony_ci }; 5732a6e48fSopenharmony_ci flushConfig = { .damage = { 5832a6e48fSopenharmony_ci .w = 0x100, 5932a6e48fSopenharmony_ci .h = 0x100, 6032a6e48fSopenharmony_ci } }; 6132a6e48fSopenharmony_ci} 6232a6e48fSopenharmony_ci 6332a6e48fSopenharmony_civoid SurfaceIPCTest::OnBufferAvailable() 6432a6e48fSopenharmony_ci{ 6532a6e48fSopenharmony_ci} 6632a6e48fSopenharmony_ci 6732a6e48fSopenharmony_cistatic inline GSError OnBufferRelease(sptr<SurfaceBuffer> &buffer) 6832a6e48fSopenharmony_ci{ 6932a6e48fSopenharmony_ci return GSERROR_OK; 7032a6e48fSopenharmony_ci} 7132a6e48fSopenharmony_ci 7232a6e48fSopenharmony_ciOHOS::GSError SurfaceIPCTest::SetData(sptr<SurfaceBuffer> &buffer, sptr<Surface> &pSurface) 7332a6e48fSopenharmony_ci{ 7432a6e48fSopenharmony_ci buffer->GetExtraData()->ExtraSet("123", 0x123); 7532a6e48fSopenharmony_ci buffer->GetExtraData()->ExtraSet("345", (int64_t)0x345); 7632a6e48fSopenharmony_ci buffer->GetExtraData()->ExtraSet("567", "567"); 7732a6e48fSopenharmony_ci 7832a6e48fSopenharmony_ci uint32_t reserveInts = 1; 7932a6e48fSopenharmony_ci GraphicExtDataHandle *handle = AllocExtDataHandle(reserveInts); 8032a6e48fSopenharmony_ci handle->reserve[0] = 1; 8132a6e48fSopenharmony_ci OHOS::GSError ret = pSurface->SetTunnelHandle(handle); 8232a6e48fSopenharmony_ci FreeExtDataHandle(handle); 8332a6e48fSopenharmony_ci handle = nullptr; 8432a6e48fSopenharmony_ci return ret; 8532a6e48fSopenharmony_ci} 8632a6e48fSopenharmony_ci 8732a6e48fSopenharmony_cibool SurfaceIPCTest::GetData(sptr<SurfaceBuffer> &buffer) 8832a6e48fSopenharmony_ci{ 8932a6e48fSopenharmony_ci int32_t int32; 9032a6e48fSopenharmony_ci int64_t int64; 9132a6e48fSopenharmony_ci std::string str; 9232a6e48fSopenharmony_ci buffer->GetExtraData()->ExtraGet("123", int32); 9332a6e48fSopenharmony_ci buffer->GetExtraData()->ExtraGet("345", int64); 9432a6e48fSopenharmony_ci buffer->GetExtraData()->ExtraGet("567", str); 9532a6e48fSopenharmony_ci if ((int32 != 0x123) || (int64 != 0x345) || (str != "567")) { 9632a6e48fSopenharmony_ci return false; 9732a6e48fSopenharmony_ci } 9832a6e48fSopenharmony_ci 9932a6e48fSopenharmony_ci sptr<SurfaceTunnelHandle> handleGet = nullptr; 10032a6e48fSopenharmony_ci handleGet = cSurface->GetTunnelHandle(); 10132a6e48fSopenharmony_ci if ((handleGet == nullptr) || (handleGet->GetHandle()->fd != -1) || 10232a6e48fSopenharmony_ci (handleGet->GetHandle()->reserveInts != 1) || (handleGet->GetHandle()->reserve[0] != 1)) { 10332a6e48fSopenharmony_ci return false; 10432a6e48fSopenharmony_ci } 10532a6e48fSopenharmony_ci 10632a6e48fSopenharmony_ci GraphicPresentTimestamp timestamp = {GRAPHIC_DISPLAY_PTS_DELAY, 1}; // mock data for test 10732a6e48fSopenharmony_ci auto sRet = cSurface->SetPresentTimestamp(buffer->GetSeqNum(), timestamp); 10832a6e48fSopenharmony_ci return (sRet == OHOS::GSERROR_OK); 10932a6e48fSopenharmony_ci} 11032a6e48fSopenharmony_ci 11132a6e48fSopenharmony_cisptr<OHOS::Surface> SurfaceIPCTest::CreateSurface() 11232a6e48fSopenharmony_ci{ 11332a6e48fSopenharmony_ci sptr<IRemoteObject> robj = nullptr; 11432a6e48fSopenharmony_ci while (true) { 11532a6e48fSopenharmony_ci auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 11632a6e48fSopenharmony_ci robj = sam->GetSystemAbility(ipcSystemAbilityID); 11732a6e48fSopenharmony_ci if (robj != nullptr) { 11832a6e48fSopenharmony_ci break; 11932a6e48fSopenharmony_ci } 12032a6e48fSopenharmony_ci sleep(0); 12132a6e48fSopenharmony_ci } 12232a6e48fSopenharmony_ci 12332a6e48fSopenharmony_ci auto producer = iface_cast<IBufferProducer>(robj); 12432a6e48fSopenharmony_ci return Surface::CreateSurfaceAsProducer(producer); 12532a6e48fSopenharmony_ci} 12632a6e48fSopenharmony_ci 12732a6e48fSopenharmony_cipid_t SurfaceIPCTest::ChildProcessMain() 12832a6e48fSopenharmony_ci{ 12932a6e48fSopenharmony_ci pipe(pipeFd); 13032a6e48fSopenharmony_ci pid_t pid = fork(); 13132a6e48fSopenharmony_ci if (pid != 0) { 13232a6e48fSopenharmony_ci return pid; 13332a6e48fSopenharmony_ci } 13432a6e48fSopenharmony_ci 13532a6e48fSopenharmony_ci int64_t data; 13632a6e48fSopenharmony_ci read(pipeFd[0], &data, sizeof(data)); 13732a6e48fSopenharmony_ci 13832a6e48fSopenharmony_ci auto pSurface = CreateSurface(); 13932a6e48fSopenharmony_ci pSurface->RegisterReleaseListener(OnBufferRelease); 14032a6e48fSopenharmony_ci sptr<SurfaceBuffer> buffer = nullptr; 14132a6e48fSopenharmony_ci int releaseFence = -1; 14232a6e48fSopenharmony_ci auto sRet = pSurface->RequestBuffer(buffer, releaseFence, requestConfig); 14332a6e48fSopenharmony_ci if (sRet != OHOS::GSERROR_OK) { 14432a6e48fSopenharmony_ci data = sRet; 14532a6e48fSopenharmony_ci write(pipeFd[1], &data, sizeof(data)); 14632a6e48fSopenharmony_ci exit(0); 14732a6e48fSopenharmony_ci } 14832a6e48fSopenharmony_ci sRet = SetData(buffer, pSurface); 14932a6e48fSopenharmony_ci if (sRet != OHOS::GSERROR_OK) { 15032a6e48fSopenharmony_ci data = sRet; 15132a6e48fSopenharmony_ci write(pipeFd[1], &data, sizeof(data)); 15232a6e48fSopenharmony_ci exit(0); 15332a6e48fSopenharmony_ci } 15432a6e48fSopenharmony_ci 15532a6e48fSopenharmony_ci sRet = pSurface->FlushBuffer(buffer, -1, flushConfig); 15632a6e48fSopenharmony_ci data = sRet; 15732a6e48fSopenharmony_ci write(pipeFd[1], &data, sizeof(data)); 15832a6e48fSopenharmony_ci usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds) 15932a6e48fSopenharmony_ci read(pipeFd[0], &data, sizeof(data)); 16032a6e48fSopenharmony_ci usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds) 16132a6e48fSopenharmony_ci GraphicPresentTimestampType type = GraphicPresentTimestampType::GRAPHIC_DISPLAY_PTS_DELAY; 16232a6e48fSopenharmony_ci int64_t time = 0; 16332a6e48fSopenharmony_ci sRet = pSurface->GetPresentTimestamp(buffer->GetSeqNum(), type, time); 16432a6e48fSopenharmony_ci if (sRet != OHOS::GSERROR_OK || time != 1) { 16532a6e48fSopenharmony_ci data = sRet; 16632a6e48fSopenharmony_ci write(pipeFd[1], &data, sizeof(data)); 16732a6e48fSopenharmony_ci exit(0); 16832a6e48fSopenharmony_ci } 16932a6e48fSopenharmony_ci pSurface->UnRegisterReleaseListener(); 17032a6e48fSopenharmony_ci close(pipeFd[0]); 17132a6e48fSopenharmony_ci close(pipeFd[1]); 17232a6e48fSopenharmony_ci exit(0); 17332a6e48fSopenharmony_ci return 0; 17432a6e48fSopenharmony_ci} 17532a6e48fSopenharmony_ci 17632a6e48fSopenharmony_ci/* 17732a6e48fSopenharmony_ci* Function: produce and consumer surface by IPC 17832a6e48fSopenharmony_ci* Type: Function 17932a6e48fSopenharmony_ci* Rank: Important(2) 18032a6e48fSopenharmony_ci* EnvConditions: N/A 18132a6e48fSopenharmony_ci* CaseDescription: 1. produce surface, fill buffer 18232a6e48fSopenharmony_ci* 2. consume surface and check buffer 18332a6e48fSopenharmony_ci* 3. call RequestBuffer in this process, check sRet and buffer 18432a6e48fSopenharmony_ci* @tc.require: issueI5I57K issueI5GMZN issueI5IWHW 18532a6e48fSopenharmony_ci */ 18632a6e48fSopenharmony_ciHWTEST_F(SurfaceIPCTest, BufferIPC001, Function | MediumTest | Level2) 18732a6e48fSopenharmony_ci{ 18832a6e48fSopenharmony_ci auto pid = ChildProcessMain(); 18932a6e48fSopenharmony_ci ASSERT_GE(pid, 0); 19032a6e48fSopenharmony_ci 19132a6e48fSopenharmony_ci uint64_t tokenId; 19232a6e48fSopenharmony_ci const char *perms[2]; 19332a6e48fSopenharmony_ci perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC"; 19432a6e48fSopenharmony_ci perms[1] = "ohos.permission.CAMERA"; 19532a6e48fSopenharmony_ci NativeTokenInfoParams infoInstance = { 19632a6e48fSopenharmony_ci .dcapsNum = 0, 19732a6e48fSopenharmony_ci .permsNum = 2, 19832a6e48fSopenharmony_ci .aclsNum = 0, 19932a6e48fSopenharmony_ci .dcaps = NULL, 20032a6e48fSopenharmony_ci .perms = perms, 20132a6e48fSopenharmony_ci .acls = NULL, 20232a6e48fSopenharmony_ci .processName = "dcamera_client_demo", 20332a6e48fSopenharmony_ci .aplStr = "system_basic", 20432a6e48fSopenharmony_ci }; 20532a6e48fSopenharmony_ci tokenId = GetAccessTokenId(&infoInstance); 20632a6e48fSopenharmony_ci SetSelfTokenID(tokenId); 20732a6e48fSopenharmony_ci int32_t rett = Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo(); 20832a6e48fSopenharmony_ci ASSERT_EQ(rett, Security::AccessToken::RET_SUCCESS); 20932a6e48fSopenharmony_ci cSurface = IConsumerSurface::Create("test"); 21032a6e48fSopenharmony_ci cSurface->RegisterConsumerListener(this); 21132a6e48fSopenharmony_ci auto producer = cSurface->GetProducer(); 21232a6e48fSopenharmony_ci auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 21332a6e48fSopenharmony_ci sam->AddSystemAbility(ipcSystemAbilityID, producer->AsObject()); 21432a6e48fSopenharmony_ci 21532a6e48fSopenharmony_ci int64_t data = 0; 21632a6e48fSopenharmony_ci write(pipeFd[1], &data, sizeof(data)); 21732a6e48fSopenharmony_ci usleep(1000); // sleep 1000 microseconds (equals 1 milliseconds) 21832a6e48fSopenharmony_ci read(pipeFd[0], &data, sizeof(data)); 21932a6e48fSopenharmony_ci EXPECT_EQ(data, OHOS::GSERROR_OK); 22032a6e48fSopenharmony_ci 22132a6e48fSopenharmony_ci sptr<SurfaceBuffer> buffer = nullptr; 22232a6e48fSopenharmony_ci int32_t fence = -1; 22332a6e48fSopenharmony_ci int64_t timestamp; 22432a6e48fSopenharmony_ci Rect damage; 22532a6e48fSopenharmony_ci auto sRet = cSurface->AcquireBuffer(buffer, fence, timestamp, damage); 22632a6e48fSopenharmony_ci EXPECT_EQ(sRet, OHOS::GSERROR_OK); 22732a6e48fSopenharmony_ci EXPECT_NE(buffer, nullptr); 22832a6e48fSopenharmony_ci EXPECT_EQ(GetData(buffer), true); 22932a6e48fSopenharmony_ci 23032a6e48fSopenharmony_ci sRet = cSurface->ReleaseBuffer(buffer, -1); 23132a6e48fSopenharmony_ci EXPECT_EQ(sRet, OHOS::GSERROR_OK); 23232a6e48fSopenharmony_ci 23332a6e48fSopenharmony_ci // RequestBuffer cannot be called in two processes 23432a6e48fSopenharmony_ci auto pSurfaceSecond = Surface::CreateSurfaceAsProducer(producer); 23532a6e48fSopenharmony_ci sptr<SurfaceBuffer> bufferSecond = nullptr; 23632a6e48fSopenharmony_ci int releaseFence = -1; 23732a6e48fSopenharmony_ci sRet = pSurfaceSecond->RequestBuffer(bufferSecond, releaseFence, requestConfig); 23832a6e48fSopenharmony_ci ASSERT_EQ(sRet, GSERROR_CONSUMER_IS_CONNECTED); 23932a6e48fSopenharmony_ci ASSERT_EQ(bufferSecond, nullptr); 24032a6e48fSopenharmony_ci 24132a6e48fSopenharmony_ci //close resource 24232a6e48fSopenharmony_ci write(pipeFd[1], &data, sizeof(data)); 24332a6e48fSopenharmony_ci close(pipeFd[0]); 24432a6e48fSopenharmony_ci close(pipeFd[1]); 24532a6e48fSopenharmony_ci sam->RemoveSystemAbility(ipcSystemAbilityID); 24632a6e48fSopenharmony_ci int32_t ret = 0; 24732a6e48fSopenharmony_ci do { 24832a6e48fSopenharmony_ci waitpid(pid, nullptr, 0); 24932a6e48fSopenharmony_ci } while (ret == -1 && errno == EINTR); 25032a6e48fSopenharmony_ci} 25132a6e48fSopenharmony_ci 25232a6e48fSopenharmony_ci/* 25332a6e48fSopenharmony_ci* Function: disconnect 25432a6e48fSopenharmony_ci* Type: Function 25532a6e48fSopenharmony_ci* Rank: Important(1) 25632a6e48fSopenharmony_ci* EnvConditions: N/A 25732a6e48fSopenharmony_ci* CaseDescription: 1. call Disconnect in other process, check sRet 25832a6e48fSopenharmony_ci */ 25932a6e48fSopenharmony_ciHWTEST_F(SurfaceIPCTest, Disconnect001, Function | MediumTest | Level1) 26032a6e48fSopenharmony_ci{ 26132a6e48fSopenharmony_ci cSurface->RegisterConsumerListener(this); 26232a6e48fSopenharmony_ci auto producer = cSurface->GetProducer(); 26332a6e48fSopenharmony_ci auto pSurface = Surface::CreateSurfaceAsProducer(producer); 26432a6e48fSopenharmony_ci auto sRet = pSurface->Disconnect(); 26532a6e48fSopenharmony_ci ASSERT_EQ(sRet, GSERROR_CONSUMER_DISCONNECTED); // Disconnect cannot be called in two processes 26632a6e48fSopenharmony_ci} 26732a6e48fSopenharmony_ci} 268