/*
 * Copyright (C) 2015 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 "IdleMaint.h"
#include "FileDeviceUtils.h"
#include "Utils.h"
#include "VoldUtil.h"
#include "VolumeManager.h"
#include "model/PrivateVolume.h"

#include <thread>
#include <utility>

#include <aidl/android/hardware/health/storage/BnGarbageCollectCallback.h>
#include <aidl/android/hardware/health/storage/IStorage.h>
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android/binder_manager.h>
#include <android/hardware/health/storage/1.0/IStorage.h>
#include <fs_mgr.h>
#include <private/android_filesystem_config.h>
#include <wakelock/wakelock.h>

#include <dirent.h>
#include <fcntl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>

using android::base::Basename;
using android::base::ReadFileToString;
using android::base::Realpath;
using android::base::StringPrintf;
using android::base::Timer;
using android::base::WriteStringToFile;
using android::hardware::Return;
using android::hardware::Void;
using AStorage = aidl::android::hardware::health::storage::IStorage;
using ABnGarbageCollectCallback =
        aidl::android::hardware::health::storage::BnGarbageCollectCallback;
using AResult = aidl::android::hardware::health::storage::Result;
using HStorage = android::hardware::health::storage::V1_0::IStorage;
using HGarbageCollectCallback = android::hardware::health::storage::V1_0::IGarbageCollectCallback;
using HResult = android::hardware::health::storage::V1_0::Result;
using std::string_literals::operator""s;

namespace android {
namespace vold {

enum class PathTypes {
    kMountPoint = 1,
    kBlkDevice,
};

enum class IdleMaintStats {
    kStopped = 1,
    kRunning,
    kAbort,
};

static const char* kWakeLock = "IdleMaint";
static const int DIRTY_SEGMENTS_THRESHOLD = 100;
/*
 * Timing policy:
 *  1. F2FS_GC = 7 mins
 *  2. Trim = 1 min
 *  3. Dev GC = 2 mins
 */
static const int GC_TIMEOUT_SEC = 420;
static const int DEVGC_TIMEOUT_SEC = 120;
static const int KBYTES_IN_SEGMENT = 2048;
static const int MIN_GC_URGENT_SLEEP_TIME = 500;
static const int ONE_MINUTE_IN_MS = 60000;
static const int GC_NORMAL_MODE = 0;
static const int GC_URGENT_MID_MODE = 3;

static int32_t previousSegmentWrite = 0;

static IdleMaintStats idle_maint_stat(IdleMaintStats::kStopped);
static std::condition_variable cv_abort, cv_stop;
static std::mutex cv_m;

static void addFromVolumeManager(std::list<std::string>* paths, PathTypes path_type) {
    VolumeManager* vm = VolumeManager::Instance();
    std::list<std::string> privateIds;
    vm->listVolumes(VolumeBase::Type::kPrivate, privateIds);
    for (const auto& id : privateIds) {
        PrivateVolume* vol = static_cast<PrivateVolume*>(vm->findVolume(id).get());
        if (vol != nullptr && vol->getState() == VolumeBase::State::kMounted) {
            if (path_type == PathTypes::kMountPoint) {
                paths->push_back(vol->getPath());
            } else if (path_type == PathTypes::kBlkDevice) {
                std::string gc_path;
                const std::string& fs_type = vol->getFsType();
                if (fs_type == "f2fs" && (Realpath(vol->getRawDmDevPath(), &gc_path) ||
                                          Realpath(vol->getRawDevPath(), &gc_path))) {
                    paths->push_back(std::string("/sys/fs/") + fs_type + "/" + Basename(gc_path));
                }
            }
        }
    }
}

static void addFromFstab(std::list<std::string>* paths, PathTypes path_type, bool only_data_part) {
    std::string previous_mount_point;
    for (const auto& entry : fstab_default) {
        // Skip raw partitions and swap space.
        if (entry.fs_type == "emmc" || entry.fs_type == "mtd" || entry.fs_type == "swap") {
            continue;
        }
        // Skip read-only filesystems and bind mounts.
        if (entry.flags & (MS_RDONLY | MS_BIND)) {
            continue;
        }
        // Skip anything without an underlying block device, e.g. virtiofs.
        if (entry.blk_device[0] != '/') {
            continue;
        }
        if (entry.fs_mgr_flags.vold_managed) {
            continue;  // Should we trim fat32 filesystems?
        }
        if (entry.fs_mgr_flags.no_trim) {
            continue;
        }

        if (only_data_part && entry.mount_point != "/data") {
            continue;
        }

        // Skip the multi-type partitions, which are required to be following each other.
        // See fs_mgr.c's mount_with_alternatives().
        if (entry.mount_point == previous_mount_point) {
            continue;
        }

        if (path_type == PathTypes::kMountPoint) {
            paths->push_back(entry.mount_point);
        } else if (path_type == PathTypes::kBlkDevice) {
            std::string path;
            if (entry.fs_type == "f2fs" &&
                Realpath(android::vold::BlockDeviceForPath(entry.mount_point + "/"), &path)) {
                paths->push_back("/sys/fs/" + entry.fs_type + "/" + Basename(path));
            }
        }

        previous_mount_point = entry.mount_point;
    }
}

