/*
 * Copyright (C) 2018 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 <IBinderNdkUnitTest.h>
#include <aidl/BnBinderNdkUnitTest.h>
#include <aidl/BnEmpty.h>
#include <android-base/logging.h>
#include <android/binder_ibinder_jni.h>
#include <android/binder_ibinder_platform.h>
#include <android/binder_libbinder.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <gtest/gtest.h>
#include <iface/iface.h>
#include <utils/Looper.h>

// warning: this is assuming that libbinder_ndk is using the same copy
// of libbinder that we are.
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
#include <binder/IServiceManager.h>
#include <binder/IShellCallback.h>

#include <sys/prctl.h>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include "android/binder_ibinder.h"

using namespace android;

constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
constexpr char kLazyBinderNdkUnitTestService[] = "LazyBinderNdkUnitTest";
constexpr char kForcePersistNdkUnitTestService[] = "ForcePersistNdkUnitTestService";
constexpr char kActiveServicesNdkUnitTestService[] = "ActiveServicesNdkUnitTestService";

constexpr unsigned int kShutdownWaitTime = 10;
constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715;

class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
    ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
        *out = in;
        return ndk::ScopedAStatus::ok();
    }
    ndk::ScopedAStatus takeInterface(const std::shared_ptr<aidl::IEmpty>& empty) {
        (void)empty;
        return ndk::ScopedAStatus::ok();
    }
    ndk::ScopedAStatus forceFlushCommands() {
        // warning: this is assuming that libbinder_ndk is using the same copy
        // of libbinder that we are.
        android::IPCThreadState::self()->flushCommands();
        return ndk::ScopedAStatus::ok();
    }
    ndk::ScopedAStatus getsRequestedSid(bool* out) {
        const char* sid = AIBinder_getCallingSid();
        std::cout << "Got security context: " << (sid ?: "null") << std::endl;
        *out = sid != nullptr;
        return ndk::ScopedAStatus::ok();
    }
    binder_status_t handleShellCommand(int /*in*/, int out, int /*err*/, const char** args,
                                       uint32_t numArgs) override {
        for (uint32_t i = 0; i < numArgs; i++) {
            dprintf(out, "%s", args[i]);
        }
        fsync(out);
        return STATUS_OK;
    }
    ndk::ScopedAStatus forcePersist(bool persist) {
        AServiceManager_forceLazyServicesPersist(persist);
        return ndk::ScopedAStatus::ok();
    }
    ndk::ScopedAStatus setCustomActiveServicesCallback() {
        AServiceManager_setActiveServicesCallback(activeServicesCallback, this);
        return ndk::ScopedAStatus::ok();
    }
    static bool activeServicesCallback(bool hasClients, void* context) {
        if (hasClients) {
            return false;
        }

        // Unregister all services
        if (!AServiceManager_tryUnregister()) {
            // Prevent shutdown (test will fail)
            return false;
        }

        // Re-register all services
        AServiceManager_reRegister();

        // Unregister again before shutdown
        if (!AServiceManager_tryUnregister()) {
            // Prevent shutdown (test will fail)
            return false;
        }

        // Check if the context was passed correctly
        MyBinderNdkUnitTest* service = static_cast<MyBinderNdkUnitTest*>(context);
        if (service->contextTestValue != kContextTestValue) {
            // Prevent shutdown (test will fail)
            return false;
        }

        exit(EXIT_SUCCESS);
        // Unreachable
    }

    uint64_t contextTestValue = kContextTestValue;
};

int generatedService() {
    ABinderProcess_setThreadPoolMaxThreadCount(0);

    auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>();
    auto binder = service->asBinder();

    AIBinder_setRequestingSid(binder.get(), true);

    binder_exception_t exception =
            AServiceManager_addService(binder.get(), kBinderNdkUnitTestService);

    if (exception != EX_NONE) {
        LOG(FATAL) << "Could not register: " << exception << " " << kBinderNdkUnitTestService;
    }

    ABinderProcess_joinThreadPool();

    return 1;  // should not return
}

// manually-written parceling class considered bad practice
class MyFoo : public IFoo {
    binder_status_t doubleNumber(int32_t in, int32_t* out) override {
        *out = 2 * in;
        LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
        return STATUS_OK;
    }

    binder_status_t die() override {
        LOG(FATAL) << "IFoo::die called!";
        return STATUS_UNKNOWN_ERROR;
    }
};

