1 /*
2 * Copyright (C) 2018 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 #include <android-base/logging.h>
18 #include <android-base/properties.h>
19 #include <android/graphics/jni_runtime.h>
20 #include <android_runtime/AndroidRuntime.h>
21 #include <jni_wrappers.h>
22 #include <nativehelper/JNIHelp.h>
23 #include <nativehelper/ScopedUtfChars.h>
24 #include <nativehelper/jni_macros.h>
25 #include <unicode/locid.h>
26 #include <unicode/putil.h>
27 #include <unicode/udata.h>
28
29 #include <clocale>
30 #include <sstream>
31 #include <unordered_map>
32 #include <vector>
33
34 #ifdef _WIN32
35 #include <windows.h>
36 #else
37 #include <fcntl.h>
38 #include <sys/mman.h>
39 #include <sys/stat.h>
40 #endif
41
42 using namespace std;
43
44 /*
45 * This is responsible for setting up the JNI environment for communication between
46 * the Java and native parts of layoutlib, including registering native methods.
47 * This is mostly achieved by copying the way it is done in the platform
48 * (see AndroidRuntime.cpp).
49 */
50
51 extern int register_android_os_Binder(JNIEnv* env);
52 extern int register_libcore_util_NativeAllocationRegistry(JNIEnv* env);
53
54 typedef void (*FreeFunction)(void*);
55
NativeAllocationRegistry_applyFreeFunction(JNIEnv *,jclass,jlong freeFunction,jlong ptr)56 static void NativeAllocationRegistry_applyFreeFunction(JNIEnv*, jclass, jlong freeFunction,
57 jlong ptr) {
58 void* nativePtr = reinterpret_cast<void*>(static_cast<uintptr_t>(ptr));
59 FreeFunction nativeFreeFunction =
60 reinterpret_cast<FreeFunction>(static_cast<uintptr_t>(freeFunction));
61 nativeFreeFunction(nativePtr);
62 }
63
64 static JNINativeMethod gMethods[] = {
65 NATIVE_METHOD(NativeAllocationRegistry, applyFreeFunction, "(JJ)V"),
66 };
67
register_libcore_util_NativeAllocationRegistry(JNIEnv * env)68 int register_libcore_util_NativeAllocationRegistry(JNIEnv* env) {
69 return android::RegisterMethodsOrDie(env, "libcore/util/NativeAllocationRegistry", gMethods,
70 NELEM(gMethods));
71 }
72
73 namespace android {
74
75 extern int register_android_animation_PropertyValuesHolder(JNIEnv* env);
76 extern int register_android_content_AssetManager(JNIEnv* env);
77 extern int register_android_content_StringBlock(JNIEnv* env);
78 extern int register_android_content_XmlBlock(JNIEnv* env);
79 extern int register_android_content_res_ApkAssets(JNIEnv* env);
80 extern int register_android_database_CursorWindow(JNIEnv* env);
81 extern int register_android_database_SQLiteConnection(JNIEnv* env);
82 extern int register_android_database_SQLiteGlobal(JNIEnv* env);
83 extern int register_android_database_SQLiteDebug(JNIEnv* env);
84 extern int register_android_database_SQLiteRawStatement(JNIEnv* env);
85 extern int register_android_os_FileObserver(JNIEnv* env);
86 extern int register_android_os_MessageQueue(JNIEnv* env);
87 extern int register_android_os_Parcel(JNIEnv* env);
88 extern int register_android_os_SystemClock(JNIEnv* env);
89 extern int register_android_os_SystemProperties(JNIEnv* env);
90 extern int register_android_text_AndroidCharacter(JNIEnv* env);
91 extern int register_android_text_Hyphenator(JNIEnv* env);
92 extern int register_android_util_EventLog(JNIEnv* env);
93 extern int register_android_util_Log(JNIEnv* env);
94 extern int register_android_util_jar_StrictJarFile(JNIEnv* env);
95 extern int register_android_view_KeyCharacterMap(JNIEnv* env);
96 extern int register_android_view_KeyEvent(JNIEnv* env);
97 extern int register_android_view_InputDevice(JNIEnv* env);
98 extern int register_android_view_MotionEvent(JNIEnv* env);
99 extern int register_android_view_Surface(JNIEnv* env);
100 extern int register_android_view_ThreadedRenderer(JNIEnv* env);
101 extern int register_android_graphics_HardwareBufferRenderer(JNIEnv* env);
102 extern int register_android_view_VelocityTracker(JNIEnv* env);
103 extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv* env);
104
105 #define REG_JNI(name) \
106 { name }
107 struct RegJNIRec {
108 int (*mProc)(JNIEnv*);
109 };
110
111 // Map of all possible class names to register to their corresponding JNI registration function
112 // pointer The actual list of registered classes will be determined at runtime via the
113 // 'native_classes' System property
114 static const std::unordered_map<std::string, RegJNIRec> gRegJNIMap = {
115 {"android.animation.PropertyValuesHolder",
116 REG_JNI(register_android_animation_PropertyValuesHolder)},
117 {"android.content.res.ApkAssets", REG_JNI(register_android_content_res_ApkAssets)},
118 {"android.content.res.AssetManager", REG_JNI(register_android_content_AssetManager)},
119 {"android.content.res.StringBlock", REG_JNI(register_android_content_StringBlock)},
120 {"android.content.res.XmlBlock", REG_JNI(register_android_content_XmlBlock)},
121 #ifdef __linux__
122 {"android.database.CursorWindow", REG_JNI(register_android_database_CursorWindow)},
123 {"android.database.sqlite.SQLiteConnection",
124 REG_JNI(register_android_database_SQLiteConnection)},
125 {"android.database.sqlite.SQLiteGlobal", REG_JNI(register_android_database_SQLiteGlobal)},
126 {"android.database.sqlite.SQLiteDebug", REG_JNI(register_android_database_SQLiteDebug)},
127 {"android.database.sqlite.SQLiteRawStatement",
128 REG_JNI(register_android_database_SQLiteRawStatement)},
129 {"android.os.Binder", REG_JNI(register_android_os_Binder)},
130 {"android.os.FileObserver", REG_JNI(register_android_os_FileObserver)},
131 {"android.os.MessageQueue", REG_JNI(register_android_os_MessageQueue)},
132 {"android.os.Parcel", REG_JNI(register_android_os_Parcel)},
133 #endif
134 {"android.os.SystemClock", REG_JNI(register_android_os_SystemClock)},
135 {"android.os.SystemProperties", REG_JNI(register_android_os_SystemProperties)},
136 {"android.text.AndroidCharacter", REG_JNI(register_android_text_AndroidCharacter)},
137 {"android.text.Hyphenator", REG_JNI(register_android_text_Hyphenator)},
138 {"android.util.EventLog", REG_JNI(register_android_util_EventLog)},
139 {"android.util.Log", REG_JNI(register_android_util_Log)},
140 {"android.util.jar.StrictJarFile", REG_JNI(register_android_util_jar_StrictJarFile)},
141 {"android.view.KeyCharacterMap", REG_JNI(register_android_view_KeyCharacterMap)},
142 {"android.view.KeyEvent", REG_JNI(register_android_view_KeyEvent)},
143 {"android.view.InputDevice", REG_JNI(register_android_view_InputDevice)},
144 {"android.view.MotionEvent", REG_JNI(register_android_view_MotionEvent)},
145 {"android.view.Surface", REG_JNI(register_android_view_Surface)},
146 {"android.view.VelocityTracker", REG_JNI(register_android_view_VelocityTracker)},
147 {"com.android.internal.util.VirtualRefBasePtr",
148 REG_JNI(register_com_android_internal_util_VirtualRefBasePtr)},
149 {"libcore.util.NativeAllocationRegistry",
150 REG_JNI(register_libcore_util_NativeAllocationRegistry)},
151 };
152
register_jni_procs(const std::unordered_map<std::string,RegJNIRec> & jniRegMap,const vector<string> & classesToRegister,JNIEnv * env)153 static int register_jni_procs(const std::unordered_map<std::string, RegJNIRec>& jniRegMap,
154 const vector<string>& classesToRegister, JNIEnv* env) {
155 for (const string& className : classesToRegister) {
156 if (jniRegMap.at(className).mProc(env) < 0) {
157 return -1;
158 }
159 }
160
161 return 0;
162 }
163
parseCsv(const string & csvString)164 static vector<string> parseCsv(const string& csvString) {
165 vector<string> result;
166 istringstream stream(csvString);
167 string segment;
168 while (getline(stream, segment, ',')) {
169 result.push_back(segment);
170 }
171 return result;
172 }
173
174 // This method has been copied/adapted from system/core/init/property_service.cpp
175 // If the ro.product.cpu.abilist* properties have not been explicitly
176 // set, derive them from ro.system.product.cpu.abilist* properties.
property_initialize_ro_cpu_abilist()177 static void property_initialize_ro_cpu_abilist() {
178 const std::string EMPTY = "";
179 const char* kAbilistProp = "ro.product.cpu.abilist";
180 const char* kAbilist32Prop = "ro.product.cpu.abilist32";
181 const char* kAbilist64Prop = "ro.product.cpu.abilist64";
182
183 // If the properties are defined explicitly, just use them.
184 if (base::GetProperty(kAbilistProp, EMPTY) != EMPTY) {
185 return;
186 }
187
188 std::string abilist32_prop_val;
189 std::string abilist64_prop_val;
190 const auto abilist32_prop = "ro.system.product.cpu.abilist32";
191 const auto abilist64_prop = "ro.system.product.cpu.abilist64";
192 abilist32_prop_val = base::GetProperty(abilist32_prop, EMPTY);
193 abilist64_prop_val = base::GetProperty(abilist64_prop, EMPTY);
194
195 // Merge ABI lists for ro.product.cpu.abilist
196 auto abilist_prop_val = abilist64_prop_val;
197 if (abilist32_prop_val != EMPTY) {
198 if (abilist_prop_val != EMPTY) {
199 abilist_prop_val += ",";
200 }
201 abilist_prop_val += abilist32_prop_val;
202 }
203
204 // Set these properties
205 const std::pair<const char*, const std::string&> set_prop_list[] = {
206 {kAbilistProp, abilist_prop_val},
207 {kAbilist32Prop, abilist32_prop_val},
208 {kAbilist64Prop, abilist64_prop_val},
209 };
210 for (const auto& [prop, prop_val] : set_prop_list) {
211 base::SetProperty(prop, prop_val);
212 }
213 }
214
mmapFile(const char * dataFilePath)215 static void* mmapFile(const char* dataFilePath) {
216 #ifdef _WIN32
217 // Windows needs file path in wide chars to handle unicode file paths
218 int size = MultiByteToWideChar(CP_UTF8, 0, dataFilePath, -1, NULL, 0);
219 std::vector<wchar_t> wideDataFilePath(size);
220 MultiByteToWideChar(CP_UTF8, 0, dataFilePath, -1, wideDataFilePath.data(), size);
221 HANDLE file =
222 CreateFileW(wideDataFilePath.data(), GENERIC_READ, FILE_SHARE_READ, nullptr,
223 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, nullptr);
224 if ((HANDLE)INVALID_HANDLE_VALUE == file) {
225 return nullptr;
226 }
227
228 struct CloseHandleWrapper {
229 void operator()(HANDLE h) {
230 CloseHandle(h);
231 }
232 };
233 std::unique_ptr<void, CloseHandleWrapper> mmapHandle(
234 CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr));
235 if (!mmapHandle) {
236 return nullptr;
237 }
238 return MapViewOfFile(mmapHandle.get(), FILE_MAP_READ, 0, 0, 0);
239 #else
240 int fd = open(dataFilePath, O_RDONLY);
241 if (fd == -1) {
242 return nullptr;
243 }
244
245 struct stat sb;
246 if (fstat(fd, &sb) == -1) {
247 close(fd);
248 return nullptr;
249 }
250
251 void* addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
252 if (addr == MAP_FAILED) {
253 close(fd);
254 return nullptr;
255 }
256
257 close(fd);
258 return addr;
259 #endif
260 }
261
262 // returns result from java.lang.System.getProperty
getJavaProperty(JNIEnv * env,const char * property_name,const char * defaultValue="")263 static string getJavaProperty(JNIEnv* env, const char* property_name,
264 const char* defaultValue = "") {
265 jclass system = FindClassOrDie(env, "java/lang/System");
266 jmethodID getPropertyMethod =
267 GetStaticMethodIDOrDie(env, system, "getProperty",
268 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
269
270 auto jString = (jstring)env->CallStaticObjectMethod(system, getPropertyMethod,
271 env->NewStringUTF(property_name),
272 env->NewStringUTF(defaultValue));
273 ScopedUtfChars chars(env, jString);
274 return string(chars.c_str());
275 }
276
loadIcuData(string icuPath)277 static void loadIcuData(string icuPath) {
278 void* addr = mmapFile(icuPath.c_str());
279 UErrorCode err = U_ZERO_ERROR;
280 udata_setCommonData(addr, &err);
281 if (err != U_ZERO_ERROR) {
282 ALOGE("Unable to load ICU data\n");
283 }
284 }
285
286 // Loads the ICU data file from the location specified in properties.
287 // First try specified in the system property ro.icu.data.path,
288 // then fallback to java property icu.data.path
loadIcuData()289 static void loadIcuData() {
290 JNIEnv* env = AndroidRuntime::getJNIEnv();
291 string icuPath = base::GetProperty("ro.icu.data.path", "");
292 if (!icuPath.empty()) {
293 loadIcuData(icuPath);
294 } else {
295 // fallback to read from java.lang.System.getProperty
296 string icuPathFromJava = getJavaProperty(env, "icu.data.path");
297 if (!icuPathFromJava.empty()) {
298 loadIcuData(icuPathFromJava);
299 }
300 }
301
302 // Check for the ICU default locale property. In Libcore, the default ICU
303 // locale is set when ICU.setDefaultLocale is called, which is called by
304 // Libcore's implemenentation of Java's Locale.setDefault. The default
305 // locale is used in cases such as when ucol_open(NULL, ...) is called, for
306 // example in SQLite's 'COLLATE UNICODE'.
307 string icuLocaleDefault = getJavaProperty(env, "icu.locale.default");
308 if (!icuLocaleDefault.empty()) {
309 UErrorCode status = U_ZERO_ERROR;
310 icu::Locale locale = icu::Locale::forLanguageTag(icuLocaleDefault.c_str(), status);
311 if (U_SUCCESS(status)) {
312 icu::Locale::setDefault(locale, status);
313 }
314 if (U_FAILURE(status)) {
315 fprintf(stderr, "Failed to set the ICU default locale to '%s' (error code %d)\n",
316 icuLocaleDefault.c_str(), status);
317 }
318 }
319 }
320
register_android_core_classes(JNIEnv * env)321 static int register_android_core_classes(JNIEnv* env) {
322 string nativesClassesString = getJavaProperty(env, "core_native_classes");
323 vector<string> classesToRegister = parseCsv(nativesClassesString);
324
325 if (register_jni_procs(gRegJNIMap, classesToRegister, env) < 0) {
326 return JNI_ERR;
327 }
328
329 return 0;
330 }
331
332 // Called right before aborting by LOG_ALWAYS_FATAL. Print the pending exception.
abort_handler(const char * abort_message)333 void abort_handler(const char* abort_message) {
334 ALOGE("About to abort the process...");
335
336 JNIEnv* env = AndroidRuntime::getJNIEnv();
337 if (env == nullptr) {
338 ALOGE("vm->GetEnv() failed");
339 return;
340 }
341 if (env->ExceptionOccurred() != NULL) {
342 ALOGE("Pending exception:");
343 env->ExceptionDescribe();
344 }
345 ALOGE("Aborting because: %s", abort_message);
346 }
347
348 // ------------------ Host implementation of AndroidRuntime ------------------
349
350 /*static*/ JavaVM* AndroidRuntime::mJavaVM;
351
registerNativeMethods(JNIEnv * env,const char * className,const JNINativeMethod * gMethods,int numMethods)352 /*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env, const char* className,
353 const JNINativeMethod* gMethods,
354 int numMethods) {
355 return jniRegisterNativeMethods(env, className, gMethods, numMethods);
356 }
357
getJNIEnv()358 /*static*/ JNIEnv* AndroidRuntime::getJNIEnv() {
359 JNIEnv* env;
360 JavaVM* vm = AndroidRuntime::getJavaVM();
361 if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {
362 return nullptr;
363 }
364 return env;
365 }
366
getJavaVM()367 /*static*/ JavaVM* AndroidRuntime::getJavaVM() {
368 return mJavaVM;
369 }
370
startReg(JNIEnv * env)371 /*static*/ int AndroidRuntime::startReg(JNIEnv* env) {
372 if (register_android_core_classes(env) < 0) {
373 return JNI_ERR;
374 }
375 if (register_android_graphics_classes(env) < 0) {
376 return JNI_ERR;
377 }
378 return 0;
379 }
380
onVmCreated(JNIEnv * env)381 void AndroidRuntime::onVmCreated(JNIEnv* env) {
382 env->GetJavaVM(&mJavaVM);
383 }
384
onStarted()385 void AndroidRuntime::onStarted() {
386 property_initialize_ro_cpu_abilist();
387 loadIcuData();
388
389 // Use English locale for number format to ensure correct parsing of floats when using strtof
390 setlocale(LC_NUMERIC, "en_US.UTF-8");
391 }
392
start(const char * className,const Vector<String8> & options,bool zygote)393 void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) {
394 JNIEnv* env = AndroidRuntime::getJNIEnv();
395
396 auto method_binding_format = getJavaProperty(env, "method_binding_format");
397
398 setJniMethodFormat(method_binding_format);
399
400 // Register native functions.
401 if (startReg(env) < 0) {
402 ALOGE("Unable to register all android native methods\n");
403 }
404 onStarted();
405 }
406
AndroidRuntime(char * argBlockStart,const size_t argBlockLength)407 AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength)
408 : mExitWithoutCleanup(false), mArgBlockStart(argBlockStart), mArgBlockLength(argBlockLength) {
409 init_android_graphics();
410 }
411
~AndroidRuntime()412 AndroidRuntime::~AndroidRuntime() {}
413
414 // Version of AndroidRuntime to run on host
415 class HostRuntime : public AndroidRuntime {
416 public:
HostRuntime()417 HostRuntime() : AndroidRuntime(nullptr, 0) {}
418
onVmCreated(JNIEnv * env)419 void onVmCreated(JNIEnv* env) override {
420 AndroidRuntime::onVmCreated(env);
421 // initialize logging, so ANDROD_LOG_TAGS env variable is respected
422 android::base::InitLogging(nullptr, android::base::StderrLogger, abort_handler);
423 }
424
onStarted()425 void onStarted() override {
426 AndroidRuntime::onStarted();
427 }
428 };
429
430 } // namespace android
431
432 using namespace android;
433
JNI_OnLoad(JavaVM * vm,void *)434 JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
435 JNIEnv* env = nullptr;
436 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
437 return JNI_ERR;
438 }
439
440 string useBaseHostRuntime = getJavaProperty(env, "use_base_native_hostruntime", "true");
441 if (useBaseHostRuntime == "true") {
442 Vector<String8> args;
443 HostRuntime runtime;
444
445 runtime.onVmCreated(env);
446 runtime.start("HostRuntime", args, false);
447 }
448
449 return JNI_VERSION_1_6;
450 }
451