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

/*
 * This file is compiled into a single SO file, which we load at the very first.
 * We can do process-wide initialization here.
 * Please be aware that all symbols defined in this SO file will be reloaded
 * as `RTLD_GLOBAL`, so make sure all functions are static except those we EXPLICITLY
 * want to expose and override globally.
 */

#include <dlfcn.h>
#include <fcntl.h>

#include <set>

#include "jni_helper.h"

// Implement a rudimentary system properties data store

#define PROP_VALUE_MAX 92

namespace {

struct prop_info {
    std::string key;
    mutable std::string value;
    mutable uint32_t serial;

    prop_info(const char* key, const char* value) : key(key), value(value), serial(0) {}
};

struct prop_info_cmp {
    using is_transparent = void;
    bool operator()(const prop_info& lhs, const prop_info& rhs) {
        return lhs.key < rhs.key;
    }
    bool operator()(std::string_view lhs, const prop_info& rhs) {
        return lhs < rhs.key;
    }
    bool operator()(const prop_info& lhs, std::string_view rhs) {
        return lhs.key < rhs;
    }
};

} // namespace

static auto& g_properties_lock = *new std::mutex;
static auto& g_properties = *new std::set<prop_info, prop_info_cmp>;

static bool property_set(const char* key, const char* value) {
    if (key == nullptr || *key == '\0') return false;
    if (value == nullptr) value = "";
    bool read_only = !strncmp(key, "ro.", 3);
    if (!read_only && strlen(value) >= PROP_VALUE_MAX) return false;

    std::lock_guard lock(g_properties_lock);
    auto [it, success] = g_properties.emplace(key, value);
    if (read_only) return success;
    if (!success) {
        it->value = value;
        ++it->serial;
    }
    return true;
}

template <typename Func>
static void property_get(const char* key, Func callback) {
    std::lock_guard lock(g_properties_lock);
    auto it = g_properties.find(key);
    if (it != g_properties.end()) {
        callback(*it);
    }
}

// Redefine the __system_property_XXX functions here so we can perform
// logging and access checks for all sysprops in native code.

static void check_system_property_access(const char* key, bool write);

extern "C" {

int __system_property_set(const char* key, const char* value) {
    check_system_property_access(key, true);
    return property_set(key, value) ? 0 : -1;
}

int __system_property_get(const char* key, char* value) {
    check_system_property_access(key, false);
    *value = '\0';
    property_get(key, [&](const prop_info& info) {
        snprintf(value, PROP_VALUE_MAX, "%s", info.value.c_str());
    });
    return strlen(value);
}

const prop_info* __system_property_find(const char* key) {
    check_system_property_access(key, false);
    const prop_info* pi = nullptr;
    property_get(key, [&](const prop_info& info) { pi = &info; });
    return pi;
}

void __system_property_read_callback(const prop_info* pi,
                                     void (*callback)(void*, const char*, const char*, uint32_t),
                                     void* cookie) {
    std::lock_guard lock(g_properties_lock);
    callback(cookie, pi->key.c_str(), pi->value.c_str(), pi->serial);
}

} // extern "C"

// ---- JNI ----

static JavaVM* gVM = nullptr;
static jclass gRunnerState = nullptr;
static jmethodID gCheckSystemPropertyAccess;

static void reloadNativeLibrary(JNIEnv* env, jclass, jstring javaPath) {
    ScopedUtfChars path(env, javaPath);
    // Force reload ourselves as global
    dlopen(path.c_str(), RTLD_LAZY | RTLD_GLOBAL | RTLD_NOLOAD);
}

// Call back into Java code to check property access
static void check_system_property_access(const char* key, bool write) {
    if (gVM != nullptr && gRunnerState != nullptr) {
        JNIEnv* env;
        if (gVM->GetEnv((void**)&env, JNI_VERSION_1_4) >= 0) {
            ALOGV("%s access to system property '%s'", write ? "Write" : "Read", key);
            env->CallStaticVoidMethod(gRunnerState, gCheckSystemPropertyAccess,
                                      env->NewStringUTF(key), write ? JNI_TRUE : JNI_FALSE);
            return;
        }
    }
    // Not on JVM thread, abort
    LOG_ALWAYS_FATAL("Access to system property '%s' on non-JVM threads is not allowed.", key);
}

static jstring getSystemProperty(JNIEnv* env, jclass, jstring javaKey) {
    ScopedUtfChars key(env, javaKey);
    jstring value = nullptr;
    property_get(key.c_str(),
                 [&](const prop_info& info) { value = env->NewStringUTF(info.value.c_str()); });
    return value;
}

static jboolean setSystemProperty(JNIEnv* env, jclass, jstring javaKey, jstring javaValue) {
    ScopedUtfChars key(env, javaKey);
    ScopedUtfChars value(env, javaValue);
    return property_set(key.c_str(), value.c_str()) ? JNI_TRUE : JNI_FALSE;
}

static jboolean removeSystemProperty(JNIEnv* env, jclass, jstring javaKey) {
    std::lock_guard lock(g_properties_lock);

    if (javaKey == nullptr) {
        g_properties.clear();
        return JNI_TRUE;
    } else {
        ScopedUtfChars key(env, javaKey);
        auto it = g_properties.find(key);
        if (it != g_properties.end()) {
            g_properties.erase(it);
            return JNI_TRUE;
        } else {
            return JNI_FALSE;
        }
    }
}

static void maybeRedirectLog() {
    auto ravenwoodLogOut = getenv("RAVENWOOD_LOG_OUT");
    if (ravenwoodLogOut == NULL) {
        return;
    }
    ALOGI("RAVENWOOD_LOG_OUT set. Redirecting output to %s", ravenwoodLogOut);

    // Redirect stdin / stdout to /dev/tty.
    int ttyFd = open(ravenwoodLogOut, O_WRONLY | O_APPEND);
    if (ttyFd == -1) {
        ALOGW("$RAVENWOOD_LOG_OUT is set to %s, but failed to open: %s ", ravenwoodLogOut,
                strerror(errno));
        return;
    }
    dup2(ttyFd, 1);
    dup2(ttyFd, 2);
}

static const JNINativeMethod sMethods[] = {
        {"reloadNativeLibrary", "(Ljava/lang/String;)V", (void*)reloadNativeLibrary},
        {"getSystemProperty", "(Ljava/lang/String;)Ljava/lang/String;", (void*)getSystemProperty},
        {"setSystemProperty", "(Ljava/lang/String;Ljava/lang/String;)Z", (void*)setSystemProperty},
        {"removeSystemProperty", "(Ljava/lang/String;)Z", (void*)removeSystemProperty},
};

extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) {
    ALOGV("%s: JNI_OnLoad", __FILE__);

    maybeRedirectLog();

    JNIEnv* env = GetJNIEnvOrDie(vm);
    gVM = vm;

    // Fetch several references for future use
    gRunnerState = FindGlobalClassOrDie(env, kRunnerState);
    gCheckSystemPropertyAccess =
            GetStaticMethodIDOrDie(env, gRunnerState, "checkSystemPropertyAccess",
                                   "(Ljava/lang/String;Z)V");

    // Expose raw property methods as JNI methods
    jint res = jniRegisterNativeMethods(env, kRuntimeNative, sMethods, NELEM(sMethods));
    if (res < 0) return -1;

    return JNI_VERSION_1_4;
}
