Android JNI原理分析

引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码:

frameworks/base/core/jni/AndroidRuntime.cpp

libcore/luni/src/main/java/java/lang/System.java
libcore/luni/src/main/java/java/lang/Runtime.java
libnativehelper/JNIHelp.cpp
libnativehelper/include/nativehelper/jni.h

frameworks/base/core/java/android/os/MessageQueue.java
frameworks/base/core/jni/android_os_MessageQueue.cpp

frameworks/base/core/java/android/os/Binder.java
frameworks/base/core/jni/android_util_Binder.cpp

frameworks/base/media/java/android/media/MediaPlayer.java
frameworks/base/media/jni/android_media_MediaPlayer.cpp

一、JNI概述

JNI(Java Native Interface,Java本地接口),用于打通Java层与Native(C/C++)层。这不是Android系统所独有的,而是Java所有。众所周知,Java语言是跨平台的语言,而这跨平台的背后都是依靠Java虚拟机,虚拟机采用C/C++编写,适配各个系统,通过JNI为上层Java提供各种服务,保证跨平台性。

相信不少经常使用Java的程序员,享受着其跨平台性,可能全然不知JNI的存在。在Android平台,让JNI大放异彩,为更多的程序员所熟知,往往为了提供效率或者其他功能需求,就需要NDK开发。上一篇文章Linux系统调用(syscall)原理,介绍了打通android上层与底层kernel的枢纽syscall,那么本文的目的则是介绍打通android上层中Java层与Native的纽带JNI。

二、JNI查找方式

Android系统在启动启动过程中,先启动Kernel创建init进程,紧接着由init进程fork第一个横穿Java和C/C++的进程,即Zygote进程。Zygote启动过程中会AndroidRuntime.cpp中的startVm创建虚拟机,VM创建完成后,紧接着调用startReg完成虚拟机中的JNI方法注册。

2.1 startReg

[–>AndroidRuntime.cpp]

int AndroidRuntime::startReg(JNIEnv* env)
{
    //设置线程创建方法为javaCreateThreadEtc
    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

    env->PushLocalFrame(200);
    //进程NI方法的注册
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);
    return 0;
}

register_jni_procs(gRegJNI, NELEM(gRegJNI), env)这行代码的作用就是就是循环调用gRegJNI数组成员所对应的方法。

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) {
            return -1;
        }
    }
    return 0;
}

gRegJNI数组,有100多个成员变量,定义在AndroidRuntime.cpp

static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_android_os_MessageQueue),
    REG_JNI(register_android_os_Binder),
    ...
};

该数组的每个成员都代表一个类文件的jni映射,其中REG_JNI是一个宏定义,在Zygote中介绍过,该宏的作用就是调用相应的方法。

2.2 如何查找native方法

当大家在看framework层代码时,经常会看到native方法,这是往往需要查看所对应的C++方法在哪个文件,对应哪个方法?下面从一个实例出发带大家如何查看java层方法所对应的native方法位置。

2.2.1 实例(一)

当分析Android消息机制源码,遇到MessageQueue.java中有多个native方法,比如:

 private native void nativePollOnce(long ptr, int timeoutMillis);

步骤1:
MessageQueue.java的全限定名为android.os.MessageQueue.java,方法名:android.os.MessageQueue.nativePollOnce(),而相对应的native层方法名只是将点号替换为下划线,可得android_os_MessageQueue_nativePollOnce()
Tips: nativePollOnce ==> android_os_MessageQueue_nativePollOnce()

步骤2:
有了native方法,那么接下来需要知道该native方法所在那个文件。前面已经介绍过Android系统启动时就已经注册了大量的JNI方法,见AndroidRuntime.cpp的gRegJNI数组。这些注册方法命令方式:

register_[包名]_[类名]

那么MessageQueue.java所定义的jni注册方法名应该是register_android_os_MessageQueue,的确存在于gRegJNI数组,说明这次JNI注册过程是有开机过程完成的。 该方法在AndroidRuntime.cpp申明为extern方法:

extern int register_android_os_MessageQueue(JNIEnv* env);

这些extern方法绝大多数位于/framework/base/core/jni/目录,大多数情况下native文件命名方式:

[包名]_[类名].cpp
[包名]_[类名].h

Tips: MessageQueue.java ==> android_os_MessageQueue.cpp

打开android_os_MessageQueue.cpp文件,搜索android_os_MessageQueue_nativePollOnce方法,这便找到了目标方法:

static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
        jlong ptr, jint timeoutMillis) {
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}

到这里完成了一次从Java层方法搜索到所对应的C++方法的过程。

2.2.2 实例(二)

对于native文件命名方式,有时并非[包名]_[类名].cpp,比如Binder.java

Binder.java所对应的native文件:android_util_Binder.cpp

public static final native int getCallingPid();

根据实例(一)方式,找到getCallingPid ==> android_os_Binder_getCallingPid(),并且在AndroidRuntime.cpp中的gRegJNI数组中找到register_android_os_Binder

按实例(一)方式则native文名应该为android_os_Binder.cpp,可是在/framework/base/core/jni/目录下找不到该文件,这是例外的情况。其实真正的文件名为android_util_Binder.cpp,这就是例外,这一点有些费劲,不明白为何google要如此打破规律的命名。

static jint android_os_Binder_getCallingPid(JNIEnv* env, jobject clazz)
{
    return IPCThreadState::self()->getCallingPid();
}

有人可能好奇,既然如何遇到打破常规的文件命令,怎么办?这个并不难,首先,可以尝试在/framework/base/core/jni/中搜索,对于binder.java,可以直接搜索binder关键字,其他也类似。如果这里也找不到,可以通过grep全局搜索android_os_Binder_getCallingPid这个方法在哪个文件。

2.2.3 实例(三)

前面两种都是在Android系统启动之初,便已经注册过JNI所对应的方法。 那么如果程序自己定义的jni方法,该如何查看jni方法所在位置呢?下面以MediaPlayer.java为例,其包名为android.media:

public class MediaPlayer{
    static {
        System.loadLibrary("media_jni");
        native_init();
    }

    private static native final void native_init();
    ...
}

通过static静态代码块中System.loadLibrary方法来加载动态库,库名为media_jni, Android平台则会自动扩展成所对应的libmedia_jni.so库。 接着通过关键字native加在native_init方法之前,便可以在java层直接使用native层方法。

接下来便要查看libmedia_jni.so库定义所在文件,一般都是通过Android.mk文件定义LOCAL_MODULE:= libmedia_jni,可以采用grep或者mgrep来搜索包含libmedia_jni字段的Android.mk所在路径。

搜索可知,libmedia_jni.so位于/frameworks/base/media/jni/Android.mk。用前面实例(一)中的知识来查看相应的文件和方法名分别为:

android_media_MediaPlayer.cpp
android_media_MediaPlayer_native_init()

再然后,你会发现果然在该Android.mk所在目录/frameworks/base/media/jni/中找到android_media_MediaPlayer.cpp文件,并在文件中存在相应的方法:

  static void
android_media_MediaPlayer_native_init(JNIEnv *env)
{
    jclass clazz;
    clazz = env->FindClass("android/media/MediaPlayer");
    fields.context = env->GetFieldID(clazz, "mNativeContext", "J");
    ...
}

Tips:MediaPlayer.java中的native_init方法所对应的native方法位于/frameworks/base/media/jni/目录下的android_media_MediaPlayer.cpp文件中的android_media_MediaPlayer_native_init方法。

2.3 小结

JNI作为连接Java世界和C/C++世界的桥梁,很有必要掌握。看完本文,至少能掌握在分析Android源码过程中如何查找native方法。首先要明白native方法名和文件名的命名规律,其次要懂得该如何去搜索代码。 JNI方式注册无非是Android系统启动过程中Zygote注册以及通过System.loadLibrary方式注册,对于系统启动过程注册的,可以通过查询AndroidRuntime.cpp中的gRegJNI是否存在对应的register方法,如果不存在,则大多数情况下是通过LoadLibrary方式来注册。

三、 JNI原理分析

再进一步来分析,Java层与native层方法是如何注册并映射的,继续以MediaPlayer为例。

在文件MediaPlayer.java中调用System.loadLibrary("media_jni")把libmedia_jni.so动态库加载到内存。接下来,以loadLibrary为起点展开JNI注册流程的过程分析。

3.1 loadLibrary

[System.java]

public static void loadLibrary(String libName) {
    //接下来调用Runtime方法
    Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
}

[Runtime.java]