void Trim(const android::sp<android::os::IVoldTaskListener>& listener) {
    auto wl = android::wakelock::WakeLock::tryGet(kWakeLock);
    if (!wl.has_value()) {
        return;
    }

    // Collect both fstab and vold volumes
    std::list<std::string> paths;
    addFromFstab(&paths, PathTypes::kMountPoint, false);
    addFromVolumeManager(&paths, PathTypes::kMountPoint);

    for (const auto& path : paths) {
        LOG(DEBUG) << "Starting trim of " << path;

        android::os::PersistableBundle extras;
        extras.putString(String16("path"), String16(path.c_str()));

        int fd = open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
        if (fd < 0) {
            PLOG(WARNING) << "Failed to open " << path;
            if (listener) {
                listener->onStatus(-1, extras);
            }
            continue;
        }

        struct fstrim_range range;
        memset(&range, 0, sizeof(range));
        range.len = ULLONG_MAX;

        nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
        if (ioctl(fd, FITRIM, &range)) {
            PLOG(WARNING) << "Trim failed on " << path;
            if (listener) {
                listener->onStatus(-1, extras);
            }
        } else {
            nsecs_t time = systemTime(SYSTEM_TIME_BOOTTIME) - start;
            LOG(INFO) << "Trimmed " << range.len << " bytes on " << path << " in "
                      << nanoseconds_to_milliseconds(time) << "ms";
            extras.putLong(String16("bytes"), range.len);
            extras.putLong(String16("time"), time);
            if (listener) {
                listener->onStatus(0, extras);
            }
        }
        close(fd);
    }

    if (listener) {
        android::os::PersistableBundle extras;
        listener->onFinished(0, extras);
    }

}

static bool waitForGc(const std::list<std::string>& paths) {
    std::unique_lock<std::mutex> lk(cv_m, std::defer_lock);
    bool stop = false, aborted = false;
    Timer timer;

    while (!stop && !aborted) {
        stop = true;
        for (const auto& path : paths) {
            std::string dirty_segments;
            if (!ReadFileToString(path + "/dirty_segments", &dirty_segments)) {
                PLOG(WARNING) << "Reading dirty_segments failed in " << path;
                continue;
            }
            if (std::stoi(dirty_segments) > DIRTY_SEGMENTS_THRESHOLD) {
                stop = false;
                break;
            }
        }

        if (stop) break;

        if (timer.duration() >= std::chrono::seconds(GC_TIMEOUT_SEC)) {
            LOG(WARNING) << "GC timeout";
            break;
        }

        lk.lock();
        aborted =
            cv_abort.wait_for(lk, 10s, [] { return idle_maint_stat == IdleMaintStats::kAbort; });
        lk.unlock();
    }

    return aborted;
}

static int startGc(const std::list<std::string>& paths) {
    for (const auto& path : paths) {
        LOG(DEBUG) << "Start GC on " << path;
        if (!WriteStringToFile("1", path + "/gc_urgent")) {
            PLOG(WARNING) << "Start GC failed on " << path;
        }
    }
    return android::OK;
}

static int stopGc(const std::list<std::string>& paths) {
    for (const auto& path : paths) {
        LOG(DEBUG) << "Stop GC on " << path;
        if (!WriteStringToFile("0", path + "/gc_urgent")) {
            PLOG(WARNING) << "Stop GC failed on " << path;
        }
    }
    return android::OK;
}

static std::string getDevSysfsPath() {
    for (const auto& entry : fstab_default) {
        if (!entry.sysfs_path.empty()) {
            return entry.sysfs_path;
        }
    }
    LOG(WARNING) << "Cannot find dev sysfs path";
    return "";
}

