/*
 * Copyright (C) 2020 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 <BnAidlStuff.h>
#include <android-base/logging.h>
#include <binder/IServiceManager.h>
#include <binderthreadstate/CallerUtils.h>
#include <binderthreadstateutilstest/1.0/IHidlStuff.h>
#include <gtest/gtest.h>
#include <hidl/HidlTransportSupport.h>
#include <linux/prctl.h>
#include <sys/prctl.h>

using android::BinderCallType;
using android::defaultServiceManager;
using android::getCurrentServingCall;
using android::getService;
using android::OK;
using android::sp;
using android::String16;
using android::binder::Status;
using android::hardware::Return;
using binderthreadstateutilstest::V1_0::IHidlStuff;

constexpr size_t kP1Id = 1;
constexpr size_t kP2Id = 2;

// AIDL and HIDL are in separate namespaces so using same service names
std::string id2name(size_t id) {
    return "libbinderthreadstateutils-" + std::to_string(id);
}

// There are two servers calling each other recursively like this.
//
// P1           P2
// |  --HIDL-->  |
// |  <--HIDL--  |
// |  --AIDL-->  |
// |  <--AIDL--  |
// |  --HIDL-->  |
// |  <--HIDL--  |
// |  --AIDL-->  |
// |  <--AIDL--  |
//   ..........
//
// Calls always come in pairs (AIDL returns AIDL, HIDL returns HIDL) because
// this means that P1 always has a 'waitForResponse' call which can service the
// returning call and continue the recursion. Of course, with more threads, more
// complicated calls are possible, but this should do here.

static void callHidl(size_t id, int32_t idx) {
    auto stuff = IHidlStuff::getService(id2name(id));
    CHECK(stuff->call(idx).isOk());
}

static void callAidl(size_t id, int32_t idx) {
    sp<IAidlStuff> stuff;
    CHECK_EQ(OK, android::getService<IAidlStuff>(String16(id2name(id).c_str()), &stuff));
    auto ret = stuff->call(idx);
    CHECK(ret.isOk()) << ret;
}

static std::string getStackPointerDebugInfo() {
    const void* hwbinderSp = android::hardware::IPCThreadState::self()->getServingStackPointer();
    const void* binderSp = android::IPCThreadState::self()->getServingStackPointer();

    std::stringstream ss;
    ss << "(hwbinder sp: " << hwbinderSp << " binder sp: " << binderSp << ")";
    return ss.str();
}

static inline std::ostream& operator<<(std::ostream& o, const BinderCallType& s) {
    return o << static_cast<std::underlying_type_t<BinderCallType>>(s);
}

class HidlServer : public IHidlStuff {
public:
    HidlServer(size_t thisId, size_t otherId) : thisId(thisId), otherId(otherId) {}
    size_t thisId;
    size_t otherId;

    Return<void> callLocal() {
        CHECK_EQ(BinderCallType::NONE, getCurrentServingCall());
        return android::hardware::Status::ok();
    }
    Return<void> call(int32_t idx) {
        bool doCallHidl = thisId == kP1Id && idx % 4 < 2;

        LOG(INFO) << "HidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
                  << " with tid: " << gettid() << " calling " << (doCallHidl ? "HIDL" : "AIDL");
        CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall())
                << " before call " << getStackPointerDebugInfo();
        if (idx > 0) {
            if (doCallHidl) {
                callHidl(otherId, idx - 1);
            } else {
                callAidl(otherId, idx - 1);
            }
        }
        CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall())
                << " after call " << getStackPointerDebugInfo();
        return android::hardware::Status::ok();
    }
};
class AidlServer : public BnAidlStuff {
public:
    AidlServer(size_t thisId, size_t otherId) : thisId(thisId), otherId(otherId) {}
    size_t thisId;
    size_t otherId;

    Status callLocal() {
        CHECK_EQ(BinderCallType::NONE, getCurrentServingCall());
        return Status::ok();
    }
    Status call(int32_t idx) {
        bool doCallHidl = thisId == kP2Id && idx % 4 < 2;
        LOG(INFO) << "AidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
                  << " with tid: " << gettid() << " calling " << (doCallHidl ? "HIDL" : "AIDL");
        CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall())
                << " before call " << getStackPointerDebugInfo();
        if (idx > 0) {
            if (doCallHidl) {
                callHidl(otherId, idx - 1);
            } else {
                callAidl(otherId, idx - 1);
            }
        }
        CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall())
                << " after call " << getStackPointerDebugInfo();
        return Status::ok();
    }
};

TEST(BinderThreadState, LocalHidlCall) {
    sp<IHidlStuff> server = new HidlServer(0, 0);
    EXPECT_TRUE(server->callLocal().isOk());
}

TEST(BinderThreadState, LocalAidlCall) {
    sp<IAidlStuff> server = new AidlServer(0, 0);
    EXPECT_TRUE(server->callLocal().isOk());
}

TEST(BindThreadState, RemoteHidlCall) {
    auto stuff = IHidlStuff::getService(id2name(kP1Id));
    ASSERT_NE(nullptr, stuff);
    ASSERT_TRUE(stuff->call(0).isOk());
}
TEST(BindThreadState, RemoteAidlCall) {
    sp<IAidlStuff> stuff;
    ASSERT_EQ(OK, android::getService<IAidlStuff>(String16(id2name(kP1Id).c_str()), &stuff));
    ASSERT_NE(nullptr, stuff);
    ASSERT_TRUE(stuff->call(0).isOk());
}

TEST(BindThreadState, RemoteNestedStartHidlCall) {
    auto stuff = IHidlStuff::getService(id2name(kP1Id));
    ASSERT_NE(nullptr, stuff);
    ASSERT_TRUE(stuff->call(100).isOk());
}
TEST(BindThreadState, RemoteNestedStartAidlCall) {
    sp<IAidlStuff> stuff;
    ASSERT_EQ(OK, android::getService<IAidlStuff>(String16(id2name(kP1Id).c_str()), &stuff));
    ASSERT_NE(nullptr, stuff);
    EXPECT_TRUE(stuff->call(100).isOk());
}

int server(size_t thisId, size_t otherId) {
    // AIDL
    android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
    sp<AidlServer> aidlServer = new AidlServer(thisId, otherId);
    CHECK_EQ(OK,
             defaultServiceManager()->addService(String16(id2name(thisId).c_str()), aidlServer));
    android::ProcessState::self()->startThreadPool();

    // HIDL
    android::hardware::configureRpcThreadpool(1, true /*callerWillJoin*/);
    sp<IHidlStuff> hidlServer = new HidlServer(thisId, otherId);
    CHECK_EQ(OK, hidlServer->registerAsService(id2name(thisId).c_str()));
    android::hardware::joinRpcThreadpool();

    return EXIT_FAILURE;
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    android::hardware::details::setTrebleTestingOverride(true);
    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return server(kP1Id, kP2Id);
    }
    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return server(kP2Id, kP1Id);
    }

    android::waitForService<IAidlStuff>(String16(id2name(kP1Id).c_str()));
    android::hardware::details::waitForHwService(IHidlStuff::descriptor, id2name(kP1Id).c_str());
    android::waitForService<IAidlStuff>(String16(id2name(kP2Id).c_str()));
    android::hardware::details::waitForHwService(IHidlStuff::descriptor, id2name(kP2Id).c_str());

    return RUN_ALL_TESTS();
}