void manualService(const char* instance) {
    // Strong reference to MyFoo kept by service manager.
    binder_exception_t exception = (new MyFoo)->addService(instance);

    if (exception != EX_NONE) {
        LOG(FATAL) << "Could not register: " << exception << " " << instance;
    }
}
int manualPollingService(const char* instance) {
    int fd;
    CHECK(STATUS_OK == ABinderProcess_setupPolling(&fd));
    manualService(instance);

    class Handler : public LooperCallback {
        int handleEvent(int /*fd*/, int /*events*/, void* /*data*/) override {
            ABinderProcess_handlePolledCommands();
            return 1;  // Continue receiving callbacks.
        }
    };

    sp<Looper> looper = Looper::prepare(0 /* opts */);
    looper->addFd(fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, new Handler(), nullptr /*data*/);
    // normally, would add additional fds
    while (true) {
        looper->pollAll(-1 /* timeoutMillis */);
    }
    return 1;  // should not reach
}
int manualThreadPoolService(const char* instance) {
    ABinderProcess_setThreadPoolMaxThreadCount(0);
    manualService(instance);
    ABinderProcess_joinThreadPool();
    return 1;
}

int lazyService(const char* instance) {
    ABinderProcess_setThreadPoolMaxThreadCount(0);
    // Wait to register this service to make sure the main test process will
    // actually wait for the service to be available. Tested with sleep(60),
    // and reduced for sake of time.
    sleep(1);
    // Strong reference to MyBinderNdkUnitTest kept by service manager.
    // This is just for testing, it has no corresponding init behavior.
    auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>();
    auto binder = service->asBinder();

    binder_status_t status = AServiceManager_registerLazyService(binder.get(), instance);
    if (status != STATUS_OK) {
        LOG(FATAL) << "Could not register: " << status << " " << instance;
    }

    ABinderProcess_joinThreadPool();

    return 1;  // should not return
}

bool isServiceRunning(const char* serviceName) {
    AIBinder* binder = AServiceManager_checkService(serviceName);
    if (binder == nullptr) {
        return false;
    }
    AIBinder_decStrong(binder);

    return true;
}

TEST(NdkBinder, GetServiceThatDoesntExist) {
    sp<IFoo> foo = IFoo::getService("asdfghkl;");
    EXPECT_EQ(nullptr, foo.get());
}

TEST(NdkBinder, CheckServiceThatDoesntExist) {
    AIBinder* binder = AServiceManager_checkService("asdfghkl;");
    ASSERT_EQ(nullptr, binder);
}

TEST(NdkBinder, CheckServiceThatDoesExist) {
    AIBinder* binder = AServiceManager_checkService(kExistingNonNdkService);
    EXPECT_NE(nullptr, binder);
    EXPECT_EQ(STATUS_OK, AIBinder_ping(binder));

    AIBinder_decStrong(binder);
}

TEST(NdkBinder, DoubleNumber) {
    sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
    ASSERT_NE(foo, nullptr);

    int32_t out;
    EXPECT_EQ(STATUS_OK, foo->doubleNumber(1, &out));
    EXPECT_EQ(2, out);
}

void defaultInstanceCounter(const char* instance, void* context) {
    if (strcmp(instance, "default") == 0) {
        ++*(size_t*)(context);
    }
}

TEST(NdkBinder, GetDeclaredInstances) {
    bool hasLight = AServiceManager_isDeclared("android.hardware.light.ILights/default");

    size_t count;
    AServiceManager_forEachDeclaredInstance("android.hardware.light.ILights", &count,
                                            defaultInstanceCounter);

    // At the time of writing this test, there is no good interface guaranteed
    // to be on all devices. Cuttlefish has light, so this will generally test
    // things.
    EXPECT_EQ(count, hasLight ? 1 : 0);
}

TEST(NdkBinder, GetLazyService) {
    // Not declared in the vintf manifest
    ASSERT_FALSE(AServiceManager_isDeclared(kLazyBinderNdkUnitTestService));
    ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService));
    std::shared_ptr<aidl::IBinderNdkUnitTest> service =
            aidl::IBinderNdkUnitTest::fromBinder(binder);
    ASSERT_NE(service, nullptr);

    EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
}

TEST(NdkBinder, IsUpdatable) {
    bool isUpdatable = AServiceManager_isUpdatableViaApex("android.hardware.light.ILights/default");
    EXPECT_EQ(isUpdatable, false);
}