void loadLibrary(String libraryName, ClassLoader loader) {
    //loader不会空,则进入该分支
    if (loader != null) {
        //查找库所在路径
        String filename = loader.findLibrary(libraryName);
        if (filename == null) {
            throw new UnsatisfiedLinkError(loader + " couldn't find \"" +
                                           System.mapLibraryName(libraryName) + "\"");
        }
        //加载库
        String error = doLoad(filename, loader);
        if (error != null) {
            throw new UnsatisfiedLinkError(error);
        }
        return;
    }

    //loader为空,则会进入该分支
    String filename = System.mapLibraryName(libraryName);
    List<String> candidates = new ArrayList<String>();
    String lastError = null;
    for (String directory : mLibPaths) {
        String candidate = directory + filename;
        candidates.add(candidate);
        if (IoUtils.canOpenReadOnly(candidate)) {
             //加载库
            String error = doLoad(candidate, loader);
            if (error == null) {
                return;//加载成功
            }
            lastError = error;
        }
    }
    if (lastError != null) {
        throw new UnsatisfiedLinkError(lastError);
    }
    throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);
}

真正加载的工作是由doLoad(),该方法内部增加同步锁,保证并发时一致性。

private String doLoad(String name, ClassLoader loader) {
    ...
    synchronized (this) {
        return nativeLoad(name, loader, ldLibraryPath);
    }
}

nativeLoad()这是一个native方法,再进入ART虚拟机java_lang_Runtime.cc,再细讲就要深入剖析虚拟机内部,这里就不再往下深入了,后续博主有空再展开art虚拟机系列的文章,这里直接说结论:

  • 调用dlopen函数,打开一个so文件并创建一个handle;
  • 调用dlsym()函数,查看相应so文件的JNI_OnLoad()函数指针,并执行相应函数。

总之,System.loadLibrary()的作用就是调用相应库中的JNI_OnLoad()方法。接下来说说JNI_OnLoad()过程。

3.2 JNI_OnLoad

[-> android_media_MediaPlayer.cpp]

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env = NULL;
    //【见3.3】 注册JNI方法
    if (register_android_media_MediaPlayer(env) < 0) {
        goto bail;
    }
    ...
}

3.3 register_android_media_MediaPlayer

[-> android_media_MediaPlayer.cpp]

static int register_android_media_MediaPlayer(JNIEnv *env)
{
    //【见3.4】
    return AndroidRuntime::registerNativeMethods(env,
                "android/media/MediaPlayer", gMethods, NELEM(gMethods));
}

其中gMethods,记录java层和C/C++层方法的一一映射关系。

static JNINativeMethod gMethods[] = {
    {"prepare",      "()V",  (void *)android_media_MediaPlayer_prepare},
    {"_start",       "()V",  (void *)android_media_MediaPlayer_start},
    {"_stop",        "()V",  (void *)android_media_MediaPlayer_stop},
    {"seekTo",       "(I)V", (void *)android_media_MediaPlayer_seekTo},
    {"_release",     "()V",  (void *)android_media_MediaPlayer_release},
    {"native_init",  "()V",  (void *)android_media_MediaPlayer_native_init},
    ...
};

这里涉及到结构体JNINativeMethod,其定义在jni.h文件:

typedef struct {
    const char* name;  //Java层native函数名
    const char* signature; //Java函数签名,记录参数类型和个数,以及返回值类型
    void*       fnPtr; //Native层对应的函数指针
} JNINativeMethod;

关于函数签名signature在下一小节展开说明。

3.4 registerNativeMethods

[-> AndroidRuntime.cpp]

int AndroidRuntime::registerNativeMethods(JNIEnv* env,
    const char* className, const JNINativeMethod* gMethods, int numMethods)
{
    //【见3.5】
    return jniRegisterNativeMethods(env, className, gMethods, numMethods);
}

jniRegisterNativeMethods该方法是由Android JNI帮助类JNIHelp.cpp来完成。

3.5 jniRegisterNativeMethods

[-> JNIHelp.cpp]

extern "C" int jniRegisterNativeMethods(C_JNIEnv* env, const char* className,
    const JNINativeMethod* gMethods, int numMethods)
{
    JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
    scoped_local_ref<jclass> c(env, findClass(env, className));
    if (c.get() == NULL) {
        e->FatalError("");//无法查找native注册方法
    }
    //【见3.6】 调用JNIEnv结构体的成员变量
    if ((*env)->RegisterNatives(e, c.get(), gMethods, numMethods) < 0) {
        e->FatalError("");//native方法注册失败
    }
    return 0;
}

3.6 RegisterNatives

[-> jni.h]

