1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 /* 17 * Set up values for System.getProperties(). 18 */ 19 #include "Dalvik.h" 20 21 #include <stdlib.h> 22 #include <sys/utsname.h> 23 #include <limits.h> 24 #include <unistd.h> 25 26 /* 27 * Create some storage for properties read from the command line. 28 */ 29 bool dvmPropertiesStartup(int maxProps) 30 { 31 gDvm.maxProps = maxProps; 32 if (maxProps > 0) { 33 gDvm.propList = (char**) malloc(maxProps * sizeof(char*)); 34 if (gDvm.propList == NULL) 35 return false; 36 } 37 gDvm.numProps = 0; 38 39 return true; 40 } 41 42 /* 43 * Clean up. 44 */ 45 void dvmPropertiesShutdown(void) 46 { 47 int i; 48 49 for (i = 0; i < gDvm.numProps; i++) 50 free(gDvm.propList[i]); 51 free(gDvm.propList); 52 gDvm.propList = NULL; 53 } 54 55 /* 56 * Add a property specified on the command line. "argStr" has the form 57 * "name=value". "name" must have nonzero length. 58 * 59 * Returns "true" if argStr appears valid. 60 */ 61 bool dvmAddCommandLineProperty(const char* argStr) 62 { 63 char* mangle; 64 char* equals; 65 66 mangle = strdup(argStr); 67 equals = strchr(mangle, '='); 68 if (equals == NULL || equals == mangle) { 69 free(mangle); 70 return false; 71 } 72 *equals = '\0'; 73 74 assert(gDvm.numProps < gDvm.maxProps); 75 gDvm.propList[gDvm.numProps++] = mangle; 76 77 return true; 78 } 79 80 81 /* 82 * Find the "put" method for this class. 83 * 84 * Returns NULL and throws an exception if not found. 85 */ 86 static Method* getPut(ClassObject* clazz) 87 { 88 Method* put; 89 90 put = dvmFindVirtualMethodHierByDescriptor(clazz, "setProperty", 91 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"); 92 if (put == NULL) { 93 dvmThrowException("Ljava/lang/RuntimeException;", 94 "could not find setProperty(String,String) in Properties"); 95 /* fall through to return */ 96 } 97 return put; 98 } 99 100 /* 101 * Set the value of the property. 102 */ 103 static void setProperty(Object* propObj, Method* put, const char* key, 104 const char* value) 105 { 106 StringObject* keyStr; 107 StringObject* valueStr; 108 109 if (value == NULL) { 110 /* unclear what to do; probably want to create prop w/ empty string */ 111 value = ""; 112 } 113 114 keyStr = dvmCreateStringFromCstr(key); 115 valueStr = dvmCreateStringFromCstr(value); 116 if (keyStr == NULL || valueStr == NULL) { 117 LOGW("setProperty string creation failed\n"); 118 goto bail; 119 } 120 121 JValue unused; 122 dvmCallMethod(dvmThreadSelf(), put, propObj, &unused, keyStr, valueStr); 123 124 bail: 125 dvmReleaseTrackedAlloc((Object*) keyStr, NULL); 126 dvmReleaseTrackedAlloc((Object*) valueStr, NULL); 127 } 128 129 /* 130 * Create the VM-default system properties. 131 * 132 * We can do them here, or do them in interpreted code with lots of native 133 * methods to get bits and pieces. This is a bit smaller. 134 */ 135 void dvmCreateDefaultProperties(Object* propObj) 136 { 137 Method* put = getPut(propObj->clazz); 138 139 if (put == NULL) 140 return; 141 142 struct utsname info; 143 uname(&info); 144 145 /* constant strings that are used multiple times below */ 146 const char *projectUrl = "http://www.android.com/"; 147 const char *projectName = "The Android Project"; 148 149 /* 150 * These are listed in the docs. 151 */ 152 153 setProperty(propObj, put, "java.boot.class.path", gDvm.bootClassPathStr); 154 setProperty(propObj, put, "java.class.path", gDvm.classPathStr); 155 setProperty(propObj, put, "java.class.version", "46.0"); 156 setProperty(propObj, put, "java.compiler", ""); 157 setProperty(propObj, put, "java.ext.dirs", ""); 158 159 if (getenv("JAVA_HOME") != NULL) { 160 setProperty(propObj, put, "java.home", getenv("JAVA_HOME")); 161 } else { 162 setProperty(propObj, put, "java.home", "/system"); 163 } 164 165 setProperty(propObj, put, "java.io.tmpdir", "/tmp"); 166 setProperty(propObj, put, "java.library.path", getenv("LD_LIBRARY_PATH")); 167 168 setProperty(propObj, put, "java.net.preferIPv6Addresses", "true"); 169 170 setProperty(propObj, put, "java.vendor", projectName); 171 setProperty(propObj, put, "java.vendor.url", projectUrl); 172 setProperty(propObj, put, "java.version", "0"); 173 setProperty(propObj, put, "java.vm.name", "Dalvik"); 174 setProperty(propObj, put, "java.vm.specification.name", 175 "Dalvik Virtual Machine Specification"); 176 setProperty(propObj, put, "java.vm.specification.vendor", projectName); 177 setProperty(propObj, put, "java.vm.specification.version", "0.9"); 178 setProperty(propObj, put, "java.vm.vendor", projectName); 179 180 char tmpBuf[64]; 181 sprintf(tmpBuf, "%d.%d.%d", 182 DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION); 183 setProperty(propObj, put, "java.vm.version", tmpBuf); 184 185 setProperty(propObj, put, "java.specification.name", 186 "Dalvik Core Library"); 187 setProperty(propObj, put, "java.specification.vendor", projectName); 188 setProperty(propObj, put, "java.specification.version", "0.9"); 189 190 setProperty(propObj, put, "os.arch", info.machine); 191 setProperty(propObj, put, "os.name", info.sysname); 192 setProperty(propObj, put, "os.version", info.release); 193 setProperty(propObj, put, "user.home", getenv("HOME")); 194 setProperty(propObj, put, "user.name", getenv("USER")); 195 196 char path[PATH_MAX]; 197 setProperty(propObj, put, "user.dir", getcwd(path, sizeof(path))); 198 199 setProperty(propObj, put, "file.separator", "/"); 200 setProperty(propObj, put, "line.separator", "\n"); 201 setProperty(propObj, put, "path.separator", ":"); 202 203 /* 204 * These show up elsewhere, so do them here too. 205 */ 206 setProperty(propObj, put, "java.runtime.name", "Android Runtime"); 207 setProperty(propObj, put, "java.runtime.version", "0.9"); 208 setProperty(propObj, put, "java.vm.vendor.url", projectUrl); 209 210 setProperty(propObj, put, "file.encoding", "UTF-8"); 211 setProperty(propObj, put, "user.language", "en"); 212 setProperty(propObj, put, "user.region", "US"); 213 214 /* 215 * These are unique to Android/Dalvik. 216 */ 217 setProperty(propObj, put, "android.vm.dexfile", "true"); 218 } 219 220 /* 221 * Add anything specified on the command line. 222 */ 223 void dvmSetCommandLineProperties(Object* propObj) 224 { 225 Method* put = getPut(propObj->clazz); 226 int i; 227 228 if (put == NULL) 229 return; 230 231 for (i = 0; i < gDvm.numProps; i++) { 232 const char* value; 233 234 /* value starts after the end of the key string */ 235 for (value = gDvm.propList[i]; *value != '\0'; value++) 236 ; 237 setProperty(propObj, put, gDvm.propList[i], value+1); 238 } 239 } 240 241 /* 242 * Get a property by calling System.getProperty(key). 243 * 244 * Returns a newly-allocated string, or NULL on failure or key not found. 245 * (Unexpected failures will also raise an exception.) 246 */ 247 char* dvmGetProperty(const char* key) 248 { 249 ClassObject* system; 250 Method* getProp; 251 StringObject* keyObj = NULL; 252 StringObject* valueObj; 253 char* result = NULL; 254 255 assert(key != NULL); 256 257 system = dvmFindSystemClass("Ljava/lang/System;"); 258 if (system == NULL) 259 goto bail; 260 261 getProp = dvmFindDirectMethodByDescriptor(system, "getProperty", 262 "(Ljava/lang/String;)Ljava/lang/String;"); 263 if (getProp == NULL) { 264 LOGW("Could not find getProperty(String) in java.lang.System\n"); 265 goto bail; 266 } 267 268 keyObj = dvmCreateStringFromCstr(key); 269 if (keyObj == NULL) 270 goto bail; 271 272 JValue val; 273 dvmCallMethod(dvmThreadSelf(), getProp, NULL, &val, keyObj); 274 valueObj = (StringObject*) val.l; 275 if (valueObj == NULL) 276 goto bail; 277 278 result = dvmCreateCstrFromString(valueObj); 279 /* fall through with result */ 280 281 bail: 282 dvmReleaseTrackedAlloc((Object*)keyObj, NULL); 283 return result; 284 } 285