Move more system property handling into managed code.

Bug: 3413364
Change-Id: I0f22ea9ed5327e4fef9d4395025173a839ea9ce2
diff --git a/vm/Dvm.mk b/vm/Dvm.mk
index 91d6b41..a299f2f 100644
--- a/vm/Dvm.mk
+++ b/vm/Dvm.mk
@@ -165,7 +165,6 @@
 	native/java_lang_Runtime.c \
 	native/java_lang_String.c \
 	native/java_lang_System.c \
-	native/java_lang_SystemProperties.c \
 	native/java_lang_Throwable.c \
 	native/java_lang_VMClassLoader.c \
 	native/java_lang_VMThread.c \
diff --git a/vm/Properties.c b/vm/Properties.c
index 243dc3e..312691a 100644
--- a/vm/Properties.c
+++ b/vm/Properties.c
@@ -64,6 +64,9 @@
     char* equals;
 
     mangle = strdup(argStr);
+    if (mangle == NULL) {
+        return false;
+    }
     equals = strchr(mangle, '=');
     if (equals == NULL || equals == mangle) {
         free(mangle);
@@ -79,15 +82,13 @@
 
 
 /*
- * Find the "put" method for this class.
+ * Find the "System.setProperty" method.
  *
  * Returns NULL and throws an exception if not found.
  */
-static Method* getPut(ClassObject* clazz)
+static Method* findSetProperty(ClassObject* clazz)
 {
-    Method* put;
-
-    put = dvmFindVirtualMethodHierByDescriptor(clazz, "setProperty",
+    Method* put = dvmFindVirtualMethodHierByDescriptor(clazz, "setProperty",
             "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
     if (put == NULL) {
         dvmThrowException("Ljava/lang/RuntimeException;",
@@ -127,107 +128,38 @@
 }
 
 /*
- * Create the VM-default system properties.
- *
- * We can do them here, or do them in interpreted code with lots of native
- * methods to get bits and pieces.  This is a bit smaller.
+ * Fills the passed-in java.util.Properties with stuff only the VM knows, such
+ * as the VM's exact version and properties set on the command-line with -D.
  */
-void dvmCreateDefaultProperties(Object* propObj)
+void dvmInitVmSystemProperties(Object* propObj)
 {
-    Method* put = getPut(propObj->clazz);
+    Method* put = findSetProperty(propObj->clazz);
+    int i;
+    struct utsname info;
+    char tmpBuf[64];
+    char path[PATH_MAX];
 
     if (put == NULL)
         return;
 
-    struct utsname info;
-    uname(&info);
-
-    /* constant strings that are used multiple times below */
-    const char *projectUrl = "http://www.android.com/";
-    const char *projectName = "The Android Project";
-
     /*
-     * These are listed in the docs.
+     * TODO: these are currently awkward to do in Java so we sneak them in
+     * here. Only java.vm.version really needs to be in Dalvik.
      */
-
     setProperty(propObj, put, "java.boot.class.path", gDvm.bootClassPathStr);
     setProperty(propObj, put, "java.class.path", gDvm.classPathStr);
-    setProperty(propObj, put, "java.class.version", "46.0");
-    setProperty(propObj, put, "java.compiler", "");
-    setProperty(propObj, put, "java.ext.dirs", "");
-
-    if (getenv("JAVA_HOME") != NULL) {
-        setProperty(propObj, put, "java.home", getenv("JAVA_HOME"));
-    } else {
-        setProperty(propObj, put, "java.home", "/system");
-    }
-
-    setProperty(propObj, put, "java.io.tmpdir", "/tmp");
-    setProperty(propObj, put, "java.library.path", getenv("LD_LIBRARY_PATH"));
-
-    setProperty(propObj, put, "java.net.preferIPv6Addresses", "true");
-
-    setProperty(propObj, put, "java.vendor", projectName);
-    setProperty(propObj, put, "java.vendor.url", projectUrl);
-    setProperty(propObj, put, "java.version", "0");
-    setProperty(propObj, put, "java.vm.name", "Dalvik");
-    setProperty(propObj, put, "java.vm.specification.name",
-            "Dalvik Virtual Machine Specification");
-    setProperty(propObj, put, "java.vm.specification.vendor", projectName);
-    setProperty(propObj, put, "java.vm.specification.version", "0.9");
-    setProperty(propObj, put, "java.vm.vendor", projectName);
-
-    char tmpBuf[64];
     sprintf(tmpBuf, "%d.%d.%d",
-        DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
+            DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
     setProperty(propObj, put, "java.vm.version", tmpBuf);
-
-    setProperty(propObj, put, "java.specification.name",
-            "Dalvik Core Library");
-    setProperty(propObj, put, "java.specification.vendor", projectName);
-    setProperty(propObj, put, "java.specification.version", "0.9");
-
+    uname(&info);
     setProperty(propObj, put, "os.arch", info.machine);
     setProperty(propObj, put, "os.name", info.sysname);
     setProperty(propObj, put, "os.version", info.release);
-    setProperty(propObj, put, "user.home", getenv("HOME"));
-    setProperty(propObj, put, "user.name", getenv("USER"));
-
-    char path[PATH_MAX];
     setProperty(propObj, put, "user.dir", getcwd(path, sizeof(path)));
 
-    setProperty(propObj, put, "file.separator", "/");
-    setProperty(propObj, put, "line.separator", "\n");
-    setProperty(propObj, put, "path.separator", ":");
-
     /*
-     * These show up elsewhere, so do them here too.
+     * Properties set on the command-line with -D.
      */
-    setProperty(propObj, put, "java.runtime.name", "Android Runtime");
-    setProperty(propObj, put, "java.runtime.version", "0.9");
-    setProperty(propObj, put, "java.vm.vendor.url", projectUrl);
-
-    setProperty(propObj, put, "file.encoding", "UTF-8");
-    setProperty(propObj, put, "user.language", "en");
-    setProperty(propObj, put, "user.region", "US");
-
-    /*
-     * These are unique to Android/Dalvik.
-     */
-    setProperty(propObj, put, "android.vm.dexfile", "true");
-}
-
-/*
- * Add anything specified on the command line.
- */
-void dvmSetCommandLineProperties(Object* propObj)
-{
-    Method* put = getPut(propObj->clazz);
-    int i;
-
-    if (put == NULL)
-        return;
-
     for (i = 0; i < gDvm.numProps; i++) {
         const char* value;
 
@@ -237,51 +169,3 @@
         setProperty(propObj, put, gDvm.propList[i], value+1);
     }
 }
-
-/*
- * Get a property by calling System.getProperty(key).
- *
- * Returns a newly-allocated string, or NULL on failure or key not found.
- * (Unexpected failures will also raise an exception.)
- */
-char* dvmGetProperty(const char* key)
-{
-    Thread* self = dvmThreadSelf();
-    ClassObject* system;
-    Method* getProp;
-    StringObject* keyObj = NULL;
-    StringObject* valueObj;
-    char* result = NULL;
-
-    assert(key != NULL);
-
-    system = dvmFindSystemClass("Ljava/lang/System;");
-    if (system == NULL)
-        goto bail;
-
-    getProp = dvmFindDirectMethodByDescriptor(system, "getProperty",
-        "(Ljava/lang/String;)Ljava/lang/String;");
-    if (getProp == NULL) {
-        LOGW("Could not find getProperty(String) in java.lang.System\n");
-        goto bail;
-    }
-
-    keyObj = dvmCreateStringFromCstr(key);
-    if (keyObj == NULL)
-        goto bail;
-
-    JValue val;
-    dvmCallMethod(self, getProp, NULL, &val, keyObj);
-    valueObj = (StringObject*) val.l;
-    if (valueObj == NULL)
-        goto bail;
-
-    /* don't need to call dvmAddTrackedAlloc on result; conv to C string safe */
-
-    result = dvmCreateCstrFromString(valueObj);
-    /* fall through with result */
-
-bail:
-    dvmReleaseTrackedAlloc((Object*)keyObj, self);
-    return result;
-}
diff --git a/vm/Properties.h b/vm/Properties.h
index f7f2f03..7e53db4 100644
--- a/vm/Properties.h
+++ b/vm/Properties.h
@@ -29,9 +29,6 @@
 bool dvmAddCommandLineProperty(const char* argStr);
 
 /* called during property initialization */
-void dvmCreateDefaultProperties(Object* propObj);
-void dvmSetCommandLineProperties(Object* propObj);
-
-char* dvmGetProperty(const char* key);
+void dvmInitVmSystemProperties(Object* propObj);
 
 #endif /*_DALVIK_PROPERTIES*/
diff --git a/vm/native/InternalNative.c b/vm/native/InternalNative.c
index 9dc61d8..595fb7e 100644
--- a/vm/native/InternalNative.c
+++ b/vm/native/InternalNative.c
@@ -31,7 +31,6 @@
     { "Ljava/lang/Runtime;",              dvm_java_lang_Runtime, 0 },
     { "Ljava/lang/String;",               dvm_java_lang_String, 0 },
     { "Ljava/lang/System;",               dvm_java_lang_System, 0 },
-    { "Ljava/lang/SystemProperties;",     dvm_java_lang_SystemProperties, 0 },
     { "Ljava/lang/Throwable;",            dvm_java_lang_Throwable, 0 },
     { "Ljava/lang/VMClassLoader;",        dvm_java_lang_VMClassLoader, 0 },
     { "Ljava/lang/VMThread;",             dvm_java_lang_VMThread, 0 },
diff --git a/vm/native/InternalNativePriv.h b/vm/native/InternalNativePriv.h
index 0e54081..79ef14c 100644
--- a/vm/native/InternalNativePriv.h
+++ b/vm/native/InternalNativePriv.h
@@ -86,7 +86,6 @@
 extern const DalvikNativeMethod dvm_java_lang_Runtime[];
 extern const DalvikNativeMethod dvm_java_lang_String[];
 extern const DalvikNativeMethod dvm_java_lang_System[];
-extern const DalvikNativeMethod dvm_java_lang_SystemProperties[];
 extern const DalvikNativeMethod dvm_java_lang_Throwable[];
 extern const DalvikNativeMethod dvm_java_lang_VMClassLoader[];
 extern const DalvikNativeMethod dvm_java_lang_VMThread[];
diff --git a/vm/native/java_lang_System.c b/vm/native/java_lang_System.c
index 0ac1746..014a774 100644
--- a/vm/native/java_lang_System.c
+++ b/vm/native/java_lang_System.c
@@ -344,6 +344,14 @@
     RETURN_INT(dvmIdentityHashCode(thisPtr));
 }
 
+static void Dalvik_java_lang_System_initVmSystemProperties(const u4* args,
+    JValue* pResult)
+{
+    Object* propObj = (Object*) args[0];
+    dvmInitVmSystemProperties(propObj);
+    RETURN_VOID();
+}
+
 /*
  * public static String mapLibraryName(String libname)
  */
@@ -377,11 +385,13 @@
         Dalvik_java_lang_System_arraycopy },
     { "currentTimeMillis",  "()J",
         Dalvik_java_lang_System_currentTimeMillis },
-    { "nanoTime",  "()J",
-        Dalvik_java_lang_System_nanoTime },
     { "identityHashCode",  "(Ljava/lang/Object;)I",
         Dalvik_java_lang_System_identityHashCode },
+    { "initVmSystemProperties",  "(Ljava/util/Properties;)V",
+        Dalvik_java_lang_System_initVmSystemProperties },
     { "mapLibraryName",     "(Ljava/lang/String;)Ljava/lang/String;",
         Dalvik_java_lang_System_mapLibraryName },
+    { "nanoTime",  "()J",
+        Dalvik_java_lang_System_nanoTime },
     { NULL, NULL, NULL },
 };
diff --git a/vm/native/java_lang_SystemProperties.c b/vm/native/java_lang_SystemProperties.c
deleted file mode 100644
index bbcf25e..0000000
--- a/vm/native/java_lang_SystemProperties.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-/*
- * java.lang.SystemProperties
- */
-#include "Dalvik.h"
-#include "native/InternalNativePriv.h"
-
-
-/*
- * Expected call sequence:
- *  (1) call SystemProperties.preInit() to get VM defaults
- *  (2) set any higher-level defaults
- *  (3) call SystemProperties.postInit() to get command-line overrides
- * This currently happens the first time somebody tries to access a property.
- *
- * SystemProperties is a Dalvik-specific package-scope class.
- */
-
-/*
- * void preInit()
- *
- * Tells the VM to populate the properties table with VM defaults.
- */
-static void Dalvik_java_lang_SystemProperties_preInit(const u4* args,
-    JValue* pResult)
-{
-    dvmCreateDefaultProperties((Object*) args[0]);
-    RETURN_VOID();
-}
-
-/*
- * void postInit()
- *
- * Tells the VM to update properties with values from the command line.
- */
-static void Dalvik_java_lang_SystemProperties_postInit(const u4* args,
-    JValue* pResult)
-{
-    dvmSetCommandLineProperties((Object*) args[0]);
-    RETURN_VOID();
-}
-
-const DalvikNativeMethod dvm_java_lang_SystemProperties[] = {
-    { "preInit",            "()V",
-        Dalvik_java_lang_SystemProperties_preInit },
-    { "postInit",           "()V",
-        Dalvik_java_lang_SystemProperties_postInit },
-    { NULL, NULL, NULL },
-};