struct _JNIEnv {
    const struct JNINativeInterface* functions;

    jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,
            jint nMethods)
    { return functions->RegisterNatives(this, clazz, methods, nMethods); }
    ...
}

functions是指向JNINativeInterface结构体指针,也就是将调用下面方法:

struct JNINativeInterface {
    jint (*RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*,jint);
    ...
}

再往下深入就到了虚拟机内部吧,这里就不再往下深入了。 总之,这个过程完成了gMethods数组中的方法的映射关系,比如java层的native_init()方法,映射到native层的android_media_MediaPlayer_native_init()方法。

虚拟机相关的变量中有两个非常重要的量JavaVM和JNIEnv:

  • JavaVM:是指进程虚拟机环境,每个进程有且只有一个JavaVM实例
  • JNIEnv:是指线程上下文环境,每个线程有且只有一个JNIEnv实例,

四、JNI资源

JNINativeMethod结构体中有一个字段为signature(签名),再介绍signature格式之前需要掌握各种数据类型在Java层、Native层以及签名所采用的签名格式。

4.1 数据类型

4.1.1 基本数据类型
Signature格式 Java Native
B byte jbyte
C char jchar
D double jdouble
F float jfloat
I int jint
S short jshort
J long jlong
Z boolean jboolean
V void void
4.1.2 数组数据类型

