diff options
| -rw-r--r-- | core/jni/LayoutlibLoader.cpp | 144 |
1 files changed, 84 insertions, 60 deletions
diff --git a/core/jni/LayoutlibLoader.cpp b/core/jni/LayoutlibLoader.cpp index 94064c1d28be..b17280908e81 100644 --- a/core/jni/LayoutlibLoader.cpp +++ b/core/jni/LayoutlibLoader.cpp @@ -17,7 +17,10 @@ #include "jni.h" #include "core_jni_helpers.h" +#include <sstream> +#include <iostream> #include <unicode/putil.h> +#include <unordered_map> #include <vector> using namespace std; @@ -72,47 +75,51 @@ struct RegJNIRec { int (*mProc)(JNIEnv*); }; -static const RegJNIRec gRegJNI[] = { - REG_JNI(register_android_animation_PropertyValuesHolder), - REG_JNI(register_android_graphics_Bitmap), - REG_JNI(register_android_graphics_BitmapFactory), - REG_JNI(register_android_graphics_ByteBufferStreamAdaptor), - REG_JNI(register_android_graphics_Canvas), - REG_JNI(register_android_graphics_ColorFilter), - REG_JNI(register_android_graphics_ColorSpace), - REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor), - REG_JNI(register_android_graphics_DrawFilter), - REG_JNI(register_android_graphics_FontFamily), - REG_JNI(register_android_graphics_Graphics), - REG_JNI(register_android_graphics_ImageDecoder), - REG_JNI(register_android_graphics_MaskFilter), - REG_JNI(register_android_graphics_Matrix), - REG_JNI(register_android_graphics_NinePatch), - REG_JNI(register_android_graphics_Paint), - REG_JNI(register_android_graphics_Path), - REG_JNI(register_android_graphics_PathEffect), - REG_JNI(register_android_graphics_PathMeasure), - REG_JNI(register_android_graphics_Picture), - REG_JNI(register_android_graphics_Region), - REG_JNI(register_android_graphics_Shader), - REG_JNI(register_android_graphics_Typeface), - REG_JNI(register_android_graphics_drawable_AnimatedVectorDrawable), - REG_JNI(register_android_graphics_drawable_VectorDrawable), - REG_JNI(register_android_graphics_fonts_Font), - REG_JNI(register_android_graphics_fonts_FontFamily), - REG_JNI(register_android_graphics_text_LineBreaker), - REG_JNI(register_android_graphics_text_MeasuredText), - REG_JNI(register_android_util_PathParser), - REG_JNI(register_com_android_internal_util_VirtualRefBasePtr), - REG_JNI(register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper), +// Map of all possible class names to register to their corresponding JNI registration function pointer +// The actual list of registered classes will be determined at runtime via the com.android.tools.layoutlib.create.NativeConfig class +static const std::unordered_map<std::string, RegJNIRec> gRegJNIMap = { + {"android.animation.PropertyValuesHolder", REG_JNI(register_android_animation_PropertyValuesHolder)}, + {"android.graphics.Bitmap", REG_JNI(register_android_graphics_Bitmap)}, + {"android.graphics.BitmapFactory", REG_JNI(register_android_graphics_BitmapFactory)}, + {"android.graphics.ByteBufferStreamAdaptor", REG_JNI(register_android_graphics_ByteBufferStreamAdaptor)}, + {"android.graphics.Canvas", REG_JNI(register_android_graphics_Canvas)}, + {"android.graphics.ColorFilter", REG_JNI(register_android_graphics_ColorFilter)}, + {"android.graphics.ColorSpace", REG_JNI(register_android_graphics_ColorSpace)}, + {"android.graphics.CreateJavaOutputStreamAdaptor", REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor)}, + {"android.graphics.DrawFilter", REG_JNI(register_android_graphics_DrawFilter)}, + {"android.graphics.FontFamily", REG_JNI(register_android_graphics_FontFamily)}, + {"android.graphics.Graphics", REG_JNI(register_android_graphics_Graphics)}, + {"android.graphics.ImageDecoder", REG_JNI(register_android_graphics_ImageDecoder)}, + {"android.graphics.MaskFilter", REG_JNI(register_android_graphics_MaskFilter)}, + {"android.graphics.Matrix", REG_JNI(register_android_graphics_Matrix)}, + {"android.graphics.NinePatch", REG_JNI(register_android_graphics_NinePatch)}, + {"android.graphics.Paint", REG_JNI(register_android_graphics_Paint)}, + {"android.graphics.Path", REG_JNI(register_android_graphics_Path)}, + {"android.graphics.PathEffect", REG_JNI(register_android_graphics_PathEffect)}, + {"android.graphics.PathMeasure", REG_JNI(register_android_graphics_PathMeasure)}, + {"android.graphics.Picture", REG_JNI(register_android_graphics_Picture)}, + {"android.graphics.Region", REG_JNI(register_android_graphics_Region)}, + {"android.graphics.Shader", REG_JNI(register_android_graphics_Shader)}, + {"android.graphics.Typeface", REG_JNI(register_android_graphics_Typeface)}, + {"android.graphics.drawable.AnimatedVectorDrawable", REG_JNI(register_android_graphics_drawable_AnimatedVectorDrawable)}, + {"android.graphics.drawable.VectorDrawable", REG_JNI(register_android_graphics_drawable_VectorDrawable)}, + {"android.graphics.fonts.Font", REG_JNI(register_android_graphics_fonts_Font)}, + {"android.graphics.fonts.FontFamily", REG_JNI(register_android_graphics_fonts_FontFamily)}, + {"android.graphics.text.LineBreaker", REG_JNI(register_android_graphics_text_LineBreaker)}, + {"android.graphics.text.MeasuredText", REG_JNI(register_android_graphics_text_MeasuredText)}, + {"android.util.PathParser", REG_JNI(register_android_util_PathParser)}, + {"com.android.internal.util.VirtualRefBasePtr", REG_JNI(register_com_android_internal_util_VirtualRefBasePtr)}, + {"com.android.internal.view.animation.NativeInterpolatorFactoryHelper", REG_JNI(register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper)}, }; // Vector to store the names of classes that need delegates of their native methods static vector<string> classesToDelegate; -static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env) { - for (size_t i = 0; i < count; i++) { - if (array[i].mProc(env) < 0) { +static int register_jni_procs(const std::unordered_map<std::string, RegJNIRec>& jniRegMap, + const vector<string>& classesToRegister, JNIEnv* env) { + + for (const string& className : classesToRegister) { + if (jniRegMap.at(className).mProc(env) < 0) { return -1; } } @@ -146,12 +153,10 @@ int AndroidRuntime::registerNativeMethods(JNIEnv* env, } jclass clazz = env->FindClass(className); - return env->RegisterNatives(clazz, gMethods, numMethods); } -JNIEnv* AndroidRuntime::getJNIEnv() -{ +JNIEnv* AndroidRuntime::getJNIEnv() { JNIEnv* env; if (javaVM->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) return nullptr; @@ -162,6 +167,25 @@ JavaVM* AndroidRuntime::getJavaVM() { return javaVM; } +static vector<string> parseCsv(const string& csvString) { + vector<string> result; + istringstream stream(csvString); + string segment; + while(getline(stream, segment, ',')) + { + result.push_back(segment); + } + return result; +} + +static vector<string> parseCsv(JNIEnv* env, jstring csvJString) { + const char* charArray = env->GetStringUTFChars(csvJString, 0); + string csvString(charArray); + vector<string> result = parseCsv(csvString); + env->ReleaseStringUTFChars(csvJString, charArray); + return result; +} + } // namespace android using namespace android; @@ -173,32 +197,32 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { return JNI_ERR; } - // Get the names of classes that have to delegate their native methods - - jclass createInfo = FindClassOrDie(env, "com/android/tools/layoutlib/create/NativeConfig"); - jfieldID arrayId = GetStaticFieldIDOrDie(env, createInfo, - "DELEGATE_CLASS_NATIVES_TO_NATIVES", "[Ljava/lang/String;"); - jobjectArray array = (jobjectArray) env->GetStaticObjectField(createInfo, arrayId); - jsize size = env->GetArrayLength(array); - - for (int i=0; i < size; ++i) { - jstring string = (jstring) env->GetObjectArrayElement(array, i); - const char* charArray = env->GetStringUTFChars(string, 0); - std::string className = std::string(charArray); - std::replace(className.begin(), className.end(), '.', '/'); - classesToDelegate.push_back(className); - env->ReleaseStringUTFChars(string, charArray); - } + // Configuration is stored as java System properties. + // Get a reference to System.getProperty + jclass system = FindClassOrDie(env, "java/lang/System"); + jmethodID getPropertyMethod = GetStaticMethodIDOrDie(env, system, "getProperty", + "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); - if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { + // Get the names of classes that have to delegate their native methods + auto delegateNativesToNativesString = + (jstring) env->CallStaticObjectMethod(system, + getPropertyMethod, env->NewStringUTF("delegate_natives_to_natives"), + env->NewStringUTF("")); + classesToDelegate = parseCsv(env, delegateNativesToNativesString); + + // Get the names of classes that need to register their native methods + auto nativesClassesJString = + (jstring) env->CallStaticObjectMethod(system, + getPropertyMethod, env->NewStringUTF("native_classes"), + env->NewStringUTF("")); + vector<string> classesToRegister = parseCsv(env, nativesClassesJString); + + if (register_jni_procs(gRegJNIMap, classesToRegister, env) < 0) { return JNI_ERR; } // Set the location of ICU data - jclass system = FindClassOrDie(env, "java/lang/System"); - jmethodID getPropertyMethod = GetStaticMethodIDOrDie(env, system, "getProperty", - "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); - jstring stringPath = (jstring) (jstring) env->CallStaticObjectMethod(system, + auto stringPath = (jstring) env->CallStaticObjectMethod(system, getPropertyMethod, env->NewStringUTF("icu.dir"), env->NewStringUTF("")); const char* path = env->GetStringUTFChars(stringPath, 0); |