1 /* //device/libs/android_runtime/android_os_SystemProperties.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** 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
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** 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
15 ** limitations under the License.
16 */
17 
18 #define LOG_TAG "SysPropJNI"
19 
20 #include "cutils/properties.h"
21 #include "utils/misc.h"
22 #include <utils/Log.h>
23 #include "jni.h"
24 #include "core_jni_helpers.h"
25 #include <nativehelper/JNIHelp.h>
26 
27 namespace android
28 {
29 
SystemProperties_getSS(JNIEnv * env,jobject clazz,jstring keyJ,jstring defJ)30 static jstring SystemProperties_getSS(JNIEnv *env, jobject clazz,
31                                       jstring keyJ, jstring defJ)
32 {
33     int len;
34     const char* key;
35     char buf[PROPERTY_VALUE_MAX];
36     jstring rvJ = NULL;
37 
38     if (keyJ == NULL) {
39         jniThrowNullPointerException(env, "key must not be null.");
40         goto error;
41     }
42 
43     key = env->GetStringUTFChars(keyJ, NULL);
44 
45     len = property_get(key, buf, "");
46     if ((len <= 0) && (defJ != NULL)) {
47         rvJ = defJ;
48     } else if (len >= 0) {
49         rvJ = env->NewStringUTF(buf);
50     } else {
51         rvJ = env->NewStringUTF("");
52     }
53 
54     env->ReleaseStringUTFChars(keyJ, key);
55 
56 error:
57     return rvJ;
58 }
59 
SystemProperties_getS(JNIEnv * env,jobject clazz,jstring keyJ)60 static jstring SystemProperties_getS(JNIEnv *env, jobject clazz,
61                                       jstring keyJ)
62 {
63     return SystemProperties_getSS(env, clazz, keyJ, NULL);
64 }
65 
SystemProperties_get_int(JNIEnv * env,jobject clazz,jstring keyJ,jint defJ)66 static jint SystemProperties_get_int(JNIEnv *env, jobject clazz,
67                                       jstring keyJ, jint defJ)
68 {
69     int len;
70     const char* key;
71     char buf[PROPERTY_VALUE_MAX];
72     char* end;
73     jint result = defJ;
74 
75     if (keyJ == NULL) {
76         jniThrowNullPointerException(env, "key must not be null.");
77         goto error;
78     }
79 
80     key = env->GetStringUTFChars(keyJ, NULL);
81 
82     len = property_get(key, buf, "");
83     if (len > 0) {
84         result = strtol(buf, &end, 0);
85         if (end == buf) {
86             result = defJ;
87         }
88     }
89 
90     env->ReleaseStringUTFChars(keyJ, key);
91 
92 error:
93     return result;
94 }
95 
SystemProperties_get_long(JNIEnv * env,jobject clazz,jstring keyJ,jlong defJ)96 static jlong SystemProperties_get_long(JNIEnv *env, jobject clazz,
97                                       jstring keyJ, jlong defJ)
98 {
99     int len;
100     const char* key;
101     char buf[PROPERTY_VALUE_MAX];
102     char* end;
103     jlong result = defJ;
104 
105     if (keyJ == NULL) {
106         jniThrowNullPointerException(env, "key must not be null.");
107         goto error;
108     }
109 
110     key = env->GetStringUTFChars(keyJ, NULL);
111 
112     len = property_get(key, buf, "");
113     if (len > 0) {
114         result = strtoll(buf, &end, 0);
115         if (end == buf) {
116             result = defJ;
117         }
118     }
119 
120     env->ReleaseStringUTFChars(keyJ, key);
121 
122 error:
123     return result;
124 }
125 
SystemProperties_get_boolean(JNIEnv * env,jobject clazz,jstring keyJ,jboolean defJ)126 static jboolean SystemProperties_get_boolean(JNIEnv *env, jobject clazz,
127                                       jstring keyJ, jboolean defJ)
128 {
129     int len;
130     const char* key;
131     char buf[PROPERTY_VALUE_MAX];
132     jboolean result = defJ;
133 
134     if (keyJ == NULL) {
135         jniThrowNullPointerException(env, "key must not be null.");
136         goto error;
137     }
138 
139     key = env->GetStringUTFChars(keyJ, NULL);
140 
141     len = property_get(key, buf, "");
142     if (len == 1) {
143         char ch = buf[0];
144         if (ch == '0' || ch == 'n')
145             result = false;
146         else if (ch == '1' || ch == 'y')
147             result = true;
148     } else if (len > 1) {
149          if (!strcmp(buf, "no") || !strcmp(buf, "false") || !strcmp(buf, "off")) {
150             result = false;
151         } else if (!strcmp(buf, "yes") || !strcmp(buf, "true") || !strcmp(buf, "on")) {
152             result = true;
153         }
154     }
155 
156     env->ReleaseStringUTFChars(keyJ, key);
157 
158 error:
159     return result;
160 }
161 
SystemProperties_set(JNIEnv * env,jobject clazz,jstring keyJ,jstring valJ)162 static void SystemProperties_set(JNIEnv *env, jobject clazz,
163                                       jstring keyJ, jstring valJ)
164 {
165     int err;
166     const char* key;
167     const char* val;
168 
169     if (keyJ == NULL) {
170         jniThrowNullPointerException(env, "key must not be null.");
171         return ;
172     }
173     key = env->GetStringUTFChars(keyJ, NULL);
174 
175     if (valJ == NULL) {
176         val = "";       /* NULL pointer not allowed here */
177     } else {
178         val = env->GetStringUTFChars(valJ, NULL);
179     }
180 
181     err = property_set(key, val);
182 
183     env->ReleaseStringUTFChars(keyJ, key);
184 
185     if (valJ != NULL) {
186         env->ReleaseStringUTFChars(valJ, val);
187     }
188 
189     if (err < 0) {
190         jniThrowException(env, "java/lang/RuntimeException",
191                           "failed to set system property");
192     }
193 }
194 
195 static JavaVM* sVM = NULL;
196 static jclass sClazz = NULL;
197 static jmethodID sCallChangeCallbacks;
198 
do_report_sysprop_change()199 static void do_report_sysprop_change() {
200     //ALOGI("Java SystemProperties: VM=%p, Clazz=%p", sVM, sClazz);
201     if (sVM != NULL && sClazz != NULL) {
202         JNIEnv* env;
203         if (sVM->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0) {
204             //ALOGI("Java SystemProperties: calling %p", sCallChangeCallbacks);
205             env->CallStaticVoidMethod(sClazz, sCallChangeCallbacks);
206         }
207     }
208 }
209 
SystemProperties_add_change_callback(JNIEnv * env,jobject clazz)210 static void SystemProperties_add_change_callback(JNIEnv *env, jobject clazz)
211 {
212     // This is called with the Java lock held.
213     if (sVM == NULL) {
214         env->GetJavaVM(&sVM);
215     }
216     if (sClazz == NULL) {
217         sClazz = (jclass) env->NewGlobalRef(clazz);
218         sCallChangeCallbacks = env->GetStaticMethodID(sClazz, "callChangeCallbacks", "()V");
219         add_sysprop_change_callback(do_report_sysprop_change, -10000);
220     }
221 }
222 
223 static const JNINativeMethod method_table[] = {
224     { "native_get", "(Ljava/lang/String;)Ljava/lang/String;",
225       (void*) SystemProperties_getS },
226     { "native_get", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
227       (void*) SystemProperties_getSS },
228     { "native_get_int", "(Ljava/lang/String;I)I",
229       (void*) SystemProperties_get_int },
230     { "native_get_long", "(Ljava/lang/String;J)J",
231       (void*) SystemProperties_get_long },
232     { "native_get_boolean", "(Ljava/lang/String;Z)Z",
233       (void*) SystemProperties_get_boolean },
234     { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V",
235       (void*) SystemProperties_set },
236     { "native_add_change_callback", "()V",
237       (void*) SystemProperties_add_change_callback },
238 };
239 
register_android_os_SystemProperties(JNIEnv * env)240 int register_android_os_SystemProperties(JNIEnv *env)
241 {
242     return RegisterMethodsOrDie(env, "android/os/SystemProperties", method_table,
243                                 NELEM(method_table));
244 }
245 
246 };
247