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