数组简称则是在前面添加[

Signature格式 Java Native
[B byte[] jbyteArray
[C char[] jcharArray
[D double[] jdoubleArray
[F float[] jfloatArray
[I int[] jintArray
[S short[] jshortArray
[J long[] jlongArray
[Z boolean[] jbooleanArray
4.1.3 复杂数据类型

对象类型简称:L+classname +;

Signature格式 Java Native
Ljava/lang/String; String jstring
L+classname +; 所有对象 jobject
[L+classname +; Object[] jobjectArray
Ljava.lang.Class; Class jclass
Ljava.lang.Throwable; Throwable jthrowable
4.1.4 Signature

有了前面的铺垫,那么再来通过实例说说函数签名: (输入参数...)返回值参数,这里用到的便是前面介绍的Signature格式。

Java函数 对应的签名
void foo() ()V
float foo(int i) (I)F
long foo(int[] i) ([I)J
double foo(Class c) (Ljava/lang/Class;)D
boolean foo(int[] i,String s) ([ILjava/lang/String;)Z
String foo(int i) (I)Ljava/lang/String;

4.2 其他

(一)垃圾回收 对于Java开发人员来说无需关系垃圾回收,完全由虚拟机GC来负责垃圾回收,而对于JNI开发人员,对于内存释放需要谨慎处理,需要的时候申请,使用完记得释放内容,以免发生内存泄露。在JNI提供了三种Reference类型,Local Reference(本地引用), Global Reference(全局引用), Weak Global Reference(全局弱引用)。其中Global Reference如果不主动释放,则一直不会释放;对于其他两个类型的引用都是释放的可能性,那是不是意味着不需要手动释放呢?答案是否定的,不管是这三种类型的那种引用,都尽可能在某个内存不再需要时,立即释放,这对系统更为安全可靠,以减少不可预知的性能与稳定性问题。

另外,ART虚拟机在GC算法有所优化,为了减少内存碎片化问题,在GC之后有可能会移动对象内存的位置,对于Java层程序并没有影响,但是对于JNI程序可要小心了,对于通过指针来直接访问内存对象是,Dalvik能正确运行的程序,ART下未必能正常运行。

(二)异常处理
Java层出现异常,虚拟机会直接抛出异常,这是需要try..catch或者继续往外throw。但是对于JNI出现异常时,即执行到JNIEnv中某个函数异常时,并不会立即抛出异常来中断程序的执行,还可以继续执行内存之类的清理工作,直到返回到Java层时才会抛出相应的异常。

另外,Dalvik虚拟机有些情况下JNI函数出错可能返回NULL,但ART虚拟机在出错时更多的是抛出异常。这样导致的问题就可能是在Dalvik版本能正常运行的程序,在ART虚拟机上由于没有正确处理异常而崩溃。

总结

本文主要通过实例,基于Android 6.0源码来分析JNI原理,讲述JNI核心功能:

  • 介绍了如何查找JNI方法,让大家明白如何从Java层跳转到Native层;
  • 分析了JNI函数注册流程,进一步加深对JNI的理解;
  • 列举Java与native以及函数签名方式。

原文地址:http://gityuan.com/2016/05/28/android-jni/

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android系统源代码情景分析》随书光盘内容(源代码) 目录如下: 第1篇 初识Android系统 第1章 准备知识 1.1 Linux内核参考书籍 1.2 Android应用程序参考书籍 1.3 下载、编译和运行Android源代码 1.3.1 下载Android源代码 1.3.2 编译Android源代码 1.3.3 运行Android模拟器 1.4 下载、编译和运行Android内核源代码 1.4.1 下载Android内核源代码 1.4.2 编译Android内核源代码 1.4.3 运行Android模拟器 1.5 开发第一个Android应用程序 1.6 单独编译和打包Android应用程序模块 1.6.1 导入单独编译模块的mmm命令 1.6.2 单独编译Android应用程序模块 1.6.3 重新打包Android系统镜像文件 第2章 硬件抽象层 2.1 开发Android硬件驱动程序 2.1.1 实现内核驱动程序模块 2.1.2 修改内核Kconfig文件 2.1.3 修改内核Makefile文件 2.1.4 编译内核驱动程序模块 2.1.5 验证内核驱动程序模块 2.2 开发C可执行程序验证Android硬件驱动程序 2.3 开发Android硬件抽象层模块 2.3.1 硬件抽象层模块编写规范 2.3.2 编写硬件抽象层模块接口 2.3.3 硬件抽象层模块的加载过程 2.3.4 处理硬件设备访问权限问题 2.4 开发Android硬件访问服务 2.4.1 定义硬件访问服务接口 2.4.2 实现硬件访问服务 2.4.3 实现硬件访问服务的JNI方法 2.4.4 启动硬件访问服务 2.5 开发Android应用程序来使用硬件访问服务 第3章 智能指针 3.1 轻量级指针 3.1.1 实现原理分析 3.1.2 应用实例分析 3.2 强指针和弱指针 3.2.1 强指针的实现原理分析 3.2.2 弱指针的实现原理分析 3.2.3 应用实例分析 第2篇 Android专用驱动系统 第4章 Logger日志系统 4.1 Logger日志格式 4.2 Logger日志驱动程序 4.2.1 基础数据结构 4.2.2 日志设备的初始化过程 4.2.3 日志设备文件的打开过程 4.2.4 日志记录的读取过程 4.2.5 日志记录的写入过程 4.3 运行时库层日志库 4.4 C/C++日志写入接口 4.5 Java日志写入接口 4.6 Logcat工具分析 4.6.1 相关数据结构 4.6.2 初始化过程 4.6.3 日志记录的读取过程 4.6.4 日志记录的输出过程 第5章 Binder进程间通信系统 5.1 Binder驱动程序 5.1.1 基础数据结构 5.1.2 Binder设备的初始化过程 5.1.3 Binder设备文件的打开过程 5.1.4 Binder设备文件的内存映射过程 5.1.5 内核缓冲区管理 5.2 Binder进程间通信库 5.3 Binder进程间通信应用实例 5.4 Binder对象引用计数技术 5.4.1 Binder本地对象的生命周期 5.4.2 Binder实体对象的生命周期 5.4.3 Binder引用对象的生命周期 5.4.4 Binder代理对象的生命周期 5.5 Binder对象死亡通知机制 5.5.1 注册死亡接收通知 5.5.2 发送死亡接收通知 5.5.3 注销死亡接收通知 5.6 Service Manager的启动过程 5.6.1 打开和映射Binder设备文件 5.6.2 注册为Binder上下文管理者 5.6.3 循环等待Client进程请求 5.7 Service Manager代理对象的获取过程 5.8 Service组件的启动过程 5.8.1 注册Service组件 5.8.2 启动Binder线程池 5.9 Service代理对象的获取过程 5.10 Binder进程间通信机制的Java接口 5.10.1 Service Manager的Java代理对象的获取过程 5.10.2 Java服务接口的定义和解析 5.10.3 Java服务的启动过程 5.10.4 Java服务代理对象的获取过程 5.10.5 Java服务的调用过程 第6章 Ashmem匿名共享内存系统 6.1 Ashmem驱动程序 6.1.1 基础数据结构 6.1.2 匿名共享内存设备的初始化过程 6.1.3 匿名共享内存设备文件的打开过程 6.1.4 匿名共享内存设备文件的内存映射过程 6.1.5 匿名共享内存块的锁定和解锁过程 6.1.6 匿名共享内存块的回收过程 6.2 运行时库cutils的匿名共享内存访问接口 6.3 匿名共享内存的C++访问接口 6.3.1 MemoryHeapBase 6.3.2 MemoryBase 6.3.3 应用实例 6.4 匿名共享内存的Java访问接口 6.4.1 MemoryFile 6.4.2 应用实例 6.5 匿名共享内存的共享原理 第3篇 Android应用程序框架 第7章 Activity组件的启动过程 7.1 Activity组件应用实例 7.2 根Activity组件的启动过程 7.3 子Activity组件在进程内的启动过程 7.4 子Activity组件在新进程中的启动过程 第8章 Service组件的启动过程 8.1 Service组件应用实例 8.2 Service组件在新进程中的启动过程 8.3 Service组件在进程内的绑定过程 第9章 Android系统广播机制 9.1 广播机制应用实例 9.2 广播接收者的注册过程 9.3 广播的发送过程 第10章 Content Provider组件的实现原理 10.1 Content Provider组件应用实例 10.1.1 ArticlesProvider 10.1.2 Article 10.2 Content Provider组件的启动过程 10.3 Content Provider组件的数据共享原理 10.3.1 数据共享模型 10.3.2 数据传输过程 10.4 Content Provider组件的数据更新通知机制 10.4.1 注册内容观察者 10.4.2 发送数据更新通知 第11章 Zygote和System进程的启动过程 11.1 Zygote进程的启动脚本 11.2 Zygote进程的启动过程 11.3 System进程的启动过程 第12章 Android应用程序进程的启动过程 12.1 应用程序进程的创建过程 12.2 Binder线程池的启动过程 12.3 消息循环的创建过程 第13章 Android应用程序的消息处理机制 13.1 创建线程消息队列 13.2 线程消息循环过程 13.3 线程消息发送过程 13.4 线程消息处理过程 第14章 Android应用程序的键盘消息处理机制 14.1 键盘消息处理模型 14.2 InputManager的启动过程 14.2.1 创建InputManager 14.2.2 启动InputManager 14.2.3 启动InputDispatcher 14.2.4 启动InputReader 14.3 InputChannel的注册过程 14.3.1 创建InputChannel 14.3.2 注册Server端InputChannel 14.3.3 注册系统当前激活的应用程序窗口 14.3.4 注册Client端InputChannel 14.4 键盘消息的分发过程 14.4.1 InputReader获得键盘事件 14.4.2 InputDispatcher分发键盘事件 14.4.3 系统当前激活的应用程序窗口获得键盘消息 14.4.4 InputDispatcher获得键盘事件处理完成通知 14.5 InputChannel的注销过程 14.5.1 销毁应用程序窗口 14.5.2 注销Client端InputChannel 14.5.3 注销Server端InputChannel 第15章 Android应用程序线程的消息循环模型 15.1 应用程序主线程消息循环模型 15.2 与界面无关的应用程序子线程消息循环模型 15.3 与界面相关的应用程序子线程消息循环模型 第16章 Android应用程序的安装和显示过程 16.1 应用程序的安装过程 16.2 应用程序的显示过程
Android系统源代码情景分析光盘资料 目录 第1篇初识Android系统 第1章 准备知识................................................................ 2 1.1 Linux内核参考书籍.................................................. 2 1.2 Android应用程序参考书籍....................................... 3 1.3 下载、编译和运行Android源代码........................... 3 1.3.1 下载Android源代码........................................... 4 1.3.2 编译Android源代码........................................... 4 1.3.3 运行Android模拟器........................................... 5 1.4 下载、编译和运行Android内核源代码............................................................ 6 1.4.1 下载Android内核源代码................................... 6 1.4.2 编译Android内核源代码................................... 7 1.4.3 运行Android模拟器........................................... 8 1.5 开发第一个Android应用程序................................... 8 1.6 单独编译和打包Android应用程序模块.......................................................... 11 1.6.1 导入单独编译模块的mmm命令............................................................... 11 1.6.2 单独编译Android应用程序模块............................................................... 12 1.6.3 重新打包Android系统镜像文件............................................................... 12 第2章 硬件抽象层....................................................... 13 2.1 开发Android硬件驱动程序..................................... 14 2.1.1 实现内核驱动程序模块.................................. 14 2.1.2 修改内核Kconfig文件...................................... 21 2.1.3 修改内核Makefile文件..................................... 22 2.1.4 编译内核驱动程序模块.................................. 22 2.1.5 验证内核驱动程序模块.................................. 23 2.2 开发C可执行程序验证Android硬件驱动程序............................................... 24 2.3 开发Android硬件抽象层模块................................. 26 2.3.1 硬件抽象层模块编写规范............................... 26 2.3.2 编写硬件抽象层模块接口............................... 29 2.3.3 硬件抽象层模块的加载过程........................... 33 2.3.4 处理硬件设备访问权限问题........................... 36 2.4 开发Android硬件访问服务..................................... 38 2.4.1 定义硬件访问服务接口.................................. 38 2.4.2 实现硬件访问服务.......................................... 39 2.4.3 实现硬件访问服务的JNI方法.......................... 40 2.4.4 启动硬件访问服务.......................................... 43 2.5 开发Android应用程序来使用硬件访问服务.................................................. 44 第3章 智能指针............................................................... 49 3.1 轻量级指针............................................................. 50 3.1.1 实现原理分析................................................ 50 3.1.2 应用实例分析................................................ 53 3.2 强指针和弱指针..................................................... 54 3.2.1 强指针的实现原理分析.................................. 55 3.2.2 弱指针的实现原理分析.................................. 61 3.2.3 应用实例分析................................................ 67 第2篇Android专用驱动系统 第4章 Logger日志系统............................................. 74 4.1 Logger日志格式....................................................... 75 4.2 Logger日志驱动程序.............................................. 76 4.2.1 基础数据结构................................................ 77 4.2.2 日志设备的初始化过程.................................. 78 4.2.3 日志设备文件的打开过程............................... 83 4.2.4 日志记录的读取过程...................................... 84 4.2.5 日志记录的写入过程...................................... 88 4.3 运行时库层日志库................................................. 93 4.4 C/C++日志写入接口............................................. 100 4.5 Java日志写入接口................................................ 104 4.6 Logcat工具分析..................................................... 110 4.6.1 基础数据结构.............................................. 111 4.6.2 初始化过程.................................................. 115 4.6.3 日志记录的读取过程.................................... 127 4.6.4 日志记录的输出过程.................................... 132 第5章 Binder进程间通信系统............................... 144 5.1 Binder驱动程序..................................................... 145 5.1.1 基础数据结构.............................................. 146 5.1.2 Binder设备的初始化过程.............................. 164 5.1.3 Binder设备文件的打开过程.......................... 165 5.1.4 Binder设备文件的内存映射过程............................................................ 166 5.1.5 内核缓冲区管理........................................... 173 5.2 Binder进程间通信库............................................. 183 5.3 Binder进程间通信应用实例................................. 188 5.4 Binder对象引用计数技术..................................... 196 5.4.1 Binder本地对象的生命周期.......................... 197 5.4.2 Binder实体对象的生命周期.......................... 201 5.4.3 Binder引用对象的生命周期.......................... 204 5.4.4 Binder代理对象的生命周期.......................... 209 5.5 Binder对象死亡通知机制..................................... 212 5.5.1 注册死亡接收通知........................................ 213 5.5.2 发送死亡接收通知........................................ 216 5.5.3 注销死亡接收通知........................................ 221 5.6 Service Manager的启动过程.................................. 224 5.6.1 打开和映射Binder设备文件.......................... 226 5.6.2 注册为Binder上下文管理者.......................... 227 5.6.3 循环等待Client进程请求............................... 231 5.7 Service Manager代理对象的获取过程........................................................... 238 5.8 Service组件的启动过程........................................ 244 5.8.1 注册Service组件............................................ 245 5.8.2 启动Binder线程池......................................... 289 5.9 Service代理对象的获取过程................................ 291 5.10 Binder进程间通信机制的Java接口............................................................. 300 5.10.1 Service Manager的Java代理对象的获取过程.......................................... 300 5.10.2 Java服务接口的定义和解析.................................................................. 310 5.10.3 Java服务的启动过程.................................... 313 5.10.4 Java服务代理对象的获取过程.............................................................. 320 5.10.5 Java服务的调用过程.................................... 323 第6章 Ashmem匿名共享内存系统.............................................................. 327 6.1 Ashmem驱动程序................................................. 328 6.1.1 基础数据结构.............................................. 328 6.1.2 匿名共享内存设备的初始化过程........................................................... 330 6.1.3 匿名共享内存设备文件的打开过程....................................................... 332 6.1.4 匿名共享内存设备文件的内存映射过程................................................ 334 6.1.5 匿名共享内存块的锁定和解锁过程....................................................... 336 6.1.6 匿名共享内存块的回收过程.................................................................. 344 6.2 运行时库cutils的匿名共享内存访问接口.................................................... 345 6.3 匿名共享内存的C++访问接口............................. 349 6.3.1 MemoryHeapBase......................................... 349 6.3.2 MemoryBase................................................. 359 6.3.3 应用实例..................................................... 364 6.4 匿名共享内存的Java访问接口............................. 370 6.4.1 MemoryFile.................................................. 370 6.4.2 应用实例..................................................... 375 6.5 匿名共享内存的共享原理.................................... 386 第3篇Android应用程序框架 第7章 Activity组件的启动过程............................. 392 7.1 Activity组件应用实例............................................ 392 7.2 根Activity组件的启动过程.................................... 398 7.3 子Activity组件在进程内的启动过程............................................................ 432 7.4 子Activity组件在新进程中的启动过程........................................................ 440 第8章 Service组件的启动过程............................ 443 8.1 Service组件应用实例............................................. 443 8.2 Service组件在新进程中的启动过程............................................................. 451 8.3 Service组件在进程内的绑定过程................................................................. 463 第9章 Android系统广播机制................................. 486 9.1 广播机制应用实例............................................... 487 9.2 广播接收者的注册过程........................................ 493 9.3 广播的发送过程................................................... 501 第10章 Content Provider组件的实现原理................................................. 524 10.1 Content Provider组件应用实例........................... 525 10.1.1 ArticlesProvider........................................... 525 10.1.2 Article......................................................... 535 10.2 Content Provider组件的启动过程................................................................ 550 10.3 Content Provider组件的数据共享原理........................................................ 573 10.3.1 数据共享模型............................................. 573 10.3.2 数据传输过程............................................. 576 10.4 Content Provider组件的数据更新通知机制................................................ 596 10.4.1 注册内容观察者.......................................... 597 10.4.2 发送数据更新通知...................................... 603 第11章 Zygote和System进程的启动过程................................................. 611 11.1 Zygote进程的启动脚本........................................ 611 11.2 Zygote进程的启动过程........................................ 614 11.3 System进程的启动过程....................................... 622 第12章 Android应用程序进程的启动过程................................................. 630 12.1 应用程序进程的创建过程.................................. 630 12.2 Binder线程池的启动过程................................... 639 12.3 消息循环的创建过程.......................................... 641 第13章 Android应用程序的消息处理机制................................................. 645 13.1 创建线程消息队列............................................. 645 13.2 线程消息循环过程............................................. 650 13.3 线程消息发送过程............................................. 655 13.4 线程消息处理过程............................................. 660 第14章 Android应用程序的键盘消息处理机制....................................... 667 14.1 键盘消息处理模型............................................. 667 14.2 InputManager的启动过程.................................... 670 14.2.1 创建InputManager...................................... 670 14.2.2 启动InputManager...................................... 673 14.2.3 启动InputDispatcher.................................... 675 14.2.4 启动InputReader........................................ 677 14.3 InputChannel的注册过程..................................... 688 14.3.1 创建InputChannel....................................... 689 14.3.2 注册Server端InputChannel........................... 697 14.3.3 注册系统当前激活的应用程序窗口..................................................... 701 14.3.4 注册Client端InputChannel........................... 706 14.4 键盘消息的分发过程.......................................... 709 14.4.1 InputReader获得键盘事件........................... 710 14.4.2 InputDispatcher分发键盘事件............................................................... 717 14.4.3 系统当前激活的应用程序窗口获得键盘消息....................................... 727 14.4.4 InputDispatcher获得键盘事件处理完成通知......................................... 743 14.5 InputChannel的注销过程..................................... 746 14.5.1 销毁应用程序窗口...................................... 747 14.5.2 注销Client端InputChannel........................... 756 14.5.3 注销Server端InputChannel........................... 758 第15章 Android应用程序线程的消息循环模型....................................... 764 15.1 应用程序主线程消息循环模型.......................... 765 15.2 与界面无关的应用程序子线程消息循环模型.......................................... 766 15.3 与界面相关的应用程序子线程消息循环模型.......................................... 769 第16章 Android应用程序的安装和显示过程............................................ 778 16.1 应用程序的安装过程......................................... 778 16.2 应用程序的显示过程.......................................... 814

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值