虽然Java层Binder系统是Native层Binder系统的一个Mirror,但这个Mirror终归还需借助Native层Binder系统来开展工作,即Mirror和Native层Binder有着千丝万缕的关系,一定要在Java层Binder正式工作之前建立这种关系。下面分析Java层Binder框架是如何初始化的。
在Android系统中,在Java初创时期,系统会提前注册一些JNI函数,其中有一个函数专门负责搭建Java Binder和Native Binder交互关系,该函数是register\_android\_os\_Binder,代码如下:
**android_util_Binder.cpp-->register_android_os_Binder()**
```
int register_android_os_Binder(JNIEnv* env)
{
// 初始化Java Binder类和Native层的关系
if(int_register_android_os_Binder(env) < 0)
return -1;
// 初始化Java BinderInternal类和Native层的关系
if(int_register_android_os_BinderInternal(env) < 0)
return -1;
// 初始化Java BinderProxy类和Native层的关系
if(int_register_android_os_BinderProxy(env) < 0)
return -1;
......
return0;
}
```
据上面的代码可知,register\_android\_os\_Binder函数完成了Java Binder架构中最重要的3个类的初始化工作。
#### 1. Binder类的初始化
int\_register\_android\_os\_Binder函数完成了Binder类的初始化工作,代码如下:
**android_util_Binder.cpp-->int_register_android_os_Binder()**
```
static int int_register_android_os_Binder(JNIEnv*env)
{
jclassclazz;
//kBinderPathName为Java层中Binder类的全路径名,“android/os/Binder“
clazz =env->FindClass(kBinderPathName);
/*gBinderOffSets是一个静态类对象,它专门保存Binder类的一些在JNI层中使用的信息,
如成员函数execTranscat的methodID,Binder类中成员mObject的fildID */
gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gBinderOffsets.mExecTransact
=env->GetMethodID(clazz, "execTransact", "(IIII)Z");
gBinderOffsets.mObject
=env->GetFieldID(clazz, "mObject", "I");
// 注册Binder类中native函数的实现
returnAndroidRuntime::registerNativeMethods(
env,kBinderPathName,
gBinderMethods,NELEM(gBinderMethods));
}
```
从上面代码可知,gBinderOffsets对象保存了和Binder类相关的某些在JNI层中使用的信息。它们将用来在JNI层对Java层的Binder对象进行操作。execTransact()函数以及mObject成员的用途将在2.2.3节介绍。
* * * * *
**建议** 如果读者对JNI不是很清楚,可参阅卷I第2章“深入理解JNI”。
* * * * *
#### 2. BinderInternal类的初始化
下一个初始化的类是BinderInternal,其代码在int\_register\_android\_os\_BinderInternal函数中。
**android_util_Binder.cpp-->int_register_android_os_BinderInternal()**
```
static intint_register_android_os_BinderInternal(JNIEnv* env)
{
jclassclazz;
// 根据BinderInternal的全路径名找到代表该类的jclass对象。全路径名为
//“com/android/internal/os/BinderInternal”
clazz =env->FindClass(kBinderInternalPathName);
//gBinderInternalOffsets也是一个静态对象,用来保存BinderInternal类的一些信息
gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
// 获取forceBinderGc的methodID
gBinderInternalOffsets.mForceGc
= env->GetStaticMethodID(clazz, "forceBinderGc","()V");
// 注册BinderInternal类中native函数的实现
returnAndroidRuntime::registerNativeMethods(
env,kBinderInternalPathName,
gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
```
int\_register\_android\_os\_BinderInternal的工作内容和int\_register\_android\_os\_Binder的工作内容类似:
- 获取一些有用的methodID和fieldID。这表明JNI层一定会向上调用Java层的函数。
- 注册相关类中native函数的实现。
#### 3. BinderProxy类的初始化
int\_register\_android\_os\_BinderProxy完成了BinderProxy类的初始化工作,代码稍显复杂,如下所示:
**android_util_Binder.cpp-->int_register_android_os_BinderProxy()**
```
static intint_register_android_os_BinderProxy(JNIEnv* env)
{
jclassclazz;
// **① gWeakReferenceOffsets用来和WeakReference类打交道**
clazz =env->FindClass("java/lang/ref/WeakReference");
gWeakReferenceOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
// 获取WeakReference类get函数的MethodID
gWeakReferenceOffsets.mGet= env->GetMethodID(clazz, "get",
"()Ljava/lang/Object;");
// **② gErrorOffsets用来和Error类打交道**
clazz =env->FindClass("java/lang/Error");
gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
// **③ gBinderProxyOffsets用来和BinderProxy类打交道**
clazz =env->FindClass(kBinderProxyPathName);
gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gBinderProxyOffsets.mConstructor= env->GetMethodID(clazz,"<init>", "()V");
......//获取BinderProxy的一些信息
// **④ gClassOffsets用来和Class类打交道**
clazz =env->FindClass("java/lang/Class");
gClassOffsets.mGetName =env->GetMethodID(clazz,
"getName","()Ljava/lang/String;");
// 注册BinderProxy native函数的实现
returnAndroidRuntime::registerNativeMethods(env,
kBinderProxyPathName,gBinderProxyMethods,
NELEM(gBinderProxyMethods));
}
```
据上面代码可知,int\_register\_android\_os\_BinderProxy函数除了初始化BinderProxy类外,还获取了WeakReference类和Error类的一些信息。看来BinderProxy对象的生命周期会委托WeakReference来管理,难怪JNI层会获取该类get函数的MethodID。
至此,Java Binder几个重要成员的初始化已完成,同时在代码中定义了几个全局静态对象,分别是gBinderOffsets、gBinderInternalOffsets和gBinderProxyOffsets。
框架的初始化其实就是提前获取一些JNI层的使用信息,如类成员函数的MethodID,类成员变量的fieldID等。这项工作是必需的,因为它能节省每次使用时获取这些信息的时间。当Binder调用频繁时,这些时间累积起来还是不容小觑的。
另外,这个过程中所创建的几个全局静态对象为JNI层访问Java层的对象提供了依据。而在每个初始化函数中所执行的registerNativeMethods()方法则为Java层访问JNI层打通了道路。换句话说,Binder初始化的工作就是通过JNI建立起Native Binder与Java Binder之间互相通信的桥梁。
下面通过一个例子来分析Java Binder的工作流程。
- 前言
- 推荐序
- 第1章 开发环境部署
- 1.1获取Android源代码
- 1.2Android的编译
- 1.3在IDE中导入Android源代码
- 1.3.1将Android源代码导入Eclipse
- 1.3.2将Android源代码导入SourceInsight
- 1.4调试Android源代码
- 1.4.1使用Eclipse调试Android Java源代码
- 1.4.2使用gdb调试Android C/C 源代码
- 1.5本章小结
- 第2章 深入理解Java Binder和MessageQueue
- 2.1概述
- 2.2Java层中的Binder分析
- 2.2.1Binder架构总览
- 2.2.2初始化Java层Binder框架
- 2.2.3窥一斑,可见全豹乎
- 2.2.4理解AIDL
- 2.2.5Java层Binder架构总结
- 2.3心系两界的MessageQueue
- 2.3.1MessageQueue的创建
- 2.3.2提取消息
- 2.3.3nativePollOnce函数分析
- 2.3.4MessageQueue总结
- 2.4本章小结
- 第3章 深入理解AudioService
- 3.1概述
- 3.2音量管理
- 3.2.1音量键的处理流程
- 3.2.2通用的音量设置函数setStreamVolume()
- 3.2.3静音控制
- 3.2.4音量控制小结
- 3.3音频外设的管理
- 3.3.1 WiredAccessoryObserver 设备状态的监控
- 3.3.2AudioService的外设状态管理
- 3.3.3音频外设管理小结
- 3.4AudioFocus机制的实现
- 3.4.1AudioFocus简单的例子
- 3.4.2AudioFocus实现原理简介
- 3.4.3申请AudioFocus
- 3.4.4释放AudioFocus
- 3.4.5AudioFocus小结
- 3.5AudioService的其他功能
- 3.6本章小结
- 第4章 深入理解WindowManager-Service
- 4.1初识WindowManagerService
- 4.1.1一个从命令行启动的动画窗口
- 4.1.2WMS的构成
- 4.1.3初识WMS的小结
- 4.2WMS的窗口管理结构
- 4.2.1理解WindowToken
- 4.2.2理解WindowState
- 4.2.3理解DisplayContent
- 4.3理解窗口的显示次序
- 4.3.1主序、子序和窗口类型
- 4.3.2通过主序与子序确定窗口的次序
- 4.3.3更新显示次序到Surface
- 4.3.4关于显示次序的小结
- 4.4窗口的布局
- 4.4.1从relayoutWindow()开始
- 4.4.2布局操作的外围代码分析
- 4.4.3初探performLayoutAndPlaceSurfacesLockedInner()
- 4.4.4布局的前期处理
- 4.4.5布局DisplayContent
- 4.4.6布局的阶段
- 4.5WMS的动画系统
- 4.5.1Android动画原理简介
- 4.5.2WMS的动画系统框架
- 4.5.3WindowAnimator分析
- 4.5.4深入理解窗口动画
- 4.5.5交替运行的布局系统与动画系统
- 4.5.6动画系统总结
- 4.6本章小结
- 第5章 深入理解Android输入系统
- 5.1初识Android输入系统
- 5.1.1getevent与sendevent工具
- 5.1.2Android输入系统简介
- 5.1.3IMS的构成
- 5.2原始事件的读取与加工
- 5.2.1基础知识:INotify与Epoll
- 5.2.2 InputReader的总体流程
- 5.2.3 深入理解EventHub
- 5.2.4 深入理解InputReader
- 5.2.5原始事件的读取与加工总结
- 5.3输入事件的派发
- 5.3.1通用事件派发流程
- 5.3.2按键事件的派发
- 5.3.3DispatcherPolicy与InputFilter
- 5.3.4输入事件的派发总结
- 5.4输入事件的发送、接收与反馈
- 5.4.1深入理解InputChannel
- 5.4.2连接InputDispatcher和窗口
- 5.4.3事件的发送
- 5.4.4事件的接收
- 5.4.5事件的反馈与发送循环
- 5.4.6输入事件的发送、接收与反馈总结
- 5.5关于输入系统的其他重要话题
- 5.5.1输入事件ANR的产生
- 5.5.2 焦点窗口的确定
- 5.5.3以软件方式模拟用户操作
- 5.6本章小结
- 第6章 深入理解控件系统
- 6.1 初识Android的控件系统
- 6.1.1 另一种创建窗口的方法
- 6.1.2 控件系统的组成
- 6.2 深入理解WindowManager
- 6.2.1 WindowManager的创建与体系结构
- 6.2.2 通过WindowManagerGlobal添加窗口
- 6.2.3 更新窗口的布局
- 6.2.4 删除窗口
- 6.2.5 WindowManager的总结
- 6.3 深入理解ViewRootImpl
- 6.3.1 ViewRootImpl的创建及其重要的成员
- 6.3.2 控件系统的心跳:performTraversals()
- 6.3.3 ViewRootImpl总结
- 6.4 深入理解控件树的绘制
- 6.4.1 理解Canvas
- 6.4.2 View.invalidate()与脏区域
- 6.4.3 开始绘制
- 6.4.4 软件绘制的原理
- 6.4.5 硬件加速绘制的原理
- 6.4.6 使用绘图缓存
- 6.4.7 控件动画
- 6.4.8 绘制控件树的总结
- 6.5 深入理解输入事件的派发
- 6.5.1 触摸模式
- 6.5.2 控件焦点
- 6.5.3 输入事件派发的综述
- 6.5.4 按键事件的派发
- 6.5.5 触摸事件的派发
- 6.5.6 输入事件派发的总结
- 6.6 Activity与控件系统
- 6.6.1 理解PhoneWindow
- 6.6.2 Activity窗口的创建与显示
- 6.7 本章小结
- 第7章 深入理解SystemUI
- 7.1 初识SystemUI
- 7.1.1 SystemUIService的启动
- 7.1.2 状态栏与导航栏的创建
- 7.1.3 理解IStatusBarService
- 7.1.4 SystemUI的体系结构
- 7.2 深入理解状态栏
- 7.2.1 状态栏窗口的创建与控件树结构
- 7.2.2 通知信息的管理与显示
- 7.2.3 系统状态图标区的管理与显示
- 7.2.4 状态栏总结
- 7.3 深入理解导航栏
- 7.3.1 导航栏的创建
- 7.3.2 虚拟按键的工作原理
- 7.3.3 SearchPanel
- 7.3.4 关于导航栏的其他话题
- 7.3.5 导航栏总结
- 7.4 禁用状态栏与导航栏的功能
- 7.4.1 如何禁用状态栏与导航栏的功能
- 7.4.2 StatusBarManagerService对禁用标记的维护
- 7.4.3 状态栏与导航栏对禁用标记的响应
- 7.5 理解SystemUIVisibility
- 7.5.1 SystemUIVisibility在系统中的漫游过程
- 7.5.2 SystemUIVisibility发挥作用
- 7.5.3 SystemUIVisibility总结
- 7.6 本章小结
- 第8章 深入理解Android壁纸
- 8.1 初识Android壁纸
- 8.2深入理解动态壁纸
- 8.2.1启动动态壁纸的方法
- 8.2.2壁纸服务的启动原理
- 8.2.3 理解UpdateSurface()方法
- 8.2.4 壁纸的销毁
- 8.2.5 理解Engine的回调
- 8.3 深入理解静态壁纸-ImageWallpaper
- 8.3.1 获取用作静态壁纸的位图
- 8.3.2 静态壁纸位图的设置
- 8.3.3 连接静态壁纸的设置与获取-WallpaperObserver
- 8.4 WMS对壁纸窗口的特殊处理
- 8.4.1 壁纸窗口Z序的确定
- 8.4.2 壁纸窗口的可见性
- 8.4.3 壁纸窗口的动画
- 8.4.4 壁纸窗口总结
- 8.5 本章小结