/*
 * 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_manager.h>
#include <android/binder_process.h>
#include <gtest/gtest.h>
#include <iface/iface.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 <mutex>

using namespace android;

constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";

class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
    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();
    }
    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;
    }
};

int generatedService() {
    ABinderProcess_setThreadPoolMaxThreadCount(0);

    auto service = ndk::SharedRefBase::make<MyBinderNdkUnitTest>();
    binder_status_t status =
            AServiceManager_addService(service->asBinder().get(), kBinderNdkUnitTestService);

    if (status != STATUS_OK) {
        LOG(FATAL) << "Could not register: " << status << " " << 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;
    }
};

int manualService(const char* instance) {
    ABinderProcess_setThreadPoolMaxThreadCount(0);

    // Strong reference to MyFoo kept by service manager.
    binder_status_t status = (new MyFoo)->addService(instance);

    if (status != STATUS_OK) {
        LOG(FATAL) << "Could not register: " << status << " " << instance;
    }

    ABinderProcess_joinThreadPool();

    return 1;  // should not return
}

// This is too slow
// 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 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, GetServiceInProcess) {
    static const char* kInstanceName = "test-get-service-in-process";

    sp<IFoo> foo = new MyTestFoo;
    EXPECT_EQ(STATUS_OK, 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 because would need to decStrong if non-null and we shouldn't need to add a no-op here
    ASSERT_NE(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(STATUS_OK, foo->addService(kInstanceName1));
    EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName2));
    EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
}

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);
}

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"}));
}

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

    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return manualService(IFoo::kInstanceNameToDieFor);
    }
    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return manualService(IFoo::kSomeInstanceName);
    }
    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return generatedService();
    }

    ABinderProcess_setThreadPoolMaxThreadCount(1);  // to recieve 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>
