/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <gtest/gtest.h>

#include <android-base/logging.h>
#include <android/os/IServiceManager.h>
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/IServiceManagerUnitTestHelper.h>
#include "fakeservicemanager/FakeServiceManager.h"

#include <sys/prctl.h>
#include <thread>

using namespace android;

#ifdef LIBBINDER_CLIENT_CACHE
constexpr bool kUseLibbinderCache = true;
#else
constexpr bool kUseLibbinderCache = false;
#endif

#ifdef LIBBINDER_ADDSERVICE_CACHE
constexpr bool kUseCacheInAddService = true;
#else
constexpr bool kUseCacheInAddService = false;
#endif

#ifdef LIBBINDER_REMOVE_CACHE_STATIC_LIST
constexpr bool kRemoveStaticList = true;
#else
constexpr bool kRemoveStaticList = false;
#endif

// A service name which is in the static list of cachable services
const String16 kCachedServiceName = String16("isub");

#define EXPECT_OK(status)                 \
    do {                                  \
        binder::Status stat = (status);   \
        EXPECT_TRUE(stat.isOk()) << stat; \
    } while (false)

const String16 kServerName = String16("binderCacheUnitTest");

class FooBar : public BBinder {
public:
    status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t) {
        // exit the server
        std::thread([] { exit(EXIT_FAILURE); }).detach();
        return OK;
    }
    void killServer(sp<IBinder> binder) {
        Parcel data, reply;
        binder->transact(0, data, &reply, 0);
    }
};

class MockAidlServiceManager : public os::IServiceManagerDefault {
public:
    MockAidlServiceManager() : innerSm() {}

    binder::Status checkService2(const ::std::string& name, os::Service* _out) override {
        os::ServiceWithMetadata serviceWithMetadata = os::ServiceWithMetadata();
        serviceWithMetadata.service = innerSm.getService(String16(name.c_str()));
        serviceWithMetadata.isLazyService = false;
        *_out = os::Service::make<os::Service::Tag::serviceWithMetadata>(serviceWithMetadata);
        return binder::Status::ok();
    }

    binder::Status addService(const std::string& name, const sp<IBinder>& service,
                              bool allowIsolated, int32_t dumpPriority) override {
        return binder::Status::fromStatusT(
                innerSm.addService(String16(name.c_str()), service, allowIsolated, dumpPriority));
    }

    void clearServices() { innerSm.clear(); }

    FakeServiceManager innerSm;
};

// Returns services with isLazyService flag as true.
class MockAidlServiceManager2 : public os::IServiceManagerDefault {
public:
    MockAidlServiceManager2() : innerSm() {}

    binder::Status checkService2(const ::std::string& name, os::Service* _out) override {
        os::ServiceWithMetadata serviceWithMetadata = os::ServiceWithMetadata();
        serviceWithMetadata.service = innerSm.getService(String16(name.c_str()));
        serviceWithMetadata.isLazyService = true;
        *_out = os::Service::make<os::Service::Tag::serviceWithMetadata>(serviceWithMetadata);
        return binder::Status::ok();
    }

    binder::Status addService(const std::string& name, const sp<IBinder>& service,
                              bool allowIsolated, int32_t dumpPriority) override {
        return binder::Status::fromStatusT(
                innerSm.addService(String16(name.c_str()), service, allowIsolated, dumpPriority));
    }

    void clearServices() { innerSm.clear(); }

    FakeServiceManager innerSm;
};

class LibbinderCacheRemoveStaticList : public ::testing::Test {
protected:
    void SetUp() override {
        fakeServiceManager = sp<MockAidlServiceManager2>::make();
        mServiceManager = getServiceManagerShimFromAidlServiceManagerForTests(fakeServiceManager);
        mServiceManager->enableAddServiceCache(true);
    }
    void TearDown() override {}

public:
    void cacheAddServiceAndConfirmCacheMiss(const sp<IBinder>& binder1) {
        // Add a service. This shouldn't cache it.
        EXPECT_EQ(OK,
                  mServiceManager->addService(kCachedServiceName, binder1,
                                              /*allowIsolated = */ false,
                                              android::os::IServiceManager::FLAG_IS_LAZY_SERVICE));
        // Try to populate cache. Cache shouldn't be updated.
        EXPECT_EQ(binder1, mServiceManager->checkService(kCachedServiceName));
        fakeServiceManager->clearServices();
        EXPECT_EQ(nullptr, mServiceManager->checkService(kCachedServiceName));
    }