// This is too slow
TEST(NdkBinder, CheckLazyServiceShutDown) {
    ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService));
    std::shared_ptr<aidl::IBinderNdkUnitTest> service =
            aidl::IBinderNdkUnitTest::fromBinder(binder);
    ASSERT_NE(service, nullptr);

    EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
    binder = nullptr;
    service = nullptr;
    IPCThreadState::self()->flushCommands();
    // Make sure the service is dead after some time of no use
    sleep(kShutdownWaitTime);
    ASSERT_EQ(nullptr, AServiceManager_checkService(kLazyBinderNdkUnitTestService));
}

TEST(NdkBinder, ForcedPersistenceTest) {
    for (int i = 0; i < 2; i++) {
        ndk::SpAIBinder binder(AServiceManager_waitForService(kForcePersistNdkUnitTestService));
        std::shared_ptr<aidl::IBinderNdkUnitTest> service =
                aidl::IBinderNdkUnitTest::fromBinder(binder);
        ASSERT_NE(service, nullptr);
        ASSERT_TRUE(service->forcePersist(i == 0).isOk());

        binder = nullptr;
        service = nullptr;
        IPCThreadState::self()->flushCommands();

        sleep(kShutdownWaitTime);

        bool isRunning = isServiceRunning(kForcePersistNdkUnitTestService);

        if (i == 0) {
            ASSERT_TRUE(isRunning) << "Service shut down when it shouldn't have.";
        } else {
            ASSERT_FALSE(isRunning) << "Service failed to shut down.";
        }
    }
}

TEST(NdkBinder, ActiveServicesCallbackTest) {
    ndk::SpAIBinder binder(AServiceManager_waitForService(kActiveServicesNdkUnitTestService));
    std::shared_ptr<aidl::IBinderNdkUnitTest> service =
            aidl::IBinderNdkUnitTest::fromBinder(binder);
    ASSERT_NE(service, nullptr);
    ASSERT_TRUE(service->setCustomActiveServicesCallback().isOk());

    binder = nullptr;
    service = nullptr;
    IPCThreadState::self()->flushCommands();

    sleep(kShutdownWaitTime);

    ASSERT_FALSE(isServiceRunning(kActiveServicesNdkUnitTestService))
            << "Service failed to shut down.";
}

void LambdaOnDeath(void* cookie) {
    auto onDeath = static_cast<std::function<void(void)>*>(cookie);
    (*onDeath)();
};
TEST(NdkBinder, DeathRecipient) {
    using namespace std::chrono_literals;

    AIBinder* binder;
    sp<IFoo> foo = IFoo::getService(IFoo::kInstanceNameToDieFor, &binder);
    ASSERT_NE(nullptr, foo.get());
    ASSERT_NE(nullptr, binder);

    std::mutex deathMutex;
    std::condition_variable deathCv;
    bool deathRecieved = false;

    std::function<void(void)> onDeath = [&] {
        std::cerr << "Binder died (as requested)." << std::endl;
        deathRecieved = true;
        deathCv.notify_one();
    };

    AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(LambdaOnDeath);

    EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, static_cast<void*>(&onDeath)));

    // the binder driver should return this if the service dies during the transaction
    EXPECT_EQ(STATUS_DEAD_OBJECT, foo->die());

    foo = nullptr;

    std::unique_lock<std::mutex> lock(deathMutex);
    EXPECT_TRUE(deathCv.wait_for(lock, 1s, [&] { return deathRecieved; }));
    EXPECT_TRUE(deathRecieved);

    AIBinder_DeathRecipient_delete(recipient);
    AIBinder_decStrong(binder);
    binder = nullptr;
}

TEST(NdkBinder, RetrieveNonNdkService) {
    AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
    ASSERT_NE(nullptr, binder);
    EXPECT_TRUE(AIBinder_isRemote(binder));
    EXPECT_TRUE(AIBinder_isAlive(binder));
    EXPECT_EQ(STATUS_OK, AIBinder_ping(binder));

    AIBinder_decStrong(binder);
}

void OnBinderDeath(void* cookie) {
    LOG(ERROR) << "BINDER DIED. COOKIE: " << cookie;
}

TEST(NdkBinder, LinkToDeath) {
    AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
    ASSERT_NE(nullptr, binder);

    AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(OnBinderDeath);
    ASSERT_NE(nullptr, recipient);

    EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, nullptr));
    EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder, recipient, nullptr));
    EXPECT_EQ(STATUS_OK, AIBinder_unlinkToDeath(binder, recipient, nullptr));
    EXPECT_EQ(STATUS_OK, AIBinder_unlinkToDeath(binder, recipient, nullptr));
    EXPECT_EQ(STATUS_NAME_NOT_FOUND, AIBinder_unlinkToDeath(binder, recipient, nullptr));

    AIBinder_DeathRecipient_delete(recipient);
    AIBinder_decStrong(binder);
}

