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