static void runDevGcFstab(void) {
    std::string path = getDevSysfsPath();
    if (path.empty()) {
        return;
    }

    path = path + "/manual_gc";
    Timer timer;

    LOG(DEBUG) << "Start Dev GC on " << path;
    while (1) {
        std::string require;
        if (!ReadFileToString(path, &require)) {
            PLOG(WARNING) << "Reading manual_gc failed in " << path;
            break;
        }
        require = android::base::Trim(require);
        if (require == "" || require == "off" || require == "disabled") {
            LOG(DEBUG) << "No more to do Dev GC";
            break;
        }

        LOG(DEBUG) << "Trigger Dev GC on " << path;
        if (!WriteStringToFile("1", path)) {
            PLOG(WARNING) << "Start Dev GC failed on " << path;
            break;
        }

        if (timer.duration() >= std::chrono::seconds(DEVGC_TIMEOUT_SEC)) {
            LOG(WARNING) << "Dev GC timeout";
            break;
        }
        sleep(2);
    }
    LOG(DEBUG) << "Stop Dev GC on " << path;
    if (!WriteStringToFile("0", path)) {
        PLOG(WARNING) << "Stop Dev GC failed on " << path;
    }
    return;
}

enum class IDL { HIDL, AIDL };
std::ostream& operator<<(std::ostream& os, IDL idl) {
    return os << (idl == IDL::HIDL ? "HIDL" : "AIDL");
}

template <IDL idl, typename Result>
class GcCallbackImpl {
  protected:
    void onFinishInternal(Result result) {
        std::unique_lock<std::mutex> lock(mMutex);
        mFinished = true;
        mResult = result;
        lock.unlock();
        mCv.notify_all();
    }

  public:
    void wait(uint64_t seconds) {
        std::unique_lock<std::mutex> lock(mMutex);
        mCv.wait_for(lock, std::chrono::seconds(seconds), [this] { return mFinished; });

        if (!mFinished) {
            LOG(WARNING) << "Dev GC on " << idl << " HAL timeout";
        } else if (mResult != Result::SUCCESS) {
            LOG(WARNING) << "Dev GC on " << idl << " HAL failed with " << toString(mResult);
        } else {
            LOG(INFO) << "Dev GC on " << idl << " HAL successful";
        }
    }

  private:
    std::mutex mMutex;
    std::condition_variable mCv;
    bool mFinished{false};
    Result mResult{Result::UNKNOWN_ERROR};
};

class AGcCallbackImpl : public ABnGarbageCollectCallback,
                        public GcCallbackImpl<IDL::AIDL, AResult> {
    ndk::ScopedAStatus onFinish(AResult result) override {
        onFinishInternal(result);
        return ndk::ScopedAStatus::ok();
    }
};

class HGcCallbackImpl : public HGarbageCollectCallback, public GcCallbackImpl<IDL::HIDL, HResult> {
    Return<void> onFinish(HResult result) override {
        onFinishInternal(result);
        return Void();
    }
};

template <IDL idl, typename Service, typename GcCallbackImpl, typename GetDescription>
static void runDevGcOnHal(Service service, GcCallbackImpl cb, GetDescription get_description) {
    LOG(DEBUG) << "Start Dev GC on " << idl << " HAL";
    auto ret = service->garbageCollect(DEVGC_TIMEOUT_SEC, cb);
    if (!ret.isOk()) {
        LOG(WARNING) << "Cannot start Dev GC on " << idl
                     << " HAL: " << std::invoke(get_description, ret);
        return;
    }
    cb->wait(DEVGC_TIMEOUT_SEC);
}

static void runDevGc(void) {
    auto aidl_service_name = AStorage::descriptor + "/default"s;
    if (AServiceManager_isDeclared(aidl_service_name.c_str())) {
        ndk::SpAIBinder binder(AServiceManager_waitForService(aidl_service_name.c_str()));
        if (binder.get() != nullptr) {
            std::shared_ptr<AStorage> aidl_service = AStorage::fromBinder(binder);
            if (aidl_service != nullptr) {
                runDevGcOnHal<IDL::AIDL>(aidl_service, ndk::SharedRefBase::make<AGcCallbackImpl>(),
                                         &ndk::ScopedAStatus::getDescription);
                return;
            }
        }
        LOG(WARNING) << "Device declares " << aidl_service_name
                     << " but it is not running, skip dev GC on AIDL HAL";
        return;
    }
    auto hidl_service = HStorage::getService();
    if (hidl_service != nullptr) {
        runDevGcOnHal<IDL::HIDL>(hidl_service, sp<HGcCallbackImpl>(new HGcCallbackImpl()),
                                 &Return<void>::description);
        return;
    }
    // fallback to legacy code path
    runDevGcFstab();
}

