xref: /aosp_15_r20/frameworks/base/core/jni/platform/host/HostRuntime.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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