• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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