/*
 * Copyright (C) 2019 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.
 */

#define LOG_TAG "IncrementalService"

#include "ServiceWrappers.h"

#include <MountRegistry.h>
#include <android-base/logging.h>
#include <android/content/pm/IDataLoaderManager.h>
#include <android/os/IVold.h>
#include <binder/AppOpsManager.h>
#include <utils/String16.h>

#include <filesystem>
#include <thread>

#include "IncrementalServiceValidation.h"

using namespace std::literals;

namespace android::incremental {

static constexpr auto kVoldServiceName = "vold"sv;
static constexpr auto kDataLoaderManagerName = "dataloader_manager"sv;

class RealVoldService : public VoldServiceWrapper {
public:
    RealVoldService(sp<os::IVold> vold) : mInterface(std::move(vold)) {}
    ~RealVoldService() = default;
    binder::Status mountIncFs(
            const std::string& backingPath, const std::string& targetDir, int32_t flags,
            const std::string& sysfsName,
            os::incremental::IncrementalFileSystemControlParcel* _aidl_return) const final {
        return mInterface->mountIncFs(backingPath, targetDir, flags, sysfsName, _aidl_return);
    }
    binder::Status unmountIncFs(const std::string& dir) const final {
        return mInterface->unmountIncFs(dir);
    }
    binder::Status bindMount(const std::string& sourceDir,
                             const std::string& targetDir) const final {
        return mInterface->bindMount(sourceDir, targetDir);
    }
    binder::Status setIncFsMountOptions(
            const ::android::os::incremental::IncrementalFileSystemControlParcel& control,
            bool enableReadLogs, bool enableReadTimeouts,
            const std::string& sysfsName) const final {
        return mInterface->setIncFsMountOptions(control, enableReadLogs, enableReadTimeouts,
                                                sysfsName);
    }

private:
    sp<os::IVold> mInterface;
};

class RealDataLoaderManager : public DataLoaderManagerWrapper {
public:
    RealDataLoaderManager(sp<content::pm::IDataLoaderManager> manager)
          : mInterface(std::move(manager)) {}
    ~RealDataLoaderManager() = default;
    binder::Status bindToDataLoader(MountId mountId,
                                    const content::pm::DataLoaderParamsParcel& params,
                                    int bindDelayMs,
                                    const sp<content::pm::IDataLoaderStatusListener>& listener,
                                    bool* _aidl_return) const final {
        return mInterface->bindToDataLoader(mountId, params, bindDelayMs, listener, _aidl_return);
    }
    binder::Status getDataLoader(MountId mountId,
                                 sp<content::pm::IDataLoader>* _aidl_return) const final {
        return mInterface->getDataLoader(mountId, _aidl_return);
    }
    binder::Status unbindFromDataLoader(MountId mountId) const final {
        return mInterface->unbindFromDataLoader(mountId);
    }

private:
    sp<content::pm::IDataLoaderManager> mInterface;
};

class RealAppOpsManager : public AppOpsManagerWrapper {
public:
    ~RealAppOpsManager() = default;
    binder::Status checkPermission(const char* permission, const char* operation,
                                   const char* package) const final {
        return android::incremental::CheckPermissionForDataDelivery(permission, operation, package);
    }
    void startWatchingMode(int32_t op, const String16& packageName,
                           const sp<IAppOpsCallback>& callback) final {
        mAppOpsManager.startWatchingMode(op, packageName, callback);
    }
    void stopWatchingMode(const sp<IAppOpsCallback>& callback) final {
        mAppOpsManager.stopWatchingMode(callback);
    }

private:
    android::AppOpsManager mAppOpsManager;
};

class RealJniWrapper final : public JniWrapper {
public:
    RealJniWrapper(JavaVM* jvm);
    void initializeForCurrentThread() const final;