    sp<MockAidlServiceManager2> fakeServiceManager;
    sp<android::IServiceManager> mServiceManager;
};

TEST_F(LibbinderCacheRemoveStaticList, AddLocalServiceAndConfirmCacheMiss) {
    if (!kRemoveStaticList) {
        GTEST_SKIP() << "Skipping as feature is not enabled";
        return;
    }
    sp<IBinder> binder1 = sp<BBinder>::make();
    cacheAddServiceAndConfirmCacheMiss(binder1);
}

TEST_F(LibbinderCacheRemoveStaticList, AddRemoteServiceAndConfirmCacheMiss) {
    if (!kRemoveStaticList) {
        GTEST_SKIP() << "Skipping as feature is not enabled";
        return;
    }
    sp<IBinder> binder1 = defaultServiceManager()->checkService(kServerName);
    ASSERT_NE(binder1, nullptr);
    cacheAddServiceAndConfirmCacheMiss(binder1);
}

class LibbinderCacheAddServiceTest : public ::testing::Test {
protected:
    void SetUp() override {
        fakeServiceManager = sp<MockAidlServiceManager>::make();
        mServiceManager = getServiceManagerShimFromAidlServiceManagerForTests(fakeServiceManager);
        mServiceManager->enableAddServiceCache(true);
    }

    void TearDown() override {}

public:
    void cacheAddServiceAndConfirmCacheHit(const sp<IBinder>& binder1) {
        // Add a service. This also caches it.
        EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder1));
        // remove services from fakeservicemanager
        fakeServiceManager->clearServices();

        sp<IBinder> result = mServiceManager->checkService(kCachedServiceName);
        if (kUseCacheInAddService && kUseLibbinderCache) {
            // If cache is enabled, we should get the binder.
            EXPECT_EQ(binder1, result);
        } else {
            // If cache is disabled, then we should get the null binder
            EXPECT_EQ(nullptr, result);
        }
    }
    sp<MockAidlServiceManager> fakeServiceManager;
    sp<android::IServiceManager> mServiceManager;
};

TEST_F(LibbinderCacheAddServiceTest, AddLocalServiceAndConfirmCacheHit) {
    sp<IBinder> binder1 = sp<BBinder>::make();
    cacheAddServiceAndConfirmCacheHit(binder1);
}

TEST_F(LibbinderCacheAddServiceTest, AddRemoteServiceAndConfirmCacheHit) {
    sp<IBinder> binder1 = defaultServiceManager()->checkService(kServerName);
    ASSERT_NE(binder1, nullptr);
    cacheAddServiceAndConfirmCacheHit(binder1);
}

class LibbinderCacheTest : public ::testing::Test {
protected:
    void SetUp() override {
        fakeServiceManager = sp<MockAidlServiceManager>::make();
        mServiceManager = getServiceManagerShimFromAidlServiceManagerForTests(fakeServiceManager);
        mServiceManager->enableAddServiceCache(false);
    }

    void TearDown() override {}

public:
    void cacheAndConfirmCacheHit(const sp<IBinder>& binder1, const sp<IBinder>& binder2) {
        // Add a service
        EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder1));
        // Get the service. This caches it.
        sp<IBinder> result = mServiceManager->checkService(kCachedServiceName);
        ASSERT_EQ(binder1, result);

        // Add the different binder and replace the service.
        // The cache should still hold the original binder.
        EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder2));

        result = mServiceManager->checkService(kCachedServiceName);
        if (kUseLibbinderCache) {
            // If cache is enabled, we should get the binder to Service Manager.
            EXPECT_EQ(binder1, result);
        } else {
            // If cache is disabled, then we should get the newer binder
            EXPECT_EQ(binder2, result);
        }
    }

    sp<MockAidlServiceManager> fakeServiceManager;
    sp<android::IServiceManager> mServiceManager;
};

