/*
 * 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.
 */

#include "BinderIncrementalService.h"

#include <android-base/logging.h>
#include <android-base/no_destructor.h>
#include <android/os/IVold.h>
#include <binder/IResultReceiver.h>
#include <binder/PermissionCache.h>
#include <incfs.h>

#include "ServiceWrappers.h"
#include "jni.h"
#include "path.h"

using namespace std::literals;
using namespace android::incremental;

namespace android::os::incremental {

static constexpr auto kAndroidDataEnv = "ANDROID_DATA"sv;
static constexpr auto kDataDir = "/data"sv;
static constexpr auto kIncrementalSubDir = "incremental"sv;

static std::string getIncrementalDir() {
    const char* dataDir = getenv(kAndroidDataEnv.data());
    if (!dataDir || !*dataDir) {
        dataDir = kDataDir.data();
    }
    return path::normalize(path::join(dataDir, kIncrementalSubDir));
}

static bool incFsEnabled() {
    // TODO(b/136132412): use vold to check /sys/fs/incfs/version (per selinux compliance)
    return incfs::enabled();
}

static bool incFsValid(const sp<IVold>& vold) {
    bool enabled = false;
    auto status = vold->incFsEnabled(&enabled);
    if (!status.isOk() || !enabled) {
        return false;
    }
    return true;
}

BinderIncrementalService::BinderIncrementalService(const sp<IServiceManager>& sm, JNIEnv* env)
      : mImpl(RealServiceManager(sm, env), getIncrementalDir()) {}

BinderIncrementalService* BinderIncrementalService::start(JNIEnv* env) {
    if (!incFsEnabled()) {
        return nullptr;
    }

    IPCThreadState::self()->disableBackgroundScheduling(true);
    sp<IServiceManager> sm(defaultServiceManager());
    if (!sm) {
        return nullptr;
    }

    sp<IBinder> voldBinder(sm->getService(String16("vold")));
    if (voldBinder == nullptr) {
        return nullptr;
    }
    sp<IVold> vold = interface_cast<IVold>(voldBinder);
    if (!incFsValid(vold)) {
        return nullptr;
    }

    sp<BinderIncrementalService> self(new BinderIncrementalService(sm, env));
    status_t ret = sm->addService(String16{getServiceName()}, self);
    if (ret != android::OK) {
        return nullptr;
    }
    sp<ProcessState> ps(ProcessState::self());
    ps->startThreadPool();
    // sm->addService increments the reference count, and now we're OK with returning the pointer.
    return self.get();
}

status_t BinderIncrementalService::dump(int fd, const Vector<String16>&) {
    static const android::base::NoDestructor<String16> kDump("android.permission.DUMP");
    if (!PermissionCache::checkCallingPermission(*kDump)) {
        return PERMISSION_DENIED;
    }
    mImpl.onDump(fd);
    return NO_ERROR;
}

void BinderIncrementalService::onSystemReady() {
    mImpl.onSystemReady();
}

static binder::Status ok() {
    return binder::Status::ok();
}

binder::Status BinderIncrementalService::openStorage(const std::string& path,
                                                     int32_t* _aidl_return) {
    *_aidl_return = mImpl.openStorage(path);
    return ok();
}

binder::Status BinderIncrementalService::createStorage(
        const ::std::string& path, const ::android::content::pm::DataLoaderParamsParcel& params,
        int32_t createMode, int32_t* _aidl_return) {
    *_aidl_return =
            mImpl.createStorage(path, const_cast<content::pm::DataLoaderParamsParcel&&>(params),
                                android::incremental::IncrementalService::CreateOptions(
                                        createMode));
    return ok();
}

binder::Status BinderIncrementalService::createLinkedStorage(const std::string& path,
                                                             int32_t otherStorageId,
                                                             int32_t createMode,
                                                             int32_t* _aidl_return) {
    *_aidl_return =
            mImpl.createLinkedStorage(path, otherStorageId,
                                      android::incremental::IncrementalService::CreateOptions(
                                              createMode));
    return ok();
}

binder::Status BinderIncrementalService::startLoading(
        int32_t storageId, const ::android::content::pm::DataLoaderParamsParcel& params,
        const ::android::sp<::android::content::pm::IDataLoaderStatusListener>& statusListener,
        const ::android::os::incremental::StorageHealthCheckParams& healthCheckParams,
        const ::android::sp<IStorageHealthListener>& healthListener,
        const ::std::vector<::android::os::incremental::PerUidReadTimeouts>& perUidReadTimeouts,
        bool* _aidl_return) {
    *_aidl_return =
            mImpl.startLoading(storageId, const_cast<content::pm::DataLoaderParamsParcel&&>(params),
                               statusListener, healthCheckParams, healthListener,
                               perUidReadTimeouts);
    return ok();
}

binder::Status BinderIncrementalService::onInstallationComplete(int32_t storageId) {
    mImpl.onInstallationComplete(storageId);
    return ok();
}

binder::Status BinderIncrementalService::makeBindMount(int32_t storageId,
                                                       const std::string& sourcePath,
                                                       const std::string& targetFullPath,
                                                       int32_t bindType, int32_t* _aidl_return) {
    *_aidl_return = mImpl.bind(storageId, sourcePath, targetFullPath,
                               android::incremental::IncrementalService::BindKind(bindType));
    return ok();
}

binder::Status BinderIncrementalService::deleteBindMount(int32_t storageId,
                                                         const std::string& targetFullPath,
                                                         int32_t* _aidl_return) {
    *_aidl_return = mImpl.unbind(storageId, targetFullPath);
    return ok();
}

binder::Status BinderIncrementalService::deleteStorage(int32_t storageId) {
    mImpl.deleteStorage(storageId);
    return ok();
}

binder::Status BinderIncrementalService::disallowReadLogs(int32_t storageId) {
    mImpl.disallowReadLogs(storageId);
    return ok();
}

binder::Status BinderIncrementalService::makeDirectory(int32_t storageId, const std::string& path,
                                                       int32_t* _aidl_return) {
    *_aidl_return = mImpl.makeDir(storageId, path);
    return ok();
}

static std::tuple<int, incfs::FileId, incfs::NewFileParams> toMakeFileParams(
        const android::os::incremental::IncrementalNewFileParams& params) {
    incfs::FileId id;
    if (params.fileId.empty()) {
        if (params.metadata.empty()) {
            return {EINVAL, {}, {}};
        }
        id = IncrementalService::idFromMetadata(params.metadata);
    } else if (params.fileId.size() != sizeof(id)) {
        return {EINVAL, {}, {}};
    } else {
        memcpy(&id, params.fileId.data(), sizeof(id));
    }
    incfs::NewFileParams nfp;
    nfp.size = params.size;
    nfp.metadata = {(const char*)params.metadata.data(), (IncFsSize)params.metadata.size()};
    if (!params.signature) {
        nfp.signature = {};
    } else {
        nfp.signature = {(const char*)params.signature->data(),
                         (IncFsSize)params.signature->size()};
    }
    return {0, id, nfp};
}

static std::span<const uint8_t> toSpan(const ::std::optional<::std::vector<uint8_t>>& content) {
    if (!content) {
        return {};
    }
    return {content->data(), (int)content->size()};
}

binder::Status BinderIncrementalService::makeFile(
        int32_t storageId, const std::string& path,
        const ::android::os::incremental::IncrementalNewFileParams& params,
        const ::std::optional<::std::vector<uint8_t>>& content, int32_t* _aidl_return) {
    auto [err, fileId, nfp] = toMakeFileParams(params);
    if (err) {
        *_aidl_return = err;
        return ok();
    }

    *_aidl_return = mImpl.makeFile(storageId, path, 0777, fileId, nfp, toSpan(content));
    return ok();
}
binder::Status BinderIncrementalService::makeFileFromRange(int32_t storageId,
                                                           const std::string& targetPath,
                                                           const std::string& sourcePath,
                                                           int64_t start, int64_t end,
                                                           int32_t* _aidl_return) {
    // TODO(b/136132412): implement this
    *_aidl_return = ENOSYS; // not implemented
    return ok();
}

binder::Status BinderIncrementalService::makeLink(int32_t sourceStorageId,
                                                  const std::string& sourcePath,
                                                  int32_t destStorageId,
                                                  const std::string& destPath,
                                                  int32_t* _aidl_return) {
    *_aidl_return = mImpl.link(sourceStorageId, sourcePath, destStorageId, destPath);
    return ok();
}

binder::Status BinderIncrementalService::unlink(int32_t storageId, const std::string& path,
                                                int32_t* _aidl_return) {
    *_aidl_return = mImpl.unlink(storageId, path);
    return ok();
}

binder::Status BinderIncrementalService::isFileFullyLoaded(int32_t storageId,
                                                           const std::string& path,
                                                           int32_t* _aidl_return) {
    *_aidl_return = (int)mImpl.isFileFullyLoaded(storageId, path);
    return ok();
}

binder::Status BinderIncrementalService::isFullyLoaded(int32_t storageId, int32_t* _aidl_return) {
    *_aidl_return = (int)mImpl.isMountFullyLoaded(storageId);
    return ok();
}

binder::Status BinderIncrementalService::getLoadingProgress(int32_t storageId,
                                                            float* _aidl_return) {
    *_aidl_return = mImpl.getLoadingProgress(storageId).getProgress();
    return ok();
}

binder::Status BinderIncrementalService::getMetadataByPath(int32_t storageId,
                                                           const std::string& path,
                                                           std::vector<uint8_t>* _aidl_return) {
    auto metadata = mImpl.getMetadata(storageId, path);
    _aidl_return->assign(metadata.begin(), metadata.end());
    return ok();
}

static FileId toFileId(const std::vector<uint8_t>& id) {
    FileId fid = {};
    memcpy(&fid, id.data(), std::min(sizeof(fid), id.size()));
    return fid;
}

binder::Status BinderIncrementalService::getMetadataById(int32_t storageId,
                                                         const std::vector<uint8_t>& id,
                                                         std::vector<uint8_t>* _aidl_return) {
    if (id.size() != sizeof(incfs::FileId)) {
        return ok();
    }
    auto fid = toFileId(id);
    auto metadata = mImpl.getMetadata(storageId, fid);
    _aidl_return->assign(metadata.begin(), metadata.end());
    return ok();
}

binder::Status BinderIncrementalService::makeDirectories(int32_t storageId, const std::string& path,
                                                         int32_t* _aidl_return) {
    *_aidl_return = mImpl.makeDirs(storageId, path);
    return ok();
}

binder::Status BinderIncrementalService::configureNativeBinaries(
        int32_t storageId, const std::string& apkFullPath, const std::string& libDirRelativePath,
        const std::string& abi, bool extractNativeLibs, bool* _aidl_return) {
    *_aidl_return = mImpl.configureNativeBinaries(storageId, apkFullPath, libDirRelativePath, abi,
                                                  extractNativeLibs);
    return ok();
}

binder::Status BinderIncrementalService::waitForNativeBinariesExtraction(int storageId,
                                                                         bool* _aidl_return) {
    *_aidl_return = mImpl.waitForNativeBinariesExtraction(storageId);
    return ok();
}

binder::Status BinderIncrementalService::registerLoadingProgressListener(
        int32_t storageId,
        const ::android::sp<::android::os::incremental::IStorageLoadingProgressListener>&
                progressListener,
        bool* _aidl_return) {
    *_aidl_return = mImpl.registerLoadingProgressListener(storageId, progressListener);
    return ok();
}
binder::Status BinderIncrementalService::unregisterLoadingProgressListener(int32_t storageId,
                                                                           bool* _aidl_return) {
    *_aidl_return = mImpl.unregisterLoadingProgressListener(storageId);
    return ok();
}

binder::Status BinderIncrementalService::getMetrics(int32_t storageId,
                                                    android::os::PersistableBundle* _aidl_return) {
    mImpl.getMetrics(storageId, _aidl_return);
    return ok();
}

} // namespace android::os::incremental

jlong Incremental_IncrementalService_Start(JNIEnv* env) {
    return (jlong)android::os::incremental::BinderIncrementalService::start(env);
}
void Incremental_IncrementalService_OnSystemReady(jlong self) {
    if (self) {
        ((android::os::incremental::BinderIncrementalService*)self)->onSystemReady();
    }
}
void Incremental_IncrementalService_OnDump(jlong self, jint fd) {
    if (self) {
        ((android::os::incremental::BinderIncrementalService*)self)->dump(fd, {});
    } else {
        dprintf(fd, "BinderIncrementalService is stopped.");
    }
}
