【Android源码 栏目提醒】:网学会员--在 Android源码 编辑为广大网友搜集整理了:Android系统Framework层源码分析 - 技术总结绩等信息,祝愿广大网友取得需要的信息,参考学习。
Android系统Framework层
源码分析 (深入理解
Android重难点解析) 主讲人——邓凡平 大纲 一 JNI重难点分析 1.1 注册方法的选择 1.2 垃圾回收 二 init重难点分析 2.1 keywords.h的有趣用法 2.2 用好“DllMain函数”——客户端Property读取的实现 三
Android常用类重难点分析 3.1 RefBase、sp和wp 3.2 题外话——无所不用其极 四 Binder重难点分析 4.1 时空穿越魔术揭秘 4.2 Binder和线程的关系 五 Audio系统重难点分析 5.1 AudioTrack 方法论 5.2 AudioFlinger中的对象 5.3 AudioPolicyService实例 5.4 audio_control_block_t分析 5.5 学习并实践Desktop Check 大纲(接上) 六 Surface系统重难点分析 6.1 来之不易的Activity 6.2 乾坤大挪移——如何与SurfaceFlinger建立联系? 6.3 生产者和消费者之间的纽带 6.4 SurfaceFlinger的工作流程分析 6.5 Transaction分析 6.6 CameraService中的严重bug 6.7 PageFlip过程分析一 JNI重难点分析1 JNI是什么? Java Native Interface2 JNI在程序中有什么作用? 白话: Java代码通过JNI调用NativeC/C写的函数 NativeC/C的函数操作Java层的函数调用函数或者操作对象 1.1 注册方法的选择什么是注册? Java中定义的native函数如何找到Native层对应的函数? 如何关联这两个函数?两种方法: 1 静态法 2 动态法静态法:很简单,就是找根据一定的函数命名规则,在so库中搜索对应的函数。
native_init------Java_
android_media_MediaScanner_native_1init静态法标准步骤:1. 先编写Java代码,然后编译生成.class文件2. 使用Java的工具程序javah,如javah –o output packagename.classname , 这样它会生成一个叫output.h的JNI层头文件。
其中packagename.classname 是Java代码编译后的class文件,而在生成的output.h文件里,声明了对应的 JNI层函数,只要实现里面的函数即可。
静态方法工作原理探析及其弊端工作原理 当Java层调用native_init函数时,它会从对应的JNI库 Java_
android_media_MediaScanner_native_linit,如果没有, 就会报错。
如果找到,则会为这个native_init和 Java_
android_media_MediaScanner_native_linit建立一个关联 关系,其实就是保存JNI层函数的函数指针。
以后再调用 native_init函数时,直接使用这个函数指针就可以了。
弊端:1. 需要编译所有声明了native函数的类。
只有生成了.class文件 后,才能交由javah工具。
2. 默认的Native函数名字巨长......3. 第一次调用某个native函数的时候,需要搜索so库中对应的 Native函数。
(估计是用dlsym来获得Native函数的函数指 针吧!)动态方法亲,您们从前面静态方法的介绍中看到了什么?native函数和JNI层的函数,不就是找一函数指针嘛?“不找贵的,只找对的......”关键数据结构:JNINativeMethod 如何注册?Quick Question:1 什么时候,在哪儿注册JNINativeMethod数组? Answer: 在一个特殊的native函数中...... Quesiton: 这个特殊的native函数又是在什么时候,在哪儿注册的? Answer: 鸡生蛋?蛋生鸡?...... 当Java层通过System.loadLibrary加载完JNI动 态库后,紧接着会查找该库中一个叫JNI_OnLoad 的函数,如果有,就调用它,而动态注册的工作 就是在这里完成的。
1.2 垃圾回收例子: 可以在别的函数使用这个save_thiz吗? 引用计数的作用呢? JNI提供三种类型的引用,足够满足亲们的需求了! Local Reference:本地引用。
在JNI层函数中使用的 非全局引用对象都是Local Reference。
它包括函数调 用时传入的jobject、在JNI层函数中创建的jobject。
Local Reference最大的特点就是,一旦JNI层函数返 回,这些jobject就可能被垃圾回收。
Global Reference:全局引用,这种对象如不主动释放,就永远不会被垃圾回收。
Weak Global Reference:弱全局引用,一种特殊的Global Reference。
在运行过程中可能会被垃圾回收。
所以在程序中使用它之前,需要调用JNIEnv的IsSameObject判断它是不是被回收了。
调用NewStringUTF创建一个jstring对象,它是Local Reference类型。
So easy? Not Really! 有可能内存不够用…… 强烈建议,及时回收Local Ref…… mEnv-DeleteLocalRefpathStrJNI最好的参考资料,一切尽在不言中…. 《Java Native Interface Specification》1. 从网上下载PDF2. JDK文档中也有可下载chm版的,查询方便……二 init重难点分析
Android对init进行了大规模改进……,但还是少不了要解析配置文件init.rc。
所以,init的破解关键在init.rc的解析代码中,解析功能在parser.c2.1 keywords.h的用法 声明一些Action函数 定义KEYWORD宏四个参 数,却只用到第一个参数 使用KEYWORD宏得到一个枚 举: enum K_UNKNOWN K_class K_on …… 两次include keywords.h 第一次包含:得到枚举定义和一些函数 Interesting :include keywords.h 重新定义KEYWROD宏 two times 四个参数全用上了 What do we get 定义一个结构体数组keyword_info 再次包含keywords.h 实际上是以枚举定义的元素为数组索引,填 充keyword_info数组(用新的KEYWORD宏)Result: 明白了?奇技淫巧乎? 2.2用好“DllMain函数”——客户端Property读取的实现
Android平台提供系统级别的属性管理和控制类比Windows平台上的“注册表”:可以存储一些类似key/value的键值对。
作用:一般而言,系统或某些应用程序会把自己的一些属性存储在注册表中,即使下次系统重启或应用程序重启,它还能够根据之前在注册表中设置的属性,进行相应的初始化工作。
Dive into code
Android想要做什么?---(目的) 1 属性区域是由init进程创建 2希望其他进程也能快速读取属性区域里的内容
Android怎么做到?---(方法) 1 属性区域创建于共享内存上 2 客户端进程不知不觉得映射这块内存 这个变量由bionic libc库输出,有什么 用呢? 利用了gcc的constructor属性,这个属性指明了一个 __libc_prenit函数,当bionic libc库被加载时,将自动调用这个 __libc_prenit,这个函数内部就将完成共享内存到本地进程的映 射工作。
Dive into code constructor属性指示加载器加载该库后,首 先调用__libc_prenit函数。
这一点和Windows 上 动态库的DllMain函数类似