int RunIdleMaint(bool needGC, const android::sp<android::os::IVoldTaskListener>& listener) {
    std::unique_lock<std::mutex> lk(cv_m);
    bool gc_aborted = false;

    if (idle_maint_stat != IdleMaintStats::kStopped) {
        LOG(DEBUG) << "idle maintenance is already running";
        if (listener) {
            android::os::PersistableBundle extras;
            listener->onFinished(0, extras);
        }
        return android::OK;
    }
    idle_maint_stat = IdleMaintStats::kRunning;
    lk.unlock();

    LOG(DEBUG) << "idle maintenance started";

    auto wl = android::wakelock::WakeLock::tryGet(kWakeLock);
    if (!wl.has_value()) {
        return android::UNEXPECTED_NULL;
    }

    if (needGC) {
        std::list<std::string> paths;
        addFromFstab(&paths, PathTypes::kBlkDevice, false);
        addFromVolumeManager(&paths, PathTypes::kBlkDevice);

        startGc(paths);

        gc_aborted = waitForGc(paths);

        stopGc(paths);
    }

    lk.lock();
    idle_maint_stat = IdleMaintStats::kStopped;
    lk.unlock();

    cv_stop.notify_one();

    if (!gc_aborted) {
        Trim(nullptr);
        runDevGc();
    }

    if (listener) {
        android::os::PersistableBundle extras;
        listener->onFinished(0, extras);
    }

    LOG(DEBUG) << "idle maintenance completed";

    return android::OK;
}

int AbortIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener) {
    auto wl = android::wakelock::WakeLock::tryGet(kWakeLock);
    if (!wl.has_value()) {
        return android::UNEXPECTED_NULL;
    }

    std::unique_lock<std::mutex> lk(cv_m);
    if (idle_maint_stat != IdleMaintStats::kStopped) {
        idle_maint_stat = IdleMaintStats::kAbort;
        lk.unlock();
        cv_abort.notify_one();
        lk.lock();
        LOG(DEBUG) << "aborting idle maintenance";
        cv_stop.wait(lk, [] { return idle_maint_stat == IdleMaintStats::kStopped; });
    }
    lk.unlock();

    if (listener) {
        android::os::PersistableBundle extras;
        listener->onFinished(0, extras);
    }

    LOG(DEBUG) << "idle maintenance stopped";

    return android::OK;
}

int getLifeTime(const std::string& path) {
    std::string result;

    if (!ReadFileToString(path, &result)) {
        PLOG(WARNING) << "Reading lifetime estimation failed for " << path;
        return -1;
    }
    return std::stoi(result, 0, 16);
}

int32_t GetStorageLifeTime() {
    std::string path = getDevSysfsPath();
    if (path.empty()) {
        return -1;
    }

    std::string lifeTimeBasePath = path + "/health_descriptor/life_time_estimation_";

    int32_t lifeTime = getLifeTime(lifeTimeBasePath + "c");
    if (lifeTime != -1) {
        return lifeTime;
    }

    int32_t lifeTimeA = getLifeTime(lifeTimeBasePath + "a");
    int32_t lifeTimeB = getLifeTime(lifeTimeBasePath + "b");
    lifeTime = std::max(lifeTimeA, lifeTimeB);
    if (lifeTime != -1) {
        return lifeTime == 0 ? -1 : lifeTime * 10;
    }
    return -1;
}

