/* * 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. */ /* * Set up values for System.getProperties(). */ #include "Dalvik.h" #include <stdlib.h> #include <sys/utsname.h> #include <limits.h> #include <unistd.h> /* * Create some storage for properties read from the command line. */ bool dvmPropertiesStartup(int maxProps) { gDvm.maxProps = maxProps; if (maxProps > 0) { gDvm.propList = (char**) malloc(maxProps * sizeof(char*)); if (gDvm.propList == NULL) return false; } gDvm.numProps = 0; return true; } /* * Clean up. */ void dvmPropertiesShutdown(void) { int i; for (i = 0; i < gDvm.numProps; i++) free(gDvm.propList[i]); free(gDvm.propList); gDvm.propList = NULL; } /* * Add a property specified on the command line. "argStr" has the form * "name=value". "name" must have nonzero length. * * Returns "true" if argStr appears valid. */ bool dvmAddCommandLineProperty(const char* argStr) { char* mangle; char* equals; mangle = strdup(argStr); equals = strchr(mangle, '='); if (equals == NULL || equals == mangle) { free(mangle); return false; } *equals = '\0'; assert(gDvm.numProps < gDvm.maxProps); gDvm.propList[gDvm.numProps++] = mangle; return true; } /* * Find the "put" method for this class. * * Returns NULL and throws an exception if not found. */ static Method* getPut(ClassObject* clazz) { Method* put; put = dvmFindVirtualMethodHierByDescriptor(clazz, "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"); if (put == NULL) { dvmThrowException("Ljava/lang/RuntimeException;", "could not find setProperty(String,String) in Properties"); /* fall through to return */ } return put; } /* * Set the value of the property. */ static void setProperty(Object* propObj, Method* put, const char* key, const char* value) { StringObject* keyStr; StringObject* valueStr; if (value == NULL) { /* unclear what to do; probably want to create prop w/ empty string */ value = ""; } keyStr = dvmCreateStringFromCstr(key, ALLOC_DEFAULT); valueStr = dvmCreateStringFromCstr(value, ALLOC_DEFAULT); if (keyStr == NULL || valueStr == NULL) { LOGW("setProperty string creation failed\n"); goto bail; } JValue unused; dvmCallMethod(dvmThreadSelf(), put, propObj, &unused, keyStr, valueStr); bail: dvmReleaseTrackedAlloc((Object*) keyStr, NULL); dvmReleaseTrackedAlloc((Object*) valueStr, NULL); } /* * 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. */ void dvmCreateDefaultProperties(Object* propObj) { Method* put = getPut(propObj->clazz); 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. */ 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); 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"); 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. */ 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; /* value starts after the end of the key string */ for (value = gDvm.propList[i]; *value != '\0'; value++) ; 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) { 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, ALLOC_DEFAULT); if (keyObj == NULL) goto bail; JValue val; dvmCallMethod(dvmThreadSelf(), getProp, NULL, &val, keyObj); valueObj = (StringObject*) val.l; if (valueObj == NULL) goto bail; result = dvmCreateCstrFromString(valueObj); /* fall through with result */ bail: dvmReleaseTrackedAlloc((Object*)keyObj, NULL); return result; }