    static JavaVM* getJvm(JNIEnv* env);

private:
    JavaVM* const mJvm;
};

class RealLooperWrapper final : public LooperWrapper {
public:
    int addFd(int fd, int ident, int events, android::Looper_callbackFunc callback,
              void* data) final {
        return mLooper.addFd(fd, ident, events, callback, data);
    }
    int removeFd(int fd) final { return mLooper.removeFd(fd); }
    void wake() final { return mLooper.wake(); }
    int pollAll(int timeoutMillis) final { return mLooper.pollAll(timeoutMillis); }

private:
    struct Looper : public android::Looper {
        Looper() : android::Looper(/*allowNonCallbacks=*/false) {}
        ~Looper() {}
    } mLooper;
};

std::string IncFsWrapper::toString(FileId fileId) {
    return incfs::toString(fileId);
}

class RealIncFs final : public IncFsWrapper {
public:
    RealIncFs() = default;
    ~RealIncFs() final = default;
    Features features() const final { return incfs::features(); }
    void listExistingMounts(const ExistingMountCallback& cb) const final {
        for (auto mount : incfs::defaultMountRegistry().copyMounts()) {
            auto binds = mount.binds(); // span() doesn't like rvalue containers, needs to save it.
            cb(mount.root(), mount.backingDir(), binds);
        }
    }
    Control openMount(std::string_view path) const final { return incfs::open(path); }
    Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs,
                          IncFsFd blocksWritten) const final {
        return incfs::createControl(cmd, pendingReads, logs, blocksWritten);
    }
    ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
                       incfs::NewFileParams params) const final {
        return incfs::makeFile(control, path, mode, id, params);
    }
    ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
                             incfs::NewMappedFileParams params) const final {
        return incfs::makeMappedFile(control, path, mode, params);
    }
    ErrorCode makeDir(const Control& control, std::string_view path, int mode) const final {
        return incfs::makeDir(control, path, mode);
    }
    ErrorCode makeDirs(const Control& control, std::string_view path, int mode) const final {
        return incfs::makeDirs(control, path, mode);
    }
    incfs::RawMetadata getMetadata(const Control& control, FileId fileid) const final {
        return incfs::getMetadata(control, fileid);
    }
    incfs::RawMetadata getMetadata(const Control& control, std::string_view path) const final {
        return incfs::getMetadata(control, path);
    }
    FileId getFileId(const Control& control, std::string_view path) const final {
        return incfs::getFileId(control, path);
    }
    std::pair<IncFsBlockIndex, IncFsBlockIndex> countFilledBlocks(
            const Control& control, std::string_view path) const final {
        if (incfs::features() & Features::v2) {
            const auto counts = incfs::getBlockCount(control, path);
            if (!counts) {
                return {-errno, -errno};
            }
            return {counts->filledDataBlocks + counts->filledHashBlocks,
                    counts->totalDataBlocks + counts->totalHashBlocks};
        }
        const auto fileId = incfs::getFileId(control, path);
        const auto fd = incfs::openForSpecialOps(control, fileId);
        int res = fd.get();
        if (!fd.ok()) {
            return {res, res};
        }
        const auto ranges = incfs::getFilledRanges(res);
        res = ranges.first;
        if (res) {
            return {res, res};
        }
        const auto totalBlocksCount = ranges.second.internalRawRanges().endIndex;
        int filledBlockCount = 0;
        for (const auto& dataRange : ranges.second.dataRanges()) {
            filledBlockCount += dataRange.size();
        }
        for (const auto& hashRange : ranges.second.hashRanges()) {
            filledBlockCount += hashRange.size();
        }
        return {filledBlockCount, totalBlocksCount};
    }
    incfs::LoadingState isFileFullyLoaded(const Control& control,
                                          std::string_view path) const final {
        return incfs::isFullyLoaded(control, path);
    }
    incfs::LoadingState isFileFullyLoaded(const Control& control, FileId id) const final {
        return incfs::isFullyLoaded(control, id);
    }
    incfs::LoadingState isEverythingFullyLoaded(const Control& control) const final {
        return incfs::isEverythingFullyLoaded(control);
    }
    ErrorCode link(const Control& control, std::string_view from, std::string_view to) const final {
        return incfs::link(control, from, to);
    }
    ErrorCode unlink(const Control& control, std::string_view path) const final {
        return incfs::unlink(control, path);
    }
    incfs::UniqueFd openForSpecialOps(const Control& control, FileId id) const final {
        return incfs::openForSpecialOps(control, id);
    }
    ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const final {
        return incfs::writeBlocks({blocks.data(), size_t(blocks.size())});
    }
    ErrorCode reserveSpace(const Control& control, FileId id, IncFsSize size) const final {
        return incfs::reserveSpace(control, id, size);
    }
    WaitResult waitForPendingReads(
            const Control& control, std::chrono::milliseconds timeout,
            std::vector<incfs::ReadInfoWithUid>* pendingReadsBuffer) const final {
        return incfs::waitForPendingReads(control, timeout, pendingReadsBuffer);
    }
    ErrorCode setUidReadTimeouts(const Control& control,
                                 const std::vector<android::os::incremental::PerUidReadTimeouts>&
                                         perUidReadTimeouts) const final {
        std::vector<incfs::UidReadTimeouts> timeouts(perUidReadTimeouts.size());
        for (int i = 0, size = perUidReadTimeouts.size(); i < size; ++i) {
            auto& timeout = timeouts[i];
            const auto& perUidTimeout = perUidReadTimeouts[i];
            timeout.uid = perUidTimeout.uid;
            timeout.minTimeUs = perUidTimeout.minTimeUs;
            timeout.minPendingTimeUs = perUidTimeout.minPendingTimeUs;
            timeout.maxPendingTimeUs = perUidTimeout.maxPendingTimeUs;
        }
        return incfs::setUidReadTimeouts(control, timeouts);
    }
    ErrorCode forEachFile(const Control& control, FileCallback cb) const final {
        return incfs::forEachFile(control,
                                  [&](auto& control, FileId id) { return cb(control, id); });
    }
    ErrorCode forEachIncompleteFile(const Control& control, FileCallback cb) const final {
        return incfs::forEachIncompleteFile(control, [&](auto& control, FileId id) {
            return cb(control, id);
        });
    }
    std::optional<Metrics> getMetrics(std::string_view sysfsName) const final {
        return incfs::getMetrics(sysfsName);
    }
    std::optional<LastReadError> getLastReadError(const Control& control) const final {
        return incfs::getLastReadError(control);
    }
};

