| /* | |
| * Copyright (C) 2020 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include "graphics_jni_helpers.h" | |
| #include <GraphicsJNI.h> | |
| #include <SkGraphics.h> | |
| #include <sstream> | |
| #include <iostream> | |
| #include <unicode/putil.h> | |
| #include <unordered_map> | |
| #include <vector> | |
| using namespace std; | |
| /* | |
| * This is responsible for setting up the JNI environment for communication between | |
| * the Java and native parts of layoutlib, including registering native methods. | |
| * This is mostly achieved by copying the way it is done in the platform | |
| * (see AndroidRuntime.cpp). | |
| */ | |
| static JavaVM* javaVM; | |
| extern int register_android_graphics_Bitmap(JNIEnv*); | |
| extern int register_android_graphics_BitmapFactory(JNIEnv*); | |
| extern int register_android_graphics_ByteBufferStreamAdaptor(JNIEnv* env); | |
| extern int register_android_graphics_CreateJavaOutputStreamAdaptor(JNIEnv* env); | |
| extern int register_android_graphics_Graphics(JNIEnv* env); | |
| extern int register_android_graphics_ImageDecoder(JNIEnv*); | |
| extern int register_android_graphics_Interpolator(JNIEnv* env); | |
| extern int register_android_graphics_MaskFilter(JNIEnv* env); | |
| extern int register_android_graphics_NinePatch(JNIEnv*); | |
| extern int register_android_graphics_PathEffect(JNIEnv* env); | |
| extern int register_android_graphics_Shader(JNIEnv* env); | |
| extern int register_android_graphics_RenderEffect(JNIEnv* env); | |
| extern int register_android_graphics_Typeface(JNIEnv* env); | |
| namespace android { | |
| extern int register_android_graphics_Canvas(JNIEnv* env); | |
| extern int register_android_graphics_ColorFilter(JNIEnv* env); | |
| extern int register_android_graphics_ColorSpace(JNIEnv* env); | |
| extern int register_android_graphics_DrawFilter(JNIEnv* env); | |
| extern int register_android_graphics_FontFamily(JNIEnv* env); | |
| extern int register_android_graphics_Matrix(JNIEnv* env); | |
| extern int register_android_graphics_Paint(JNIEnv* env); | |
| extern int register_android_graphics_Path(JNIEnv* env); | |
| extern int register_android_graphics_PathMeasure(JNIEnv* env); | |
| extern int register_android_graphics_Picture(JNIEnv* env); | |
| //extern int register_android_graphics_Region(JNIEnv* env); | |
| extern int register_android_graphics_animation_NativeInterpolatorFactory(JNIEnv* env); | |
| extern int register_android_graphics_animation_RenderNodeAnimator(JNIEnv* env); | |
| extern int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env); | |
| extern int register_android_graphics_drawable_VectorDrawable(JNIEnv* env); | |
| extern int register_android_graphics_fonts_Font(JNIEnv* env); | |
| extern int register_android_graphics_fonts_FontFamily(JNIEnv* env); | |
| extern int register_android_graphics_text_LineBreaker(JNIEnv* env); | |
| extern int register_android_graphics_text_MeasuredText(JNIEnv* env); | |
| extern int register_android_util_PathParser(JNIEnv* env); | |
| extern int register_android_view_RenderNode(JNIEnv* env); | |
| extern int register_android_view_DisplayListCanvas(JNIEnv* env); | |
| #define REG_JNI(name) { name } | |
| struct RegJNIRec { | |
| int (*mProc)(JNIEnv*); | |
| }; | |
| // 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 'native_classes' System property | |
| static const std::unordered_map<std::string, RegJNIRec> gRegJNIMap = { | |
| {"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.RenderNode", REG_JNI(register_android_view_RenderNode)}, | |
| {"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.Interpolator", REG_JNI(register_android_graphics_Interpolator)}, | |
| {"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.RecordingCanvas", REG_JNI(register_android_view_DisplayListCanvas)}, | |
| // {"android.graphics.Region", REG_JNI(register_android_graphics_Region)}, | |
| {"android.graphics.Shader", REG_JNI(register_android_graphics_Shader)}, | |
| {"android.graphics.RenderEffect", REG_JNI(register_android_graphics_RenderEffect)}, | |
| {"android.graphics.Typeface", REG_JNI(register_android_graphics_Typeface)}, | |
| {"android.graphics.animation.NativeInterpolatorFactory", | |
| REG_JNI(register_android_graphics_animation_NativeInterpolatorFactory)}, | |
| {"android.graphics.animation.RenderNodeAnimator", | |
| REG_JNI(register_android_graphics_animation_RenderNodeAnimator)}, | |
| {"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)}, | |
| }; | |
| 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; | |
| } | |
| } | |
| return 0; | |
| } | |
| 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; | |
| void init_android_graphics() { | |
| SkGraphics::Init(); | |
| } | |
| int register_android_graphics_classes(JNIEnv *env) { | |
| JavaVM* vm = nullptr; | |
| env->GetJavaVM(&vm); | |
| GraphicsJNI::setJavaVM(vm); | |
| // 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;"); | |
| // 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; | |
| } | |
| return 0; | |
| } | |
| void zygote_preload_graphics() { } |