1 /* 2 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 #define LOG_TAG "libcore" 26 27 #include <stdlib.h> 28 #include <string.h> 29 #include <time.h> 30 31 #include <log/log.h> 32 33 #include "io_util.h" 34 #include "jni.h" 35 #include "jni_util.h" 36 #include "jvm.h" 37 38 #include "openssl/opensslv.h" 39 #include "zlib.h" 40 #include <nativehelper/JNIHelp.h> 41 #include <nativehelper/jni_macros.h> 42 43 #if defined(__ANDROID__) 44 void android_get_LD_LIBRARY_PATH(char*, size_t); 45 #endif 46 47 #define PUTPROP(props, key, val) \ 48 if (1) { \ 49 jstring jkey = (*env)->NewStringUTF(env, key); \ 50 jstring jval = (*env)->NewStringUTF(env, val); \ 51 jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \ 52 if ((*env)->ExceptionOccurred(env)) return NULL; \ 53 (*env)->DeleteLocalRef(env, jkey); \ 54 (*env)->DeleteLocalRef(env, jval); \ 55 (*env)->DeleteLocalRef(env, r); \ 56 } else ((void) 0) 57 58 /* "key" is a char type string with only ASCII character in it. 59 "val" is a nchar (typedefed in java_props.h) type string */ 60 61 #define PUTPROP_ForPlatformNString(props, key, val) \ 62 if (1) { \ 63 jstring jkey = (*env)->NewStringUTF(env, key); \ 64 jstring jval = GetStringPlatform(env, val); \ 65 jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \ 66 if ((*env)->ExceptionOccurred(env)) return NULL; \ 67 (*env)->DeleteLocalRef(env, jkey); \ 68 (*env)->DeleteLocalRef(env, jval); \ 69 (*env)->DeleteLocalRef(env, r); \ 70 } else ((void) 0) 71 #define REMOVEPROP(props, key) \ 72 if (1) { \ 73 jstring jkey = JNU_NewStringPlatform(env, key); \ 74 jobject r = (*env)->CallObjectMethod(env, props, removeID, jkey); \ 75 if ((*env)->ExceptionOccurred(env)) return NULL; \ 76 (*env)->DeleteLocalRef(env, jkey); \ 77 (*env)->DeleteLocalRef(env, r); \ 78 } else ((void) 0) 79 #define GETPROP(props, key, jret) \ 80 if (1) { \ 81 jstring jkey = JNU_NewStringPlatform(env, key); \ 82 (jret) = (*env)->CallObjectMethod(env, props, getPropID, jkey); \ 83 if ((*env)->ExceptionOccurred(env)) return NULL; \ 84 (*env)->DeleteLocalRef(env, jkey); \ 85 } else ((void) 0) 86 87 #ifndef VENDOR /* Third party may overwrite this. */ 88 #define VENDOR "Oracle Corporation" 89 #define VENDOR_URL "http://java.oracle.com/" 90 #define VENDOR_URL_BUG "http://bugreport.sun.com/bugreport/" 91 #endif 92 93 #define JAVA_MAX_SUPPORTED_VERSION 51 94 #define JAVA_MAX_SUPPORTED_MINOR_VERSION 0 95 96 #ifdef JAVA_SPECIFICATION_VENDOR /* Third party may NOT overwrite this. */ 97 #error "ERROR: No override of JAVA_SPECIFICATION_VENDOR is allowed" 98 #else 99 #define JAVA_SPECIFICATION_VENDOR "Oracle Corporation" 100 #endif 101 102 /* 103 * The following three functions implement setter methods for 104 * java.lang.System.{in, out, err}. They are natively implemented 105 * because they violate the semantics of the language (i.e. set final 106 * variable). 107 */ 108 JNIEXPORT void JNICALL System_setIn0(JNIEnv * env,jclass cla,jobject stream)109 System_setIn0(JNIEnv *env, jclass cla, jobject stream) 110 { 111 jfieldID fid = 112 (*env)->GetStaticFieldID(env,cla,"in","Ljava/io/InputStream;"); 113 if (fid == 0) 114 return; 115 (*env)->SetStaticObjectField(env,cla,fid,stream); 116 } 117 118 JNIEXPORT void JNICALL System_setOut0(JNIEnv * env,jclass cla,jobject stream)119 System_setOut0(JNIEnv *env, jclass cla, jobject stream) 120 { 121 jfieldID fid = 122 (*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;"); 123 if (fid == 0) 124 return; 125 (*env)->SetStaticObjectField(env,cla,fid,stream); 126 } 127 128 JNIEXPORT void JNICALL System_setErr0(JNIEnv * env,jclass cla,jobject stream)129 System_setErr0(JNIEnv *env, jclass cla, jobject stream) 130 { 131 jfieldID fid = 132 (*env)->GetStaticFieldID(env,cla,"err","Ljava/io/PrintStream;"); 133 if (fid == 0) 134 return; 135 (*env)->SetStaticObjectField(env,cla,fid,stream); 136 } 137 cpchars(jchar * dst,char * src,int n)138 static void cpchars(jchar *dst, char *src, int n) 139 { 140 int i; 141 for (i = 0; i < n; i++) { 142 dst[i] = src[i]; 143 } 144 } 145 146 JNIEXPORT jstring JNICALL System_mapLibraryName(JNIEnv * env,jclass ign,jstring libname)147 System_mapLibraryName(JNIEnv *env, jclass ign, jstring libname) 148 { 149 int len; 150 int prefix_len = (int) strlen(JNI_LIB_PREFIX); 151 int suffix_len = (int) strlen(JNI_LIB_SUFFIX); 152 153 jchar chars[256]; 154 if (libname == NULL) { 155 JNU_ThrowNullPointerException(env, 0); 156 return NULL; 157 } 158 len = (*env)->GetStringLength(env, libname); 159 if (len > 240) { 160 JNU_ThrowIllegalArgumentException(env, "name too long"); 161 return NULL; 162 } 163 cpchars(chars, JNI_LIB_PREFIX, prefix_len); 164 (*env)->GetStringRegion(env, libname, 0, len, chars + prefix_len); 165 len += prefix_len; 166 cpchars(chars + len, JNI_LIB_SUFFIX, suffix_len); 167 len += suffix_len; 168 169 return (*env)->NewString(env, chars, len); 170 } 171 System_specialProperties(JNIEnv * env,jclass ignored)172 static jobjectArray System_specialProperties(JNIEnv* env, jclass ignored) { 173 jclass stringClass = (*env)->FindClass(env, "java/lang/String"); 174 jobjectArray result = (*env)->NewObjectArray(env, 4, stringClass, NULL); 175 176 char path[PATH_MAX]; 177 char* process_path = getcwd(path, sizeof(path)); 178 char user_dir[PATH_MAX + 10] = "user.dir="; 179 strncat(user_dir, process_path, PATH_MAX); 180 jstring user_dir_str = (*env)->NewStringUTF(env, user_dir); 181 if ((*env)->ExceptionCheck(env)) { 182 return NULL; 183 } 184 (*env)->SetObjectArrayElement(env, result, 0, user_dir_str); 185 if ((*env)->ExceptionCheck(env)) { 186 return NULL; 187 } 188 jstring zlib_str = (*env)->NewStringUTF(env, "android.zlib.version=" ZLIB_VERSION); 189 if ((*env)->ExceptionCheck(env)) { 190 return NULL; 191 } 192 (*env)->SetObjectArrayElement(env, result, 1, zlib_str); 193 if ((*env)->ExceptionCheck(env)) { 194 return NULL; 195 } 196 jstring ssl_str = (*env)->NewStringUTF(env, "android.openssl.version=" OPENSSL_VERSION_TEXT); 197 if ((*env)->ExceptionCheck(env)) { 198 return NULL; 199 } 200 (*env)->SetObjectArrayElement(env, result, 2, ssl_str); 201 if ((*env)->ExceptionCheck(env)) { 202 return NULL; 203 } 204 205 206 const char* library_path = getenv("LD_LIBRARY_PATH"); 207 #if defined(__ANDROID__) 208 if (library_path == NULL) { 209 android_get_LD_LIBRARY_PATH(path, sizeof(path)); 210 library_path = path; 211 } 212 #endif 213 if (library_path == NULL) { 214 library_path = ""; 215 } 216 char* java_path = malloc(strlen("java.library.path=") + strlen(library_path) + 1); 217 strcpy(java_path, "java.library.path="); 218 strcat(java_path, library_path); 219 jstring java_path_str = (*env)->NewStringUTF(env, java_path); 220 free((void*)java_path); 221 if ((*env)->ExceptionCheck(env)) { 222 return NULL; 223 } 224 (*env)->SetObjectArrayElement(env, result, 3, java_path_str); 225 if ((*env)->ExceptionCheck(env)) { 226 return NULL; 227 } 228 229 return result; 230 } 231 System_log(JNIEnv * env,jclass ignored,jchar type,jstring javaMessage,jthrowable exception)232 static void System_log(JNIEnv* env, jclass ignored, jchar type, jstring javaMessage, jthrowable exception) { 233 int priority; 234 switch (type) { 235 case 'D': case 'd': priority = ANDROID_LOG_DEBUG; break; 236 case 'E': case 'e': priority = ANDROID_LOG_ERROR; break; 237 case 'F': case 'f': priority = ANDROID_LOG_FATAL; break; 238 case 'I': case 'i': priority = ANDROID_LOG_INFO; break; 239 case 'S': case 's': priority = ANDROID_LOG_SILENT; break; 240 case 'V': case 'v': priority = ANDROID_LOG_VERBOSE; break; 241 case 'W': case 'w': priority = ANDROID_LOG_WARN; break; 242 default: priority = ANDROID_LOG_DEFAULT; break; 243 } 244 245 WITH_PLATFORM_STRING(env, javaMessage, message) { 246 LOG_PRI(priority, "System", "%s", message); 247 } END_PLATFORM_STRING(env, message); 248 249 if (exception != NULL) { 250 jniLogException(env, priority, "System", exception); 251 } 252 } 253 System_nanoTime()254 static jlong System_nanoTime() { 255 struct timespec now; 256 clock_gettime(CLOCK_MONOTONIC, &now); 257 return now.tv_sec * 1000000000LL + now.tv_nsec; 258 } 259 System_currentTimeMillis()260 static jlong System_currentTimeMillis() { 261 return JVM_CurrentTimeMillis(NULL, NULL); 262 } 263 264 static JNINativeMethod gMethods[] = { 265 NATIVE_METHOD(System, mapLibraryName, "(Ljava/lang/String;)Ljava/lang/String;"), 266 NATIVE_METHOD(System, setErr0, "(Ljava/io/PrintStream;)V"), 267 NATIVE_METHOD(System, setOut0, "(Ljava/io/PrintStream;)V"), 268 NATIVE_METHOD(System, setIn0, "(Ljava/io/InputStream;)V"), 269 NATIVE_METHOD(System, specialProperties, "()[Ljava/lang/String;"), 270 NATIVE_METHOD(System, log, "(CLjava/lang/String;Ljava/lang/Throwable;)V"), 271 CRITICAL_NATIVE_METHOD(System, currentTimeMillis, "()J"), 272 CRITICAL_NATIVE_METHOD(System, nanoTime, "()J"), 273 }; 274 register_java_lang_System(JNIEnv * env)275 void register_java_lang_System(JNIEnv* env) { 276 jniRegisterNativeMethods(env, "java/lang/System", gMethods, NELEM(gMethods)); 277 } 278