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#define LOG_TAG "System" 18 19#include "JNIHelp.h" 20#include "JniConstants.h" 21#include "ScopedUtfChars.h" 22#include "cutils/log.h" 23#include "openssl/opensslv.h" 24#include "toStringArray.h" 25#include "zlib.h" 26 27#include <string> 28#include <vector> 29 30#include <limits.h> 31#include <stdlib.h> 32#include <string.h> 33#include <sys/time.h> 34#include <time.h> 35#include <unistd.h> 36 37#if defined(HAVE_ANDROID_OS) 38extern "C" void android_get_LD_LIBRARY_PATH(char*, size_t); 39#endif 40 41static void System_log(JNIEnv* env, jclass, jchar type, jstring javaMessage, jthrowable exception) { 42 ScopedUtfChars message(env, javaMessage); 43 if (message.c_str() == NULL) { 44 // Since this function is used for last-gasp debugging output, be noisy on failure. 45 ALOGE("message.c_str() == NULL"); 46 return; 47 } 48 int priority; 49 switch (type) { 50 case 'D': case 'd': priority = ANDROID_LOG_DEBUG; break; 51 case 'E': case 'e': priority = ANDROID_LOG_ERROR; break; 52 case 'F': case 'f': priority = ANDROID_LOG_FATAL; break; 53 case 'I': case 'i': priority = ANDROID_LOG_INFO; break; 54 case 'S': case 's': priority = ANDROID_LOG_SILENT; break; 55 case 'V': case 'v': priority = ANDROID_LOG_VERBOSE; break; 56 case 'W': case 'w': priority = ANDROID_LOG_WARN; break; 57 default: priority = ANDROID_LOG_DEFAULT; break; 58 } 59 LOG_PRI(priority, LOG_TAG, "%s", message.c_str()); 60 if (exception != NULL) { 61 jniLogException(env, priority, LOG_TAG, exception); 62 } 63} 64 65// Sets a field via JNI. Used for the standard streams, which are read-only otherwise. 66static void System_setFieldImpl(JNIEnv* env, jclass clazz, 67 jstring javaName, jstring javaSignature, jobject object) { 68 ScopedUtfChars name(env, javaName); 69 if (name.c_str() == NULL) { 70 return; 71 } 72 ScopedUtfChars signature(env, javaSignature); 73 if (signature.c_str() == NULL) { 74 return; 75 } 76 jfieldID fieldID = env->GetStaticFieldID(clazz, name.c_str(), signature.c_str()); 77 env->SetStaticObjectField(clazz, fieldID, object); 78} 79 80static jobjectArray System_specialProperties(JNIEnv* env, jclass) { 81 std::vector<std::string> properties; 82 83 char path[PATH_MAX]; 84 properties.push_back(std::string("user.dir=") + getcwd(path, sizeof(path))); 85 86 properties.push_back("android.zlib.version=" ZLIB_VERSION); 87 properties.push_back("android.openssl.version=" OPENSSL_VERSION_TEXT); 88 89 const char* library_path = getenv("LD_LIBRARY_PATH"); 90#if defined(HAVE_ANDROID_OS) 91 if (library_path == NULL) { 92 android_get_LD_LIBRARY_PATH(path, sizeof(path)); 93 library_path = path; 94 } 95#endif 96 if (library_path == NULL) { 97 library_path = ""; 98 } 99 properties.push_back(std::string("java.library.path=") + library_path); 100 101 return toStringArray(env, properties); 102} 103 104static jlong System_currentTimeMillis(JNIEnv*, jclass) { 105 timeval now; 106 gettimeofday(&now, NULL); 107 jlong when = now.tv_sec * 1000LL + now.tv_usec / 1000; 108 return when; 109} 110 111static jlong System_nanoTime(JNIEnv*, jclass) { 112#if defined(HAVE_POSIX_CLOCKS) 113 timespec now; 114 clock_gettime(CLOCK_MONOTONIC, &now); 115 return now.tv_sec * 1000000000LL + now.tv_nsec; 116#else 117 timeval now; 118 gettimeofday(&now, NULL); 119 return static_cast<jlong>(now.tv_sec) * 1000000000LL + now.tv_usec * 1000LL; 120#endif 121} 122 123static jstring System_mapLibraryName(JNIEnv* env, jclass, jstring javaName) { 124 ScopedUtfChars name(env, javaName); 125 if (name.c_str() == NULL) { 126 return NULL; 127 } 128 char* mappedName = NULL; 129 asprintf(&mappedName, OS_SHARED_LIB_FORMAT_STR, name.c_str()); 130 jstring result = env->NewStringUTF(mappedName); 131 free(mappedName); 132 return result; 133} 134 135static JNINativeMethod gMethods[] = { 136 NATIVE_METHOD(System, currentTimeMillis, "!()J"), 137 NATIVE_METHOD(System, log, "(CLjava/lang/String;Ljava/lang/Throwable;)V"), 138 NATIVE_METHOD(System, mapLibraryName, "(Ljava/lang/String;)Ljava/lang/String;"), 139 NATIVE_METHOD(System, nanoTime, "!()J"), 140 NATIVE_METHOD(System, setFieldImpl, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V"), 141 NATIVE_METHOD(System, specialProperties, "()[Ljava/lang/String;"), 142}; 143void register_java_lang_System(JNIEnv* env) { 144 jniRegisterNativeMethods(env, "java/lang/System", gMethods, NELEM(gMethods)); 145} 146