static JNIEnv* getOrAttachJniEnv(JavaVM* jvm);

class RealTimedQueueWrapper final : public TimedQueueWrapper {
public:
    RealTimedQueueWrapper(JavaVM* jvm) {
        mThread = std::thread([this, jvm]() {
            (void)getOrAttachJniEnv(jvm);
            runTimers();
        });
    }
    ~RealTimedQueueWrapper() final {
        CHECK(!mRunning) << "call stop first";
        CHECK(!mThread.joinable()) << "call stop first";
    }

    void addJob(MountId id, Milliseconds timeout, Job what) final {
        const auto now = Clock::now();
        {
            std::unique_lock lock(mMutex);
            mJobs.insert(TimedJob{id, now + timeout, std::move(what)});
        }
        mCondition.notify_all();
    }
    void removeJobs(MountId id) final {
        std::unique_lock lock(mMutex);
        std::erase_if(mJobs, [id](auto&& item) { return item.id == id; });
    }
    void stop() final {
        {
            std::unique_lock lock(mMutex);
            mRunning = false;
        }
        mCondition.notify_all();
        mThread.join();
        mJobs.clear();
    }

private:
    void runTimers() {
        static constexpr TimePoint kInfinityTs{Clock::duration::max()};
        std::unique_lock lock(mMutex);
        for (;;) {
            const TimePoint nextJobTs = mJobs.empty() ? kInfinityTs : mJobs.begin()->when;
            mCondition.wait_until(lock, nextJobTs, [this, oldNextJobTs = nextJobTs]() {
                const auto now = Clock::now();
                const auto newFirstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs;
                return newFirstJobTs <= now || newFirstJobTs < oldNextJobTs || !mRunning;
            });
            if (!mRunning) {
                return;
            }

            const auto now = Clock::now();
            // Always re-acquire begin(). We can't use it after unlock as mTimedJobs can change.
            for (auto it = mJobs.begin(); it != mJobs.end() && it->when <= now;
                 it = mJobs.begin()) {
                auto jobNode = mJobs.extract(it);

                lock.unlock();
                jobNode.value().what();
                lock.lock();
            }
        }
    }

    struct TimedJob {
        MountId id;
        TimePoint when;
        Job what;
        friend bool operator<(const TimedJob& lhs, const TimedJob& rhs) {
            return lhs.when < rhs.when;
        }
    };
    bool mRunning = true;
    std::multiset<TimedJob> mJobs;
    std::condition_variable mCondition;
    std::mutex mMutex;
    std::thread mThread;
};

class RealFsWrapper final : public FsWrapper {
public:
    RealFsWrapper() = default;
    ~RealFsWrapper() = default;