class MyTestFoo : public IFoo {
    binder_status_t doubleNumber(int32_t in, int32_t* out) override {
        *out = 2 * in;
        LOG(INFO) << "doubleNumber (" << in << ") => " << *out;
        return STATUS_OK;
    }
    binder_status_t die() override {
        ADD_FAILURE() << "die called on local instance";
        return STATUS_OK;
    }
};

TEST(NdkBinder, AddNullService) {
    EXPECT_EQ(EX_ILLEGAL_ARGUMENT, AServiceManager_addService(nullptr, "any-service-name"));
}

TEST(NdkBinder, AddInvalidServiceName) {
    sp<IFoo> foo = new MyTestFoo;
    EXPECT_EQ(EX_ILLEGAL_ARGUMENT, foo->addService("!@#$%^&"));
}

TEST(NdkBinder, GetServiceInProcess) {
    static const char* kInstanceName = "test-get-service-in-process";

    sp<IFoo> foo = new MyTestFoo;
    EXPECT_EQ(EX_NONE, foo->addService(kInstanceName));

    sp<IFoo> getFoo = IFoo::getService(kInstanceName);
    EXPECT_EQ(foo.get(), getFoo.get());

    int32_t out;
    EXPECT_EQ(STATUS_OK, getFoo->doubleNumber(1, &out));
    EXPECT_EQ(2, out);
}

TEST(NdkBinder, EqualityOfRemoteBinderPointer) {
    AIBinder* binderA = AServiceManager_getService(kExistingNonNdkService);
    ASSERT_NE(nullptr, binderA);

    AIBinder* binderB = AServiceManager_getService(kExistingNonNdkService);
    ASSERT_NE(nullptr, binderB);

    EXPECT_EQ(binderA, binderB);

    AIBinder_decStrong(binderA);
    AIBinder_decStrong(binderB);
}

TEST(NdkBinder, ToFromJavaNullptr) {
    EXPECT_EQ(nullptr, AIBinder_toJavaBinder(nullptr, nullptr));
    EXPECT_EQ(nullptr, AIBinder_fromJavaBinder(nullptr, nullptr));
}

TEST(NdkBinder, ABpBinderRefCount) {
    AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
    AIBinder_Weak* wBinder = AIBinder_Weak_new(binder);

    ASSERT_NE(nullptr, binder);
    EXPECT_EQ(1, AIBinder_debugGetRefCount(binder));

    AIBinder_decStrong(binder);

    ASSERT_EQ(nullptr, AIBinder_Weak_promote(wBinder));

    AIBinder_Weak_delete(wBinder);
}

TEST(NdkBinder, AddServiceMultipleTimes) {
    static const char* kInstanceName1 = "test-multi-1";
    static const char* kInstanceName2 = "test-multi-2";
    sp<IFoo> foo = new MyTestFoo;
    EXPECT_EQ(EX_NONE, foo->addService(kInstanceName1));
    EXPECT_EQ(EX_NONE, foo->addService(kInstanceName2));
    EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
}

TEST(NdkBinder, RequestedSidWorks) {
    ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService));
    std::shared_ptr<aidl::IBinderNdkUnitTest> service =
            aidl::IBinderNdkUnitTest::fromBinder(binder);

    bool gotSid = false;
    EXPECT_TRUE(service->getsRequestedSid(&gotSid).isOk());
    EXPECT_TRUE(gotSid);
}

TEST(NdkBinder, SentAidlBinderCanBeDestroyed) {
    static volatile bool destroyed = false;
    static std::mutex dMutex;
    static std::condition_variable cv;

    class MyEmpty : public aidl::BnEmpty {
        virtual ~MyEmpty() {
            destroyed = true;
            cv.notify_one();
        }
    };

    std::shared_ptr<MyEmpty> empty = ndk::SharedRefBase::make<MyEmpty>();

    ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService));
    std::shared_ptr<aidl::IBinderNdkUnitTest> service =
            aidl::IBinderNdkUnitTest::fromBinder(binder);

    EXPECT_FALSE(destroyed);

    service->takeInterface(empty);
    service->forceFlushCommands();
    empty = nullptr;

    // give other binder thread time to process commands
    {
        using namespace std::chrono_literals;
        std::unique_lock<std::mutex> lk(dMutex);
        cv.wait_for(lk, 1s, [] { return destroyed; });
    }

    EXPECT_TRUE(destroyed);
}

