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 "android_runtime/AndroidRuntime.h" 25#include <nativehelper/JNIHelp.h> 26 27namespace android 28{ 29 30static 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 56error: 57 return rvJ; 58} 59 60static jstring SystemProperties_getS(JNIEnv *env, jobject clazz, 61 jstring keyJ) 62{ 63 return SystemProperties_getSS(env, clazz, keyJ, NULL); 64} 65 66static 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 92error: 93 return result; 94} 95 96static 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 122error: 123 return result; 124} 125 126static 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 158error: 159 return result; 160} 161 162static 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 195static JavaVM* sVM = NULL; 196static jclass sClazz = NULL; 197static jmethodID sCallChangeCallbacks; 198 199static 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 210static 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 223static 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 240int register_android_os_SystemProperties(JNIEnv *env) 241{ 242 return AndroidRuntime::registerNativeMethods( 243 env, "android/os/SystemProperties", 244 method_table, NELEM(method_table)); 245} 246 247}; 248