/* //device/libs/android_runtime/android_os_SystemProperties.cpp
**
** Copyright 2006, 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 "SysPropJNI"

#include "android-base/logging.h"
#include "android-base/properties.h"
#include "cutils/properties.h"
#include "utils/misc.h"
#include <utils/Log.h>
#include "jni.h"
#include "core_jni_helpers.h"
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedPrimitiveArray.h>
#include <nativehelper/ScopedUtfChars.h>

namespace android
{

namespace {

template <typename T, typename Handler>
T ConvertKeyAndForward(JNIEnv *env, jstring keyJ, T defJ, Handler handler) {
    std::string key;
    {
        // Scope the String access. If the handler can throw an exception,
        // releasing the string characters late would trigger an abort.
        ScopedUtfChars key_utf(env, keyJ);
        if (key_utf.c_str() == nullptr) {
            return defJ;
        }
        key = key_utf.c_str();  // This will make a copy, but we can't avoid
                                // with the existing interface in
                                // android::base.
    }
    return handler(key, defJ);
}

jstring SystemProperties_getSS(JNIEnv *env, jclass clazz, jstring keyJ,
                               jstring defJ)
{
    // Using ConvertKeyAndForward is sub-optimal for copying the key string,
    // but improves reuse and reasoning over code.
    auto handler = [&](const std::string& key, jstring defJ) {
        std::string prop_val = android::base::GetProperty(key, "");
        if (!prop_val.empty()) {
            return env->NewStringUTF(prop_val.c_str());
        };
        if (defJ != nullptr) {
            return defJ;
        }
        // This function is specified to never return null (or have an
        // exception pending).
        return env->NewStringUTF("");
    };
    return ConvertKeyAndForward(env, keyJ, defJ, handler);
}

jstring SystemProperties_getS(JNIEnv *env, jclass clazz, jstring keyJ)
{
    return SystemProperties_getSS(env, clazz, keyJ, nullptr);
}

template <typename T>
T SystemProperties_get_integral(JNIEnv *env, jclass, jstring keyJ,
                                       T defJ)
{
    auto handler = [](const std::string& key, T defV) {
        return android::base::GetIntProperty<T>(key, defV);
    };
    return ConvertKeyAndForward(env, keyJ, defJ, handler);
}

jboolean SystemProperties_get_boolean(JNIEnv *env, jclass, jstring keyJ,
                                      jboolean defJ)
{
    auto handler = [](const std::string& key, jboolean defV) -> jboolean {
        bool result = android::base::GetBoolProperty(key, defV);
        return result ? JNI_TRUE : JNI_FALSE;
    };
    return ConvertKeyAndForward(env, keyJ, defJ, handler);
}

void SystemProperties_set(JNIEnv *env, jobject clazz, jstring keyJ,
                          jstring valJ)
{
    auto handler = [&](const std::string& key, bool) {
        std::string val;
        if (valJ != nullptr) {
            ScopedUtfChars key_utf(env, valJ);
            val = key_utf.c_str();
        }
        return android::base::SetProperty(key, val);
    };
    if (!ConvertKeyAndForward(env, keyJ, true, handler)) {
        // Must have been a failure in SetProperty.
        jniThrowException(env, "java/lang/RuntimeException",
                          "failed to set system property");
    }
}

JavaVM* sVM = nullptr;
jclass sClazz = nullptr;
jmethodID sCallChangeCallbacks;

void do_report_sysprop_change() {
    //ALOGI("Java SystemProperties: VM=%p, Clazz=%p", sVM, sClazz);
    if (sVM != nullptr && sClazz != nullptr) {
        JNIEnv* env;
        if (sVM->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0) {
            //ALOGI("Java SystemProperties: calling %p", sCallChangeCallbacks);
            env->CallStaticVoidMethod(sClazz, sCallChangeCallbacks);
            // There should not be any exceptions. But we must guarantee
            // there are none on return.
            if (env->ExceptionCheck()) {
                env->ExceptionClear();
                LOG(ERROR) << "Exception pending after sysprop_change!";
            }
        }
    }
}

void SystemProperties_add_change_callback(JNIEnv *env, jobject clazz)
{
    // This is called with the Java lock held.
    if (sVM == nullptr) {
        env->GetJavaVM(&sVM);
    }
    if (sClazz == nullptr) {
        sClazz = (jclass) env->NewGlobalRef(clazz);
        sCallChangeCallbacks = env->GetStaticMethodID(sClazz, "callChangeCallbacks", "()V");
        add_sysprop_change_callback(do_report_sysprop_change, -10000);
    }
}

void SystemProperties_report_sysprop_change(JNIEnv /**env*/, jobject /*clazz*/)
{
    report_sysprop_change();
}

}  // namespace

int register_android_os_SystemProperties(JNIEnv *env)
{
    const JNINativeMethod method_table[] = {
        { "native_get", "(Ljava/lang/String;)Ljava/lang/String;",
          (void*) SystemProperties_getS },
        { "native_get",
          "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
          (void*) SystemProperties_getSS },
        { "native_get_int", "(Ljava/lang/String;I)I",
          (void*) SystemProperties_get_integral<jint> },
        { "native_get_long", "(Ljava/lang/String;J)J",
          (void*) SystemProperties_get_integral<jlong> },
        { "native_get_boolean", "(Ljava/lang/String;Z)Z",
          (void*) SystemProperties_get_boolean },
        { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V",
          (void*) SystemProperties_set },
        { "native_add_change_callback", "()V",
          (void*) SystemProperties_add_change_callback },
        { "native_report_sysprop_change", "()V",
          (void*) SystemProperties_report_sysprop_change },
    };
    return RegisterMethodsOrDie(env, "android/os/SystemProperties",
                                method_table, NELEM(method_table));
}

};
