当前位置:首页 >> IT/计算机 >>

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 Interface

2 JNI在程序中有什么作用?
白话: ? Java代码通过JNI调用Native(C/C++)写的函数 ? Native(C/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库中对应的 估计是用dlsym来获得 来获得Native函数的函数指 Native函数。(估计是用 估计是用 来获得 函数的函数指 针吧! 针吧!)

动态方法
亲,您们从前面静态方法的介绍中看到了什么? 您们从前面静态方法的介绍中看到了什么? native函数和JNI层的函数,不就是找一函数指针嘛? native函数和JNI层的函数,不就是找一函数指针嘛? 函数和JNI层的函数 “不找贵的,只找对的...... 不找贵的,只找对的......” ......
关键数据结构:JNINativeMethod 如何注册?

Quick Question: 1 什么时候,在哪儿注册JNINativeMethod数组?
Answer: Answer: 在一个特殊的native函数中...... Quesiton: Quesiton: 这个特殊的native函数又是在什么时候,在哪儿注册的? Answer: 鸡生蛋?蛋生鸡?......

当Java层通过System.loadLibrary加载完JNI动 Java层通过System.loadLibrary加载完JNI动 层通过System.loadLibrary加载完JNI 态库后,紧接着会查找该库中一个叫JNI_OnLoad 态库后,紧接着会查找该库中一个叫JNI_OnLoad 的函数,如果有,就调用它, 的函数,如果有,就调用它,而动态注册的工作 就是在这里完成的。 就是在这里完成的。

1.2 垃圾回收
例子:

可以在别的函数使用这个save_thiz吗?

引用计数的作用呢? 引用计数的作用呢?
JNI提供三种类型的引用,足够满足亲们的需求了! 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类型 类型。 调用NewStringUTF创建一个jstring对象,它是Local Reference类型。 NewStringUTF创建一个jstring对象

easy? So easy? Really! Not Really!
有可能内存不够用…… 有可能内存不够用 强烈建议,及时回收Local Ref…… 强烈建议,及时回收Local Ref mEnvmEnv->DeleteLocalRef(pathStr);

JNI最好的参考资料,一切尽在不言中…. Specification》 《Java Native Interface Specification》 1. 从网上下载PDF 从网上下载PDF JDK文档中也有 可下载chm版的,查询方便……) 文档中也有( chm版的 2. JDK文档中也有(可下载chm版的,查询方便 )

二 init重难点分析
Android对init进行了大规模改进……,但还是少不了要解 析配置文件init.rc。 所以,init的破解关键在init.rc的解析 代码中,解析功能在parser.c

2.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函数类似

Any Questions about init?

四 Android常用类重难点分析
代码中漫天可见的 RefBase、sp and wp 到底是 什么?
In my opinion: 1 Refbase类似MFC的CObject,为C++对象之始祖。 2 sp非smart pointer,而是strong pointer,wp为weak pointer。 3 三者协同组建Android C++对象生命周期的管理和控制机能。

Let’s code…… Let s dive into code

3.1 Sample One:初识影子对象

//A没有任何自己的功能

//sp,wp对象是在{}中创建的,下面将先创建sp,然后创建wp

//大括号结束前,先析构wp,再析构sp

Dive into Code 类A从RefBase中派生。使用的是RefBase构造函数 //强引用计数,初始值为0x1000000 //弱引用计数,初始值为0 //该影子对象所指向的实际对象 mRefs是RefBase的成员变量,类型是 weakref_impl,暂且称之为影子对象

Question: Quick Question: 见到mStrong和mWeak,是否嗅到蛛丝马迹 见到mStrong和mWeak,是否嗅到蛛丝马迹? mStrong 是否嗅到蛛丝马迹 发现影子对象成员中有两个引用计数?一个强引用, 一个弱引用。如果知道引用计数和对象生死有些许 关联的话,就容易想到影子对象的作用了。

sp的构造

//mRefs就是刚才RefBase构造函数中new出来的影子对象

continue incStrong

调试版的:这几个函数将 do nothing!

//原子操作,影子对象的弱引用计数加1

//刚才增加了弱引用计数,再增加强引用计数 //下面函数为原子加1操作,并返回旧值。所以c=0x1000000,而mStrong变为0x1000001

sp构造后的结果:
//如果c不是初始值,则表明这个对象已经被强引用过一次了 //下面这个是原子加操作,相当于执行refs->mStrong +(-0x1000000),最终mStrong=1

sp的出生导致影子对象的强引用计数 加1,弱引用计数加1
如果是第一次引用,则调用onFirstRef, 如果是第一次引用,则调用onFirstRef,这 onFirstRef 个函数很重要,派生类可以重载这个函数, 个函数很重要,派生类可以重载这个函数, 完成一些初始化工作。 完成一些初始化工作。

wp的构造

wp构造后的结果: 影子对象的弱引用计数将增加1,所 以现在弱引用计数为2,而强引用计 数仍为1 //调用pA的createWeak,并且保存返回值到成员变量m_refs中 wp中有两个成员变量,一个保存实际 对象,另一个保存影子对象.
//调用影子对象的incWeak,将导致影子对象的弱引用计数增加1

sp只有一个成员变量用来保存实际对 象,但这个实际对象内部已包含了对 应的影子对象

wp的析构 //把基类指针转换成子类(影子对象)的类型,这种做法有些违背面向对象编程的思想 //原子减1,返回旧值,c=2,而弱引用计数从2变为1 如果c为1,则弱引用计数为0,这说明没有弱引用指向实际对象, //调用影子对象的decWeak,由影子对象的基类实现 需要考虑是否释放内存

wp析构后,弱引用计数减1。但由于 此时强引用计数和弱引用计数仍为1, OBJECT_LIFETIME_XXX和生命周期 OBJECT_LIFETIME_XXX和生命周期 有关系….. 有关系 .. 所以没有对象被干掉,即没有释放实 比较难分析…. 比较难分析 . 际对象和影子对象占据的内存。

sp的析构

delete this自杀行为没有把影子对象干掉 //调用前影子对象的弱引用计数为1,强引用计数为0,调用结束后c=1,弱引用计数为0 但我们还在decStrong中 //注意,此时强弱引用计数都是1,下面函数调用的结果是c=1,强引用计数为0 //这次弱引用计数终于变为0,并且mFlags为0, mStrong也为0 //注意,实际数据对象已经被干掉了,所以mRefs也没有用了,但是decStrong刚进来 //的时候就保存mRefs到refs了,所以这里的refs指向影子对象

//mFlags为0,所以会通过delete this把自己干掉 //注意,此时弱引用计数仍为1

Sample 1 sum up:
RefBase中有一个隐含的影子对象,该影子对象内部有强弱引用计数。 sp化后,强弱引用计数各增加1,sp析构后,强弱引用计数各减1。 wp化后,弱引用计数增加1,wp析构后,弱引用计数减1。 完全彻底地消灭RefBase对象,包括让实际对象和影子对象灭亡, 这些都是由强弱引用计数控制的,另外还要考虑flag的取值情况。 当flag为0时,可得出如下结论:

强引用为0将导致实际对象被delete。 弱引用为0将导致影子对象被delete。

生死魔咒----extendObjectLifetime
1 flags为0,强引用计数控制实际对象的生命周期,弱引用计数控制 影子对象的生命周期。强引用计数为0后,实际对象被delete。所以 对于这种情况,应记住的是,使用wp时要由弱生强,以免收到 segment fault信号。 2 flags为LIFETIME_WEAK,强引用计数为0,弱引用计数不为0时,
FOREVER的值是3,二进制表示是B11,而WEAK的二 实际对象不会被delete。当弱引用计数减为0时,实际对象和影 进制是B01,也就是说FOREVER包括了WEAK的情况

子对象会同时被delete。这是功德圆满的情况。 3 flags为LIFETIME_FOREVER,对象将长生不老,彻底摆脱强弱引

有什么用? 用计数的控制。所以你要在适当的时候杀死这些老妖精,
免得她祸害“人间”。

3.2 题外话——无所不用其极
既然它的代码不多而且简单,那何不把它移植到台式机的开发环境下, 我的烦恼: 整一个类似的RefBase呢?步骤: 1 RefBase,sp和wp:共两个文件,1千行左右的代码。--不 1 用Visual Studio,编译和调试代码。 多,真正参与分析的代码应该不到400行。 2 至于原子操作,Windows平台上有很直接的InterlockedExchangeXXX与 之对应。 2 判断极为复杂,打log也不方便,影响整个系统。——对于 3 Linux平台上,不考虑多线程的话,将原子操作换成普通的 这类逻辑复杂的代码,打log实为下策。 非原子操作 4 冥思苦想……,any good ideas? 如果你够猛的话,用汇编来实现常用的原子操作。

Tips:

我的解决办法: 1 直观想法,要是能够调试该多好!

如果把破解代码看成是攻城略地的话,必须学会灵活多变, 问题:部署gdbserver?——太麻烦
2 生猛一点:代码多且简单,不存在依赖关系,不如…… 而且应力求破解方法日臻极致!

四 Binder重难点分析
Binder....Binder......听烦了没?见恶心了没?

OK,let’s 有木有?有木有啊??
伤不起....... Binder本质:

RTFSC......

要是今天听了讲座,还没搞懂,哥伤不起啊...

和Socket,Pipe一样,是一种IPC机制
为什么觉得难?或者代码看得头疼... 完全拜Android所赐,因为它把业务逻辑和通信逻辑混杂在一起了......

4.1 时空穿越魔术揭秘

ProcessState创建的结果: 这么重要的函数,放在这里...
//打开/dev/binder设备 有木有看走眼的时候? 1 打开/dev/binder设备,这就相当于与内核的Binder驱动有了交互的通道。

2 对返回的fd使用mmap,这样Binder驱动就会分配一块内存来接收数据。 由于ProcessState的惟一性,因此一个进程只打开设备一次。
获得一个ProcessState实例 //通过ioctl方式告诉binder驱动,这个fd支持的最大线程数是15个 调用defaultServiceManager,得到 一个IServiceManager BIDNER_VM_SIZE定义为(1*1024*1024) (4096 *2) = 1M-8K mmap映射一块内存

defaultServiceManager分析

handle值为0

以0为变量,创建一 个BpBinder //真正的gDefaultServiceManager是 在这里创建的。

//返回BpBinder(handle),注意,handle的值为0

BpBinder分析

//handle是0

What is BpBinder?
//另一个重要对象是IPCThreadState,我们稍后会详细讲解。 BpBinder和BBinder都是Android中

与Binder通信相关的代表,它们都从IBinder类派生
question: I have a question: 如果说BpBinder和通信有关, 如果说BpBinder和通信有关,是否能看到 BpBinder和通信有关 类似send,write或者和binder设备交互的函数? 类似send,write或者和binder设备交互的函数? send,write或者和binder设备交互的函数

Sorry,IBinder家族的代码中不能找到任何 Sorry,IBinder家族的代码中不能找到任何 binder设备相关的代码 与binder设备相关的代码

障眼法——interface_cast

if (interface_cast == dynamic_cast || interface_cast == static_cast) { 如何把BpBinder*类型转换成IServiceManager*类型? 如何把BpBinder*类型转换成IServiceManager*类型? BpBinder*类型转换成IServiceManager*类型 }

Binder理解的重点:区分业务和通信 BpBinder和通信相关, BpBinder和通信相关, 和通信相关 梦回MFC?关键无比的宏! 通过interface_cast转换成IServiceManager interface_cast转换成 通过interface_cast转换成IServiceManager

终于,业务和通信这两个对象搞到一起去 So,how to “cast” Bpbinder* to 了…… IServiceManager*?
有DECLARE,就有IMPLEMENT……
这几个是ServiceManager所 提供的业务函数

通过DECLARE和IMPLEMENT这一对媒婆做到的…. 注意,这里有两个对象….

不是家人,不进一家门…….

思考一下: 1 BpServiceManager与BpBinder结合,参与Binder通信 2 BnServiceManager直接从BBinder派生,参与Binder通信

mRemote指向BpBinder

as we said before: BpBinder等IBinder家族中找不到和binder设备通信的代码, BpBinder等IBinder家族中找不到和binder设备通信的代码, 家族中找不到和binder设备通信的代码 那么,通信层是如何完成通信工作的呢? 那么,通信层是如何完成通信工作的呢?

Dive into code


相关文章:
Android系统Framework层源码分析_图文.ppt
Android系统Framework层源码分析 - Android系统Framework层源码分析 (深入理解Android重难点解析) 主讲人邓凡平 大纲 ? ? ? ? ? 一 J...
Android系统Framework层源码分析18152703_图文.ppt
Android系统Framework层源码分析18152703 - Android系统Framework层源码分析 (深入理解Android重难点解析) 大纲 ? ? ? ? ? 一 JN...
5.4 Android系统Framework层源码分析_图文.ppt
5.4 Android系统Framework层源码分析_计算机软件及应用_IT/计算机_专业资料。android rom定制,android framework层分析 Android系统Framework层源码 分析(深入理解Android重...
Android系统源代码情景分析全文阅读_Android系统源代码..._百度阅读.pdf
因此,在本书中,我们选择了Android 2.3的源代码分析Android系统的实现,...层(HAL)、运行时库层(Runtime)、应用程序框架层(Application Framework)...
51CTO下载-Android系统Framework层源码分析_图文.ppt
51CTO下载-Android系统Framework层源码分析 - Android系统Framework层源码分析 (深入理解Android重难点解析) 主讲人邓凡平 大纲 ? 一 JN...
Android源码的层次结构分析.doc
Android源码的层次结构分析 - bionic,整个系统的基础类库,Android系统就是基于这个类库开发的, system,Android系统类库,基于bionic类库开发,包含工具类库...
Android Framework框架分析.pdf
系统首先加载 android_server 共享库 libandroid_server.so 源代码位于 /...Android系统Framework层... 40页 免费 android display框架分... 27页 1...
Android系统源代码情景分析全文阅读_Android系统源代码....pdf
因此,在本书中,我们选择了Android 2.3的源代码分析Android系统的实现,一是...Framework)以及应用程序层(Application),这有利于读者从整体上掌握Android系统的...
ANDROID源码结构分析.pdf
framework.jar) (有个 client.jar) |-- opt |-- com.google.android |--...(系统接口头文件) (init 程序源代码) (轻量级 C 编译器) (libc 测试相关) ...
如何分析学习Android系统的源代码.doc
如何分析学习Android系统源代码_计算机软件及应用_IT/计算机_专业资料。学习android...(External Libraries & Android Runtime)、应用程序框架层(Application Framework)...
最全的Android源码目录结构详解.doc
最全的 Android 源码目录结构详解 Android 2.1 |-...(有个 framework.jar) (有个 client.jar) ...(基本墙纸,系统内置墙纸) (选择动态壁纸) (壁纸...
Android Framework 分析.doc
Android Framework 分析 http://raymond1860.spaces.live.com/Blog/cns!BF47B6...系统首先加载 android_server 共享库 libandroid_server.so 源 代码位于/framework...
android-framework-Android系统原理与开发_图文.pdf
android-framework-Android系统原理与开发 - Jolle
Android系统框架和高性能程序开发最佳实践.doc
HAL 是 Android Framework&Application 与底层硬件整合的关键技术和必修技术; Native...( 90 分钟) 1、Main Thread+HandlerThread 2、剖析 HandlerThread 的源码实现 ...
Android 源码目录结构详解.txt
com.google.android (有个framework.jar) | |-- com.google.android.google...(系统接口头文件) | |-- init (init程序源代码) | |-- libacc (轻量级C...
Android源代码结构分析.pdf
源代码 全局的 Makefile 系统编译规则和配置所需要的脚本和工具 android 的...|-- common | `-- obj |-- bin |-- framework |-- lib `-- obj (...
Android Ril源代码分析.doc
Android Ril源代码分析_IT/计算机_专业资料。1 Framework Layer(Java) 1.1 数据连结的核心是 DataConnectionTracker.java, 主要流程是: Android 2.1: Data...
Android软硬整合设计与框架揭秘: HAL&Framework &Nativ....doc
Android软硬整合设计与框架揭秘: HAL&Framework &...HTML5 系统架构和开发人员 四、学员基础 1) 具有 ...源代码剖析 9.2 Shared Memory 剖析 9.3 Binder 是...
1 android源码系统框架、系统应用开发流程_图文.ppt
1 android源码系统框架、系统应用开发流程_其它_高等...Android的第一层是有C语言实现,第二层由C和C++...Framework Native API UserSpace HAL fb driver ...
如何调试跟踪Android Framework源代码.doc
http://www.eefocus.com/book/09-04/713771276059618.html Android 平台代码很多...Android系统Framework层... 40页 免费 android源码跟踪 3页 2下载券 android...
更多相关标签: