nullAndroid系统Framework层源码
分析
定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析
(深入理解Android重难点解析) Android系统Framework层源码分析(深入理解Android重难点解析) 主讲人——邓凡平大纲大纲一 JNI重难点分析
1.1 注册
方法
快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载
的选择
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重难点分析一 JNI重难点分析1 JNI是什么?Java Native Interface2 JNI在程序中有什么作用?白话:
Java代码通过JNI调用Native(C/C++)写的函数
Native(C/C++)的函数操作Java层的函数(调用函数或者操作对象)1.1 注册方法的选择 1.1 注册方法的选择 什么是注册?Java中定义的native函数如何找到Native层对应的函数?如何关联这两个函数?null两种方法:
1 静态法
2 动态法静态法:很简单,就是找根据一定的函数命名规则,在so库中搜索对应的函数。native_init------Java_android_media_MediaScanner_native_1init 静态法
标准
excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载
步骤:
先编写Java代码,然后编译生成.class文件
使用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函数时,直接使用这个函数指针就可以了。弊端:
需要编译所有声明了native函数的类。只有生成了.class文件后,才能交由javah工具。
默认的Native函数名字巨长......
第一次调用某个native函数的时候,需要搜索so库中对应的Native函数。(估计是用dlsym来获得Native函数的函数指针吧!)动态方法动态方法 亲,您们从前面静态方法的介绍中看到了什么?native函数和JNI层的函数,不就是找一函数指针嘛?
“不找贵的,只找对的......”关键数据结构:JNINativeMethodnullQuick Question:
1 什么时候,在哪儿注册JNINativeMethod数组?Answer:
在一个特殊的native函数中......
Quesiton:
这个特殊的native函数又是在什么时候,在哪儿注册的?
Answer:
鸡生蛋?蛋生鸡?......当Java层通过System.loadLibrary加载完JNI动态库后,紧接着会查找该库中一个叫JNI_OnLoad的函数,如果有,就调用它,而动态注册的工作就是在这里完成的。 1.2 垃圾回收1.2 垃圾回收例子:引用计数的作用呢?JNI提供三种类型的引用,足够满足亲们的需求了!nullLocal Reference:本地引用。在JNI层函数中使用的
非全局引用对象都是Local Reference。它包括函数调
用时传入的jobject、在JNI层函数中创建的jobject。
Local Reference最大的特点就是,一旦JNI层函数返
回,这些jobject就可能被垃圾回收。 Global Reference:全局引用,这种对象如不主动释放,
就永远不会被垃圾回收。 Weak Global Reference:弱全局引用,一种特殊的
Global Reference。在运行过程中可能会被垃圾回收。
所以在程序中使用它之前,
需要调用JNIEnv的IsSameObject判断它是不是被回收了。 null调用NewStringUTF创建一个jstring对象,它是Local Reference类型。 有可能内存不够用……强烈建议,及时回收Local Ref……
mEnv->DeleteLocalRef(pathStr); So easy?
Not Really! nullJNI最好的参考资料,一切尽在不言中….
《Java Native Interface Specification》
从网上下载PDF
JDK文档中也有(可下载chm版的,查询方便……)二 init重难点分析二 init重难点分析Android对init进行了大规模改进……,但还是少不了要解
析配置文件init.rc。所以,init的破解关键在init.rc的解析
代码中,解析功能在parser.c2.1 keywords.h的用法2.1 keywords.h的用法两次include keywords.h两次include keywords.hInteresting :include keywords.h two times?
What do we get?第一次包含:得到枚举定义和一些函数定义一个结构体数组keyword_info再次包含keywords.h
实际上是以枚举定义的元素为数组索引,填充keyword_info数组(用新的KEYWORD宏)Result:Result:明白了?奇技淫巧乎?2.2用好“DllMain函数”——客户端Property读取的实现2.2用好“DllMain函数”——客户端Property读取的实现Android平台提供系统级别的属性管理和控制类比Windows平台上的“注册
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
”:可以存储一些类似key/value的键值对。
作用:一般而言,系统或某些应用程序会把自己的一些属性存储在注册表中,
即使下次系统重启或应用程序重启,它还能够根据之前在注册表中设置的
属性,进行相应的初始化工作。Dive into codeDive into codeAndroid想要做什么?---(目的)
1 属性区域是由init进程创建
2希望其他进程也能快速读取属性区域里的内容Android怎么做到?---(方法)
1 属性区域创建于共享内存上
2 客户端进程不知不觉得映射这块内存 Dive into codeDive into codeAny Questions about init?Any Questions about init?四 Android常用类重难点分析四 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 dive into code……3.1 Sample One:初识影子对象3.1 Sample One:初识影子对象//A没有任何自己的功能 //sp,wp对象是在{}中创建的,下面将先创建sp,然后创建wp //大括号结束前,先析构wp,再析构sp nullDive into Code类A从RefBase中派生。使用的是RefBase构造函数 Quick Question:
见到mStrong和mWeak,是否嗅到蛛丝马迹?发现影子对象成员中有两个引用计数?一个强引用,
一个弱引用。如果知道引用计数和对象生死有些许
关联的话,就容易想到影子对象的作用了。 sp的构造sp的构造//mRefs就是刚才RefBase构造函数中new出来的影子对象 //原子操作,影子对象的弱引用计数加1 continue incStrongnull//刚才增加了弱引用计数,再增加强引用计数//下面函数为原子加1操作,并返回旧值。所以c=0x1000000,而mStrong变为0x1000001 //如果c不是初始值,则表明这个对象已经被强引用过一次了 //下面这个是原子加操作,相当于执行refs->mStrong +(-0x1000000),最终mStrong=1sp构造后的结果:
sp的出生导致影子对象的强引用计数加1,弱引用计数加1 wp的构造wp的构造//调用pA的createWeak,并且保存返回值到成员变量m_refs中 //调用影子对象的incWeak,将导致影子对象的弱引用计数增加1wp构造后的结果:
影子对象的弱引用计数将增加1,所以现在弱引用计数为2,而强引用计数仍为1
wp中有两个成员变量,一个保存实际对象,另一个保存影子对象.
sp只有一个成员变量用来保存实际对象,但这个实际对象内部已包含了对应的影子对象wp的析构wp的析构//调用影子对象的decWeak,由影子对象的基类实现 //把基类指针转换成子类(影子对象)的类型,这种做法有些违背面向对象编程的思想 //原子减1,返回旧值,c=2,而弱引用计数从2变为1 如果c为1,则弱引用计数为0,这说明没有弱引用指向实际对象,
需要考虑是否释放内存 OBJECT_LIFETIME_XXX和生命周期有关系…..
比较难分析….wp析构后,弱引用计数减1。但由于此时强引用计数和弱引用计数仍为1,所以没有对象被干掉,即没有释放实际对象和影子对象占据的内存。nullsp的析构//注意,此时强弱引用计数都是1,下面函数调用的结果是c=1,强引用计数为0 //调用前影子对象的弱引用计数为1,强引用计数为0,调用结束后c=1,弱引用计数为0 //这次弱引用计数终于变为0,并且mFlags为0, mStrong也为0 //注意,实际数据对象已经被干掉了,所以mRefs也没有用了,但是decStrong刚进来
//的时候就保存mRefs到refs了,所以这里的refs指向影子对象Sample 1 sum up:Sample 1 sum up:RefBase中有一个隐含的影子对象,该影子对象内部有强弱引用计数。
sp化后,强弱引用计数各增加1,sp析构后,强弱引用计数各减1。
wp化后,弱引用计数增加1,wp析构后,弱引用计数减1。 完全彻底地消灭RefBase对象,包括让实际对象和影子对象灭亡,
这些都是由强弱引用计数控制的,另外还要考虑flag的取值情况。
当flag为0时,可得出如下结论: 强引用为0将导致实际对象被delete。
弱引用为0将导致影子对象被delete。 生死魔咒----extendObjectLifetime生死魔咒----extendObjectLifetime有什么用?1 flags为0,强引用计数控制实际对象的生命周期,弱引用计数控制
影子对象的生命周期。强引用计数为0后,实际对象被delete。所以
对于这种情况,应记住的是,使用wp时要由弱生强,以免收到
segment fault信号。
2 flags为LIFETIME_WEAK,强引用计数为0,弱引用计数不为0时,
实际对象不会被delete。当弱引用计数减为0时,实际对象和影
子对象会同时被delete。这是功德圆满的情况。
3 flags为LIFETIME_FOREVER,对象将长生不老,彻底摆脱强弱引
用计数的控制。所以你要在适当的时候杀死这些老妖精,
免得她祸害“人间”。 3.2 题外话——无所不用其极3.2 题外话——无所不用其极我的烦恼:
1 RefBase,sp和wp:共两个文件,1千行左右的代码。--不多,真正参与分析的代码应该不到400行。
2 判断极为复杂,打log也不方便,影响整个系统。——对于这类逻辑复杂的代码,打log实为下策。
冥思苦想……,any good ideas?我的解决
办法
鲁班奖评选办法下载鲁班奖评选办法下载鲁班奖评选办法下载企业年金办法下载企业年金办法下载
:
1 直观想法,要是能够调试该多好!
问题:部署gdbserver?——太麻烦
2 生猛一点:代码多且简单,不存在依赖关系,不如……既然它的代码不多而且简单,那何不把它移植到台式机的开发环境下,
整一个类似的RefBase呢?步骤:
1 用Visual Studio,编译和调试代码。
2 至于原子操作,Windows平台上有很直接的InterlockedExchangeXXX与
之对应。
3 Linux平台上,不考虑多线程的话,将原子操作换成普通的
非原子操作
4 如果你够猛的话,用汇编来实现常用的原子操作。Tips:
如果把破解代码看成是攻城略地的话,必须学会灵活多变,
而且应力求破解方法日臻极致! 四 Binder重难点分析四 Binder重难点分析Binder....Binder......听烦了没?见恶心了没?有木有?有木有啊??要是今天听了讲座,还没搞懂,哥伤不起啊...
伤不起.......Binder本质:
和Socket,Pipe一样,是一种IPC机制为什么觉得难?或者代码看得头疼...
完全拜Android所赐,因为它把业务逻辑和通信逻辑混杂在一起了......OK,let’s RTFSC......4.1 时空穿越魔术揭秘4.1 时空穿越魔术揭秘获得一个ProcessState实例 调用defaultServiceManager,得到一个IServiceManager BIDNER_VM_SIZE定义为(1*1024*1024) - (4096 *2) = 1M-8K
mmap映射一块内存 //打开/dev/binder设备 //通过ioctl方式告诉binder驱动,这个fd支持的最大线程数是15个 ProcessState创建的结果:
1 打开/dev/binder设备,这就相当于与内核的Binder驱动有了交互的通道。
2 对返回的fd使用mmap,这样Binder驱动就会分配一块内存来接收数据。
由于ProcessState的惟一性,因此一个进程只打开设备一次。defaultServiceManager分析defaultServiceManager分析handle值为0以0为变量,创建一个BpBinder//返回BpBinder(handle),注意,handle的值为0 BpBinder分析BpBinder分析What is BpBinder?BpBinder和BBinder都是Android中
与Binder通信相关的代表,它们都从IBinder类派生 I have a question:
如果说BpBinder和通信有关,是否能看到
类似send,write或者和binder设备交互的函数?
障眼法——interface_cast障眼法——interface_castif (interface_cast == dynamic_cast ||
interface_cast == static_cast)
{
如何把BpBinder*类型转换成IServiceManager*类型?
}Binder理解的重点:区分业务和通信Binder理解的重点:区分业务和通信BpBinder和通信相关,
通过interface_cast转换成IServiceManager梦回MFC?关键无比的宏! 有DECLARE,就有IMPLEMENT……So,how to “cast” Bpbinder* to IServiceManager*?终于,业务和通信这两个对象搞到一起去了……
通过DECLARE和IMPLEMENT这一对媒婆做到的….
注意,这里有两个对象….
不是家人,不进一家门…….不是家人,不进一家门…….思考一下:
1 BpServiceManager与BpBinder结合,参与Binder通信
2 BnServiceManager直接从BBinder派生,参与Binder通信nullas we said before:
BpBinder等IBinder家族中找不到和binder设备通信的代码,
那么,通信层是如何完成通信工作的呢?