SystemProperties: eliminate unnecessary string allocation.

getInt(), getLong() and getBoolean() no longer allocate a temporary String object.

Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index c3ae3c2..4a036ec 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -30,6 +30,9 @@
 
     private static native String native_get(String key);
     private static native String native_get(String key, String def);
+    private static native int native_get_int(String key, int def);
+    private static native long native_get_long(String key, long def);
+    private static native boolean native_get_boolean(String key, boolean def);
     private static native void native_set(String key, String def);
 
     /**
@@ -65,11 +68,10 @@
      * @throws IllegalArgumentException if the key exceeds 32 characters
      */
     public static int getInt(String key, int def) {
-        try {
-            return Integer.parseInt(get(key));
-        } catch (NumberFormatException e) {
-            return def;
+        if (key.length() > PROP_NAME_MAX) {
+            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
         }
+        return native_get_int(key, def);
     }
 
     /**
@@ -81,11 +83,10 @@
      * @throws IllegalArgumentException if the key exceeds 32 characters
      */
     public static long getLong(String key, long def) {
-        try {
-            return Long.parseLong(get(key));
-        } catch (NumberFormatException e) {
-            return def;
+        if (key.length() > PROP_NAME_MAX) {
+            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
         }
+        return native_get_long(key, def);
     }
 
     /**
@@ -102,27 +103,10 @@
      * @throws IllegalArgumentException if the key exceeds 32 characters
      */
     public static boolean getBoolean(String key, boolean def) {
-        String value = get(key);
-        // Deal with these quick cases first: not found, 0 and 1
-        if (value.equals("")) {
-            return def;
-        } else if (value.equals("0")) {
-            return false;
-        } else if (value.equals("1")) {
-            return true;
-        // now for slower (and hopefully less common) cases
-        } else if (value.equalsIgnoreCase("n") ||
-                   value.equalsIgnoreCase("no") ||
-                   value.equalsIgnoreCase("false") ||
-                   value.equalsIgnoreCase("off")) {
-            return false;
-        } else if (value.equalsIgnoreCase("y") ||
-                   value.equalsIgnoreCase("yes") ||
-                   value.equalsIgnoreCase("true") ||
-                   value.equalsIgnoreCase("on")) {
-            return true;
+        if (key.length() > PROP_NAME_MAX) {
+            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
         }
-        return def;
+        return native_get_boolean(key, def);
     }
 
     /**
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index ca4fa11..406884b 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -36,9 +36,9 @@
                                 "key must not be null.");
         goto error;
     }
-    
+
     key = env->GetStringUTFChars(keyJ, NULL);
-    
+
     len = property_get(key, buf, "");
     if ((len <= 0) && (defJ != NULL)) {
         rvJ = defJ;
@@ -47,9 +47,9 @@
     } else {
         rvJ = env->NewStringUTF("");
     }
-    
+
     env->ReleaseStringUTFChars(keyJ, key);
-    
+
 error:
     return rvJ;
 }
@@ -60,6 +60,101 @@
     return SystemProperties_getSS(env, clazz, keyJ, NULL);
 }
 
+static jint SystemProperties_get_int(JNIEnv *env, jobject clazz,
+                                      jstring keyJ, jint defJ)
+{
+    int len;
+    const char* key;
+    char buf[PROPERTY_VALUE_MAX];
+    jint result = defJ;
+
+    if (keyJ == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException",
+                                "key must not be null.");
+        goto error;
+    }
+
+    key = env->GetStringUTFChars(keyJ, NULL);
+
+    len = property_get(key, buf, "");
+    if (len > 0) {
+        jint temp;
+        if (sscanf(buf, "%d", &temp) == 1)
+            result = temp;
+    }
+
+    env->ReleaseStringUTFChars(keyJ, key);
+
+error:
+    return result;
+}
+
+static jlong SystemProperties_get_long(JNIEnv *env, jobject clazz,
+                                      jstring keyJ, jlong defJ)
+{
+    int len;
+    const char* key;
+    char buf[PROPERTY_VALUE_MAX];
+    jlong result = defJ;
+
+    if (keyJ == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException",
+                                "key must not be null.");
+        goto error;
+    }
+
+    key = env->GetStringUTFChars(keyJ, NULL);
+
+    len = property_get(key, buf, "");
+    if (len > 0) {
+        jlong temp;
+        if (sscanf(buf, "%lld", &temp) == 1)
+            result = temp;
+    }
+
+    env->ReleaseStringUTFChars(keyJ, key);
+
+error:
+    return result;
+}
+
+static jboolean SystemProperties_get_boolean(JNIEnv *env, jobject clazz,
+                                      jstring keyJ, jboolean defJ)
+{
+    int len;
+    const char* key;
+    char buf[PROPERTY_VALUE_MAX];
+    jboolean result = defJ;
+
+    if (keyJ == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException",
+                                "key must not be null.");
+        goto error;
+    }
+
+    key = env->GetStringUTFChars(keyJ, NULL);
+
+    len = property_get(key, buf, "");
+    if (len == 1) {
+        char ch = buf[0];
+        if (ch == '0' || ch == 'n')
+            result = false;
+        else if (ch == '1' || ch == 'y')
+            result = true;
+    } else if (len > 1) {
+         if (!strcmp(buf, "no") || !strcmp(buf, "false") || !strcmp(buf, "off")) {
+            result = false;
+        } else if (!strcmp(buf, "yes") || !strcmp(buf, "true") || !strcmp(buf, "on")) {
+            result = true;
+        }
+    }
+
+    env->ReleaseStringUTFChars(keyJ, key);
+
+error:
+    return result;
+}
+
 static void SystemProperties_set(JNIEnv *env, jobject clazz,
                                       jstring keyJ, jstring valJ)
 {
@@ -94,6 +189,12 @@
       (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_int },
+    { "native_get_long", "(Ljava/lang/String;J)J",
+      (void*) SystemProperties_get_long },
+    { "native_get_boolean", "(Ljava/lang/String;Z)Z",
+      (void*) SystemProperties_get_boolean },
     { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V",
       (void*) SystemProperties_set },
 };