blob: 9ec7517754d9a55b3bc6a9820382a7f509f3f732 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //device/libs/android_runtime/android_os_SystemProperties.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
Elliott Hughes69a017b2011-04-08 14:10:28 -07005** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008**
Elliott Hughes69a017b2011-04-08 14:10:28 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010**
Elliott Hughes69a017b2011-04-08 14:10:28 -070011** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015** limitations under the License.
16*/
17
Dianne Hackborna53de062012-05-08 18:53:51 -070018#define LOG_TAG "SysPropJNI"
19
Andreas Gampea90534b2017-07-29 14:14:39 -070020#include "android-base/logging.h"
21#include "android-base/properties.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022#include "cutils/properties.h"
Dianne Hackborna53de062012-05-08 18:53:51 -070023#include "utils/misc.h"
24#include <utils/Log.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025#include "jni.h"
Andreas Gampeed6b9df2014-11-20 22:02:20 -080026#include "core_jni_helpers.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027#include <nativehelper/JNIHelp.h>
Andreas Gampea90534b2017-07-29 14:14:39 -070028#include <nativehelper/ScopedPrimitiveArray.h>
29#include <nativehelper/ScopedUtfChars.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
31namespace android
32{
33
Andreas Gampea90534b2017-07-29 14:14:39 -070034namespace {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035
Andreas Gampea90534b2017-07-29 14:14:39 -070036template <typename T, typename Handler>
37T ConvertKeyAndForward(JNIEnv *env, jstring keyJ, T defJ, Handler handler) {
38 std::string key;
39 {
40 // Scope the String access. If the handler can throw an exception,
41 // releasing the string characters late would trigger an abort.
42 ScopedUtfChars key_utf(env, keyJ);
43 if (key_utf.c_str() == nullptr) {
44 return defJ;
Dianne Hackborn83e6eb12012-05-08 14:53:24 -070045 }
Andreas Gampea90534b2017-07-29 14:14:39 -070046 key = key_utf.c_str(); // This will make a copy, but we can't avoid
47 // with the existing interface in
48 // android::base.
Mike Lockwoodd1945952009-08-12 17:15:51 -040049 }
Andreas Gampea90534b2017-07-29 14:14:39 -070050 return handler(key, defJ);
Mike Lockwoodd1945952009-08-12 17:15:51 -040051}
52
Andreas Gampea90534b2017-07-29 14:14:39 -070053jstring SystemProperties_getSS(JNIEnv *env, jclass clazz, jstring keyJ,
54 jstring defJ)
Mike Lockwoodd1945952009-08-12 17:15:51 -040055{
Andreas Gampea90534b2017-07-29 14:14:39 -070056 // Using ConvertKeyAndForward is sub-optimal for copying the key string,
57 // but improves reuse and reasoning over code.
58 auto handler = [&](const std::string& key, jstring defJ) {
59 std::string prop_val = android::base::GetProperty(key, "");
60 if (!prop_val.empty()) {
61 return env->NewStringUTF(prop_val.c_str());
62 };
63 if (defJ != nullptr) {
64 return defJ;
Dianne Hackborn83e6eb12012-05-08 14:53:24 -070065 }
Andreas Gampea90534b2017-07-29 14:14:39 -070066 // This function is specified to never return null (or have an
67 // exception pending).
68 return env->NewStringUTF("");
69 };
70 return ConvertKeyAndForward(env, keyJ, defJ, handler);
Mike Lockwoodd1945952009-08-12 17:15:51 -040071}
72
Andreas Gampea90534b2017-07-29 14:14:39 -070073jstring SystemProperties_getS(JNIEnv *env, jclass clazz, jstring keyJ)
Mike Lockwoodd1945952009-08-12 17:15:51 -040074{
Andreas Gampea90534b2017-07-29 14:14:39 -070075 return SystemProperties_getSS(env, clazz, keyJ, nullptr);
76}
Mike Lockwoodd1945952009-08-12 17:15:51 -040077
Andreas Gampea90534b2017-07-29 14:14:39 -070078template <typename T>
79T SystemProperties_get_integral(JNIEnv *env, jclass, jstring keyJ,
80 T defJ)
81{
82 auto handler = [](const std::string& key, T defV) {
83 return android::base::GetIntProperty<T>(key, defV);
84 };
85 return ConvertKeyAndForward(env, keyJ, defJ, handler);
86}
Mike Lockwoodd1945952009-08-12 17:15:51 -040087
Andreas Gampea90534b2017-07-29 14:14:39 -070088jboolean SystemProperties_get_boolean(JNIEnv *env, jclass, jstring keyJ,
89 jboolean defJ)
90{
91 auto handler = [](const std::string& key, jboolean defV) -> jboolean {
92 bool result = android::base::GetBoolProperty(key, defV);
93 return result ? JNI_TRUE : JNI_FALSE;
94 };
95 return ConvertKeyAndForward(env, keyJ, defJ, handler);
96}
Mike Lockwoodd1945952009-08-12 17:15:51 -040097
Andreas Gampea90534b2017-07-29 14:14:39 -070098void SystemProperties_set(JNIEnv *env, jobject clazz, jstring keyJ,
99 jstring valJ)
100{
101 auto handler = [&](const std::string& key, bool) {
102 std::string val;
103 if (valJ != nullptr) {
104 ScopedUtfChars key_utf(env, valJ);
105 val = key_utf.c_str();
Mike Lockwoodd1945952009-08-12 17:15:51 -0400106 }
Andreas Gampea90534b2017-07-29 14:14:39 -0700107 return android::base::SetProperty(key, val);
108 };
109 if (!ConvertKeyAndForward(env, keyJ, true, handler)) {
110 // Must have been a failure in SetProperty.
Brad Fitzpatrick06f36742011-03-10 16:04:59 -0800111 jniThrowException(env, "java/lang/RuntimeException",
112 "failed to set system property");
113 }
114}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115
Andreas Gampea90534b2017-07-29 14:14:39 -0700116JavaVM* sVM = nullptr;
117jclass sClazz = nullptr;
118jmethodID sCallChangeCallbacks;
Dianne Hackborna53de062012-05-08 18:53:51 -0700119
Andreas Gampea90534b2017-07-29 14:14:39 -0700120void do_report_sysprop_change() {
Dianne Hackborna53de062012-05-08 18:53:51 -0700121 //ALOGI("Java SystemProperties: VM=%p, Clazz=%p", sVM, sClazz);
Andreas Gampea90534b2017-07-29 14:14:39 -0700122 if (sVM != nullptr && sClazz != nullptr) {
Dianne Hackborna53de062012-05-08 18:53:51 -0700123 JNIEnv* env;
124 if (sVM->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0) {
125 //ALOGI("Java SystemProperties: calling %p", sCallChangeCallbacks);
126 env->CallStaticVoidMethod(sClazz, sCallChangeCallbacks);
Andreas Gampe7074e6f2018-03-16 16:14:29 -0700127 // There should not be any exceptions. But we must guarantee
128 // there are none on return.
129 if (env->ExceptionCheck()) {
130 env->ExceptionClear();
131 LOG(ERROR) << "Exception pending after sysprop_change!";
132 }
Dianne Hackborna53de062012-05-08 18:53:51 -0700133 }
134 }
135}
136
Andreas Gampea90534b2017-07-29 14:14:39 -0700137void SystemProperties_add_change_callback(JNIEnv *env, jobject clazz)
Dianne Hackborna53de062012-05-08 18:53:51 -0700138{
139 // This is called with the Java lock held.
Andreas Gampea90534b2017-07-29 14:14:39 -0700140 if (sVM == nullptr) {
Dianne Hackborna53de062012-05-08 18:53:51 -0700141 env->GetJavaVM(&sVM);
142 }
Andreas Gampea90534b2017-07-29 14:14:39 -0700143 if (sClazz == nullptr) {
Dianne Hackborna53de062012-05-08 18:53:51 -0700144 sClazz = (jclass) env->NewGlobalRef(clazz);
145 sCallChangeCallbacks = env->GetStaticMethodID(sClazz, "callChangeCallbacks", "()V");
146 add_sysprop_change_callback(do_report_sysprop_change, -10000);
147 }
148}
149
Andreas Gampea90534b2017-07-29 14:14:39 -0700150void SystemProperties_report_sysprop_change(JNIEnv /**env*/, jobject /*clazz*/)
Martijn Coenen0754b272016-11-17 14:06:38 +0100151{
152 report_sysprop_change();
153}
154
Andreas Gampea90534b2017-07-29 14:14:39 -0700155} // namespace
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156
157int register_android_os_SystemProperties(JNIEnv *env)
158{
Andreas Gampea90534b2017-07-29 14:14:39 -0700159 const JNINativeMethod method_table[] = {
160 { "native_get", "(Ljava/lang/String;)Ljava/lang/String;",
161 (void*) SystemProperties_getS },
162 { "native_get",
163 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
164 (void*) SystemProperties_getSS },
165 { "native_get_int", "(Ljava/lang/String;I)I",
166 (void*) SystemProperties_get_integral<jint> },
167 { "native_get_long", "(Ljava/lang/String;J)J",
168 (void*) SystemProperties_get_integral<jlong> },
169 { "native_get_boolean", "(Ljava/lang/String;Z)Z",
170 (void*) SystemProperties_get_boolean },
171 { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V",
172 (void*) SystemProperties_set },
173 { "native_add_change_callback", "()V",
174 (void*) SystemProperties_add_change_callback },
175 { "native_report_sysprop_change", "()V",
176 (void*) SystemProperties_report_sysprop_change },
177 };
178 return RegisterMethodsOrDie(env, "android/os/SystemProperties",
179 method_table, NELEM(method_table));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180}
181
182};