void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate,
                     float reclaimWeight, int32_t gcPeriod) {
    std::list<std::string> paths;
    bool needGC = true;
    int32_t sleepTime;

    addFromFstab(&paths, PathTypes::kBlkDevice, true);
    if (paths.empty()) {
        LOG(WARNING) << "There is no valid blk device path for data partition";
        return;
    }

    std::string f2fsSysfsPath = paths.front();
    std::string freeSegmentsPath = f2fsSysfsPath + "/free_segments";
    std::string dirtySegmentsPath = f2fsSysfsPath + "/dirty_segments";
    std::string gcSleepTimePath = f2fsSysfsPath + "/gc_urgent_sleep_time";
    std::string gcUrgentModePath = f2fsSysfsPath + "/gc_urgent";
    std::string ovpSegmentsPath = f2fsSysfsPath + "/ovp_segments";
    std::string reservedBlocksPath = f2fsSysfsPath + "/reserved_blocks";
    std::string freeSegmentsStr, dirtySegmentsStr, ovpSegmentsStr, reservedBlocksStr;

    if (!ReadFileToString(freeSegmentsPath, &freeSegmentsStr)) {
        PLOG(WARNING) << "Reading failed in " << freeSegmentsPath;
        return;
    }

    if (!ReadFileToString(dirtySegmentsPath, &dirtySegmentsStr)) {
        PLOG(WARNING) << "Reading failed in " << dirtySegmentsPath;
        return;
    }

    if (!ReadFileToString(ovpSegmentsPath, &ovpSegmentsStr)) {
            PLOG(WARNING) << "Reading failed in " << ovpSegmentsPath;
            return;
        }

    if (!ReadFileToString(reservedBlocksPath, &reservedBlocksStr)) {
            PLOG(WARNING) << "Reading failed in " << reservedBlocksPath;
            return;
        }

    int32_t freeSegments = std::stoi(freeSegmentsStr);
    int32_t dirtySegments = std::stoi(dirtySegmentsStr);
    int32_t reservedBlocks = std::stoi(ovpSegmentsStr) + std::stoi(reservedBlocksStr);

    freeSegments = freeSegments > reservedBlocks ? freeSegments - reservedBlocks : 0;
    neededSegments *= reclaimWeight;
    if (freeSegments >= neededSegments) {
        LOG(INFO) << "Enough free segments: " << freeSegments
                   << ", needed segments: " << neededSegments;
        needGC = false;
    } else if (freeSegments + dirtySegments < minSegmentThreshold) {
        LOG(INFO) << "The sum of free segments: " << freeSegments
                   << ", dirty segments: " << dirtySegments << " is under " << minSegmentThreshold;
        needGC = false;
    } else {
        neededSegments -= freeSegments;
        neededSegments = std::min(neededSegments, (int32_t)(dirtySegments * dirtyReclaimRate));
        if (neededSegments == 0) {
            LOG(INFO) << "Low dirty segments: " << dirtySegments;
            needGC = false;
        } else {
            sleepTime = gcPeriod * ONE_MINUTE_IN_MS / neededSegments;
            if (sleepTime < MIN_GC_URGENT_SLEEP_TIME) {
                sleepTime = MIN_GC_URGENT_SLEEP_TIME;
            }
        }
    }

    if (!needGC) {
        if (!WriteStringToFile(std::to_string(GC_NORMAL_MODE), gcUrgentModePath)) {
            PLOG(WARNING) << "Writing failed in " << gcUrgentModePath;
        }
        return;
    }

    if (!WriteStringToFile(std::to_string(sleepTime), gcSleepTimePath)) {
        PLOG(WARNING) << "Writing failed in " << gcSleepTimePath;
        return;
    }

    if (!WriteStringToFile(std::to_string(GC_URGENT_MID_MODE), gcUrgentModePath)) {
        PLOG(WARNING) << "Writing failed in " << gcUrgentModePath;
        return;
    }

    LOG(INFO) << "Successfully set gc urgent mode: "
               << "free segments: " << freeSegments << ", reclaim target: " << neededSegments
               << ", sleep time: " << sleepTime;
}

static int32_t getLifeTimeWrite() {
    std::list<std::string> paths;
    addFromFstab(&paths, PathTypes::kBlkDevice, true);
    if (paths.empty()) {
        LOG(WARNING) << "There is no valid blk device path for data partition";
        return -1;
    }

    std::string writeKbytesPath = paths.front() + "/lifetime_write_kbytes";
    std::string writeKbytesStr;
    if (!ReadFileToString(writeKbytesPath, &writeKbytesStr)) {
        PLOG(WARNING) << "Reading failed in " << writeKbytesPath;
        return -1;
    }

    long long writeBytes = std::stoll(writeKbytesStr);
    return writeBytes / KBYTES_IN_SEGMENT;
}

void RefreshLatestWrite() {
    int32_t segmentWrite = getLifeTimeWrite();
    if (segmentWrite != -1) {
        previousSegmentWrite = segmentWrite;
    }
}

int32_t GetWriteAmount() {
    int32_t currentSegmentWrite = getLifeTimeWrite();
    if (currentSegmentWrite == -1) {
        return -1;
    }

    int32_t writeAmount = currentSegmentWrite - previousSegmentWrite;
    previousSegmentWrite = currentSegmentWrite;
    return writeAmount;
}

}  // namespace vold
}  // namespace android
