本帖对Android framework层的API函数与其对应本地方法的映射、注册原理进行了介绍,通过本文,应该会对我们频繁调用的Android API的调用过程及实现原理有更深一步的认识。
我们知道,Android平台是Java、C/C++等多种混合语言写成的,我们在使用Android SDK提供的framework层的API来进行应用开发时通常调用的是Java方法,而实际上,这些Java API很多时候只是一个入口,方法功能的真正实现是通过JNI调用到framework层的native本地方法来实现的。比如,我们在使用Canvas的drawBitmap方法来绘制图片时,drawBitmap的真正实现就是通过JNI调用C++的同名方法来实现的。
下面,我们通过开机启动后本地方法的注册流程来具体的介绍Android API与对应本地方法究竟是如何关联起来的。
Android在开机启动后,经过一系列的加载流程,将进入\frameworks\base\cmds\ app_process\ App_main.cpp的main()方法,在main()方法中,会调用\frameworks\base\core\jni \AndroidRuntime.cpp的start()方法。事实上,Android API与本地方法的注册关联主要就是在AndroidRuntime.cpp模块里完成的。
在AndroidRuntime.cpp的start()方法中,会经过如下的调用流程,即:
void AndroidRuntime::start() 
void AndroidRuntime::start(const char* className, const bool startSystemServer)
int AndroidRuntime::startReg(JNIEnv* env) 
其中,startReg函数主要就是用来进行函数注册的。我们深入到该函数内部,可以看到如下的代码片段:
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
好了,流程介绍到这里,我们已经定位到了Android API与本地方法的注册关联的关键之处,实际上,API与本地方法的注册关键就是在此处完成的。标记为红色的register_jni_procs及其参数gRegJNI是注册关联的两大要素,下面我们对其分别作具体分析。
首先看gRegJNI的定义:
static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_android_debug_JNITest),
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_android_os_SystemClock),
    REG_JNI(register_android_util_EventLog),
    REG_JNI(register_android_util_Log),
    REG_JNI(register_android_util_FloatMath),
    REG_JNI(register_android_text_format_Time),
    REG_JNI(register_android_pim_EventRecurrence),
    REG_JNI(register_android_content_AssetManager),
    REG_JNI(register_android_content_StringBlock),
    REG_JNI(register_android_content_XmlBlock),
    REG_JNI(register_android_emoji_EmojiFactory),
    REG_JNI(register_android_security_Md5MessageDigest),
    REG_JNI(register_android_text_AndroidCharacter),
    REG_JNI(register_android_text_AndroidBidi),
    REG_JNI(register_android_text_KeyCharacterMap),
    REG_JNI(register_android_os_Process),
    REG_JNI(register_android_os_Binder),
    REG_JNI(register_android_view_Display),
    REG_JNI(register_android_nio_utils),
    REG_JNI(register_android_graphics_PixelFormat),
    REG_JNI(register_android_graphics_Graphics),
    REG_JNI(register_android_view_Surface),
    REG_JNI(register_android_view_ViewRoot),
    REG_JNI(register_com_google_android_gles_jni_EGLImpl),
    REG_JNI(register_com_google_android_gles_jni_GLImpl),
    REG_JNI(register_android_opengl_jni_GLES10),
    REG_JNI(register_android_opengl_jni_GLES10Ext),
    REG_JNI(register_android_opengl_jni_GLES11),
    REG_JNI(register_android_opengl_jni_GLES11Ext),
    REG_JNI(register_android_opengl_jni_GLES20),    REG_JNI(register_android_graphics_Bitmap),
    REG_JNI(register_android_graphics_BitmapFactory),
    REG_JNI(register_android_graphics_BitmapRegionDecoder),
    REG_JNI(register_android_graphics_Camera),
    REG_JNI(register_android_graphics_Canvas),
    REG_JNI(register_android_graphics_ColorFilter),
    REG_JNI(register_android_graphics_DrawFilter),
    REG_JNI(register_android_graphics_Interpolator),
    REG_JNI(register_android_graphics_LayerRasterizer),
    REG_JNI(register_android_graphics_MaskFilter),
    REG_JNI(register_android_graphics_Matrix),
    REG_JNI(register_android_graphics_Movie),
    REG_JNI(register_android_graphics_NinePatch),
    REG_JNI(register_android_graphics_Paint),
    REG_JNI(register_android_graphics_Path),
    REG_JNI(register_android_graphics_PathMeasure),
    REG_JNI(register_android_graphics_PathEffect),
    REG_JNI(register_android_graphics_Picture),
    REG_JNI(register_android_graphics_PorterDuff),
    REG_JNI(register_android_graphics_Rasterizer),
    REG_JNI(register_android_graphics_Region),
    REG_JNI(register_android_graphics_Shader),
    REG_JNI(register_android_graphics_Typeface),
    REG_JNI(register_android_graphics_Xfermode),
    REG_JNI(register_android_graphics_YuvImage),
    REG_JNI(register_com_android_internal_graphics_NativeUtils),    REG_JNI(register_android_database_CursorWindow),
    REG_JNI(register_android_database_SQLiteCompiledSql),
    REG_JNI(register_android_database_SQLiteDatabase),
    REG_JNI(register_android_database_SQLiteDebug),
    REG_JNI(register_android_database_SQLiteProgram),
    REG_JNI(register_android_database_SQLiteQuery),
    REG_JNI(register_android_database_SQLiteStatement),
    REG_JNI(register_android_os_Debug),
    REG_JNI(register_android_os_FileObserver),
    REG_JNI(register_android_os_FileUtils),
    REG_JNI(register_android_os_MessageQueue),
    REG_JNI(register_android_os_ParcelFileDescriptor),
    REG_JNI(register_android_os_Power),
    REG_JNI(register_android_os_StatFs),
    REG_JNI(register_android_os_SystemProperties),
    REG_JNI(register_android_os_UEventObserver),
    REG_JNI(register_android_net_LocalSocketImpl),
    REG_JNI(register_android_net_NetworkUtils),
    REG_JNI(register_android_net_TrafficStats),
    REG_JNI(register_android_net_wifi_WifiManager),
    REG_JNI(register_android_nfc_NdefMessage),
    REG_JNI(register_android_nfc_NdefRecord),
    REG_JNI(register_android_os_MemoryFile),
    REG_JNI(register_com_android_internal_os_ZygoteInit),
    REG_JNI(register_android_hardware_Camera),
    REG_JNI(register_android_hardware_SensorManager),
    REG_JNI(register_android_media_AudioRecord),
    REG_JNI(register_android_media_AudioSystem),
    REG_JNI(register_android_media_AudioTrack),
    REG_JNI(register_android_media_JetPlayer),
    REG_JNI(register_android_media_ToneGenerator),    REG_JNI(register_android_opengl_classes),
    REG_JNI(register_android_bluetooth_HeadsetBase),
    REG_JNI(register_android_bluetooth_BluetoothAudioGateway),
    REG_JNI(register_android_bluetooth_BluetoothSocket),
    REG_JNI(register_android_bluetooth_ScoSocket),
    REG_JNI(register_android_server_BluetoothService),
    REG_JNI(register_android_server_BluetoothEventLoop),
    REG_JNI(register_android_server_BluetoothA2dpService),
    REG_JNI(register_android_server_Watchdog),
    REG_JNI(register_android_message_digest_sha1),
    REG_JNI(register_android_ddm_DdmHandleNativeHeap),
    REG_JNI(register_android_backup_BackupDataInput),
    REG_JNI(register_android_backup_BackupDataOutput),
    REG_JNI(register_android_backup_FileBackupHelperBase),
    REG_JNI(register_android_backup_BackupHelperDispatcher),
    
    REG_JNI(register_android_app_NativeActivity),
    REG_JNI(register_android_view_InputChannel),
    REG_JNI(register_android_view_InputQueue),
    REG_JNI(register_android_view_KeyEvent),
    REG_JNI(register_android_view_MotionEvent),    REG_JNI(register_android_content_res_ObbScanner),
    REG_JNI(register_android_content_res_Configuration),
};
可以看到,gRegJNI是一个静态对象数组,这个对象数组实际上存储了Android framework中所有具有本地方法的java API模块的注册信息。为了理解这个RegJNIRec类型的静态数组,我们先看REG_JNI预编译宏和RegJNIRec类型的定义:
#ifdef NDEBUG
    #define REG_JNI(name)      { name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
    };