TEST(NdkBinder, ConvertToPlatformBinder) {
    for (const ndk::SpAIBinder& binder :
         {// remote
          ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)),
          // local
          ndk::SharedRefBase::make<MyBinderNdkUnitTest>()->asBinder()}) {
        // convert to platform binder
        EXPECT_NE(binder.get(), nullptr);
        sp<IBinder> platformBinder = AIBinder_toPlatformBinder(binder.get());
        EXPECT_NE(platformBinder.get(), nullptr);
        auto proxy = interface_cast<IBinderNdkUnitTest>(platformBinder);
        EXPECT_NE(proxy, nullptr);

        // use platform binder
        int out;
        EXPECT_TRUE(proxy->repeatInt(4, &out).isOk());
        EXPECT_EQ(out, 4);

        // convert back
        ndk::SpAIBinder backBinder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(platformBinder));
        EXPECT_EQ(backBinder.get(), binder.get());
    }
}

class MyResultReceiver : public BnResultReceiver {
   public:
    Mutex mMutex;
    Condition mCondition;
    bool mHaveResult = false;
    int32_t mResult = 0;

    virtual void send(int32_t resultCode) {
        AutoMutex _l(mMutex);
        mResult = resultCode;
        mHaveResult = true;
        mCondition.signal();
    }

    int32_t waitForResult() {
        AutoMutex _l(mMutex);
        while (!mHaveResult) {
            mCondition.wait(mMutex);
        }
        return mResult;
    }
};

class MyShellCallback : public BnShellCallback {
   public:
    virtual int openFile(const String16& /*path*/, const String16& /*seLinuxContext*/,
                         const String16& /*mode*/) {
        // Empty implementation.
        return 0;
    }
};

bool ReadFdToString(int fd, std::string* content) {
    char buf[64];
    ssize_t n;
    while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
        content->append(buf, n);
    }
    return (n == 0) ? true : false;
}

std::string shellCmdToString(sp<IBinder> unitTestService, const std::vector<const char*>& args) {
    int inFd[2] = {-1, -1};
    int outFd[2] = {-1, -1};
    int errFd[2] = {-1, -1};

    EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, inFd));
    EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, outFd));
    EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, errFd));

    sp<MyShellCallback> cb = new MyShellCallback();
    sp<MyResultReceiver> resultReceiver = new MyResultReceiver();

    Vector<String16> argsVec;
    for (int i = 0; i < args.size(); i++) {
        argsVec.add(String16(args[i]));
    }
    status_t error = IBinder::shellCommand(unitTestService, inFd[0], outFd[0], errFd[0], argsVec,
                                           cb, resultReceiver);
    EXPECT_EQ(error, android::OK);

    status_t res = resultReceiver->waitForResult();
    EXPECT_EQ(res, android::OK);

    close(inFd[0]);
    close(inFd[1]);
    close(outFd[0]);
    close(errFd[0]);
    close(errFd[1]);

    std::string ret;
    EXPECT_TRUE(ReadFdToString(outFd[1], &ret));
    close(outFd[1]);
    return ret;
}

TEST(NdkBinder, UseHandleShellCommand) {
    static const sp<android::IServiceManager> sm(android::defaultServiceManager());
    sp<IBinder> testService = sm->getService(String16(kBinderNdkUnitTestService));

    EXPECT_EQ("", shellCmdToString(testService, {}));
    EXPECT_EQ("", shellCmdToString(testService, {"", ""}));
    EXPECT_EQ("Hello world!", shellCmdToString(testService, {"Hello ", "world!"}));
    EXPECT_EQ("CMD", shellCmdToString(testService, {"C", "M", "D"}));
}

TEST(NdkBinder, GetClassInterfaceDescriptor) {
    ASSERT_STREQ(IFoo::kIFooDescriptor, AIBinder_Class_getDescriptor(IFoo::kClass));
}

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

    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return manualThreadPoolService(IFoo::kInstanceNameToDieFor);
    }
    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return manualPollingService(IFoo::kSomeInstanceName);
    }
    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return lazyService(kLazyBinderNdkUnitTestService);
    }
    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return lazyService(kForcePersistNdkUnitTestService);
    }
    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return lazyService(kActiveServicesNdkUnitTestService);
    }
    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return generatedService();
    }

    ABinderProcess_setThreadPoolMaxThreadCount(1);  // to receive death notifications/callbacks
    ABinderProcess_startThreadPool();

    return RUN_ALL_TESTS();
}

#include <android/binder_auto_utils.h>
#include <android/binder_interface_utils.h>
#include <android/binder_parcel_utils.h>