    void listFilesRecursive(std::string_view directoryPath, FileCallback onFile) const final {
        for (const auto& entry : std::filesystem::recursive_directory_iterator(directoryPath)) {
            if (!entry.is_regular_file()) {
                continue;
            }
            if (!onFile(entry.path().native())) {
                break;
            }
        }
    }
};

class RealClockWrapper final : public ClockWrapper {
public:
    RealClockWrapper() = default;
    ~RealClockWrapper() = default;

    TimePoint now() const final { return Clock::now(); }
};

RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager, JNIEnv* env)
      : mServiceManager(std::move(serviceManager)), mJvm(RealJniWrapper::getJvm(env)) {}

template <class INTERFACE>
sp<INTERFACE> RealServiceManager::getRealService(std::string_view serviceName) const {
    sp<IBinder> binder =
            mServiceManager->getService(String16(serviceName.data(), serviceName.size()));
    if (!binder) {
        return nullptr;
    }
    return interface_cast<INTERFACE>(binder);
}

std::unique_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() {
    sp<os::IVold> vold = RealServiceManager::getRealService<os::IVold>(kVoldServiceName);
    if (vold != 0) {
        return std::make_unique<RealVoldService>(vold);
    }
    return nullptr;
}

std::unique_ptr<DataLoaderManagerWrapper> RealServiceManager::getDataLoaderManager() {
    sp<content::pm::IDataLoaderManager> manager =
            RealServiceManager::getRealService<content::pm::IDataLoaderManager>(
                    kDataLoaderManagerName);
    if (manager) {
        return std::make_unique<RealDataLoaderManager>(manager);
    }
    return nullptr;
}

std::unique_ptr<IncFsWrapper> RealServiceManager::getIncFs() {
    return std::make_unique<RealIncFs>();
}

std::unique_ptr<AppOpsManagerWrapper> RealServiceManager::getAppOpsManager() {
    return std::make_unique<RealAppOpsManager>();
}

std::unique_ptr<JniWrapper> RealServiceManager::getJni() {
    return std::make_unique<RealJniWrapper>(mJvm);
}

std::unique_ptr<LooperWrapper> RealServiceManager::getLooper() {
    return std::make_unique<RealLooperWrapper>();
}

std::unique_ptr<TimedQueueWrapper> RealServiceManager::getTimedQueue() {
    return std::make_unique<RealTimedQueueWrapper>(mJvm);
}

std::unique_ptr<TimedQueueWrapper> RealServiceManager::getProgressUpdateJobQueue() {
    return std::make_unique<RealTimedQueueWrapper>(mJvm);
}

std::unique_ptr<FsWrapper> RealServiceManager::getFs() {
    return std::make_unique<RealFsWrapper>();
}

std::unique_ptr<ClockWrapper> RealServiceManager::getClock() {
    return std::make_unique<RealClockWrapper>();
}

static JavaVM* getJavaVm(JNIEnv* env) {
    CHECK(env);
    JavaVM* jvm = nullptr;
    env->GetJavaVM(&jvm);
    CHECK(jvm);
    return jvm;
}

static JNIEnv* getJniEnv(JavaVM* vm) {
    JNIEnv* env;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return nullptr;
    }
    return env;
}

static JNIEnv* getOrAttachJniEnv(JavaVM* jvm) {
    if (!jvm) {
        LOG(ERROR) << "No JVM instance";
        return nullptr;
    }

    JNIEnv* env = getJniEnv(jvm);
    if (!env) {
        int result = jvm->AttachCurrentThread(&env, nullptr);
        if (result != JNI_OK) {
            LOG(ERROR) << "JVM thread attach failed: " << result;
            return nullptr;
        }
        struct VmDetacher {
            VmDetacher(JavaVM* vm) : mVm(vm) {}
            ~VmDetacher() { mVm->DetachCurrentThread(); }

        private:
            JavaVM* const mVm;
        };
        static thread_local VmDetacher detacher(jvm);
    }

    return env;
}

RealJniWrapper::RealJniWrapper(JavaVM* jvm) : mJvm(jvm) {
    CHECK(!!mJvm) << "JVM is unavailable";
}

void RealJniWrapper::initializeForCurrentThread() const {
    (void)getOrAttachJniEnv(mJvm);
}

JavaVM* RealJniWrapper::getJvm(JNIEnv* env) {
    return getJavaVm(env);
}

} // namespace android::incremental