TEST_F(LibbinderCacheTest, AddLocalServiceAndConfirmCacheHit) {
    sp<IBinder> binder1 = sp<BBinder>::make();
    sp<IBinder> binder2 = sp<BBinder>::make();

    cacheAndConfirmCacheHit(binder1, binder2);
}

TEST_F(LibbinderCacheTest, AddRemoteServiceAndConfirmCacheHit) {
    sp<IBinder> binder1 = defaultServiceManager()->checkService(kServerName);
    ASSERT_NE(binder1, nullptr);
    sp<IBinder> binder2 = IInterface::asBinder(mServiceManager);

    cacheAndConfirmCacheHit(binder1, binder2);
}

TEST_F(LibbinderCacheTest, RemoveFromCacheOnServerDeath) {
    sp<IBinder> binder1 = defaultServiceManager()->checkService(kServerName);
    FooBar foo = FooBar();

    EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder1));

    // Check Service, this caches the binder
    sp<IBinder> result = mServiceManager->checkService(kCachedServiceName);
    ASSERT_EQ(binder1, result);

    // Kill the server, this should remove from cache.
    pid_t pid;
    ASSERT_EQ(OK, binder1->getDebugPid(&pid));
    foo.killServer(binder1);
    system(("kill -9 " + std::to_string(pid)).c_str());

    sp<IBinder> binder2 = sp<BBinder>::make();

    // Add new service with the same name.
    // This will replace the service in FakeServiceManager.
    EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder2));

    // Confirm that new service is returned instead of old.
    int retry_count = 20;
    sp<IBinder> result2;
    do {
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
        if (retry_count-- == 0) {
            break;
        }
        result2 = mServiceManager->checkService(kCachedServiceName);
    } while (result2 != binder2);

    ASSERT_EQ(binder2, result2);
}

TEST_F(LibbinderCacheTest, NullBinderNotCached) {
    sp<IBinder> binder1 = nullptr;
    sp<IBinder> binder2 = sp<BBinder>::make();

    // Check for a cacheble service which isn't registered.
    // FakeServiceManager should return nullptr.
    // This shouldn't be cached.
    sp<IBinder> result = mServiceManager->checkService(kCachedServiceName);
    ASSERT_EQ(binder1, result);

    // Add the same service
    EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder2));

    // This should return the newly added service.
    result = mServiceManager->checkService(kCachedServiceName);
    EXPECT_EQ(binder2, result);
}

// TODO(b/333854840): Remove this test removing the static list
TEST_F(LibbinderCacheTest, DoNotCacheServiceNotInList) {
    if (kRemoveStaticList) {
        GTEST_SKIP() << "Skipping test as static list is disabled";
        return;
    }

    sp<IBinder> binder1 = sp<BBinder>::make();
    sp<IBinder> binder2 = sp<BBinder>::make();
    String16 serviceName = String16("NewLibbinderCacheTest");
    // Add a service
    EXPECT_EQ(OK, mServiceManager->addService(serviceName, binder1));
    // Get the service. This shouldn't caches it.
    sp<IBinder> result = mServiceManager->checkService(serviceName);
    ASSERT_EQ(binder1, result);

    // Add the different binder and replace the service.
    EXPECT_EQ(OK, mServiceManager->addService(serviceName, binder2));

    // Confirm that we get the new service
    result = mServiceManager->checkService(serviceName);
    EXPECT_EQ(binder2, result);
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);

    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);

        // Start a FooBar service and add it to the servicemanager.
        sp<IBinder> server = new FooBar();
        defaultServiceManager()->addService(kServerName, server);

        IPCThreadState::self()->joinThreadPool(true);
        exit(1); // should not reach
    }

    status_t err = ProcessState::self()->setThreadPoolMaxThreadCount(3);
    ProcessState::self()->startThreadPool();
    CHECK_EQ(ProcessState::self()->isThreadPoolStarted(), true);
    CHECK_GT(ProcessState::self()->getThreadPoolMaxTotalThreadCount(), 0);

    auto binder = defaultServiceManager()->waitForService(kServerName);
    CHECK_NE(nullptr, binder.get());
    return RUN_ALL_TESTS();
}