#else
    #define REG_JNI(name)      { name, #name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
        const char* mName;
    };
#endif
显然,带参数的REG_JNII预编译宏实际上等价于一个“{name}”,而name是一个参数;而RegJNIRec类型实际上是一个包含函数指针的结构体类型。
这样,在gRegJNI[]数组中,一个数组元素“REG_JNI(register_android_debug_JNITest),”也就等价于“{register_android_debug_JNITest },”,而这种数组定义方式的含义实际上就是把register_android_debug_JNITest这个函数指针,作为该数组元素的初始化参数,即该数组元素的mProc指针指向register_android_debug_JNITest。也就是说,gRegJNI[]数组的每个RegJNIRec结构体元素对应了一个framework子模块的本地方法注册信息,这个注册信息是通过RegJNIRec结构体元素的mProc指针来存储的。
理解静态gRegJNI数组的含义非常重要,因为其直接定义了各个framework子模块本地方法的注册关联。
下面我具体来看下gRegJNI[]数组中每个结构体元素的mProc指针存储的函数指针究竟是什么,这个函数指针指向的函数是如何工作的。我们在gRegJNI[]数组中选取大家比较熟悉的Canvas相关的数组元素REG_JNI( register_android_graphics_Canvas)为例,看看register_android_graphics_Canvas的实现,该函数的实现在frameworks\base\core\jni\android\graphics\ Canvas.cpp中:
int register_android_graphics_Canvas(JNIEnv* env) {
    int result;
    REG(env, "android/graphics/Canvas", gCanvasMethods);
    REG(env, "android/graphics/utils/BoundaryPatch", gBoundaryPatchMethods);
    return result;
}
其中REG是一个预编译宏,其定义是:
#define REG(env, name, array) \
    result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
                                        SK_ARRAY_COUNT(array));  \
    if (result < 0) return result
该宏最终会调用到\frameworks\base\core\jni \AndroidRuntime.cpp的registerNativeMethods 方法:
/*
 * Register native methods using JNI.
 */
/*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env,
    const char* className, const JNINativeMethod* gMethods, int numMethods)
{
    return jniRegisterNativeMethods(env, className, gMethods, numMethods);
}
熟悉Java JNI的朋友对jniRegisterNativeMethods应该不会陌生,在这里完成了Java标准JNI的本地方法映射。
好了,至此我们已经明白实际上函数register_android_graphics_Canvas的功能就是把数组gCanvasMethods存储的各个JNI映射元素通过标准Java JNI的jniRegisterNativeMethods方法来完成JNI映射。
那么数组gCanvasMethods又是如何实现各个JNI映射的呢?
...PS:本帖是本人CSDN博客“Android原理揭秘系列”的最新一篇,该原理揭秘系列后续将陆续推出新的文章,敬请关注。
系统提示帖子过长无法发表,本帖全文及更多Android原理揭秘系列文章,欢迎访问本人博客:http://blog.csdn.net/droidpioneer
Android原理揭秘系列之framework本地方法注册 
Android原理揭秘系列之VacantCell缓存 
Android原理揭秘系列之View、ViewGroup 
Android原理揭秘系列之动态墙纸