龙空技术网

Binder篇-bindService源码

黑键 57

前言:

当前兄弟们对“bind绑定器”大概比较关切,同学们都需要知道一些“bind绑定器”的相关资讯。那么小编在网络上搜集了一些有关“bind绑定器””的相关知识,希望兄弟们能喜欢,大家一起来学习一下吧!

前言:

查看源码时,切记要把持好自己的方向和尺度,忌刨根问底,最好是能联系已有的思维,这样才能快速看完想要看的源码。

正如标题说的,我们今天要干的事是就是查看 bindService() 源码。

为什么要查看这个方法的源码呢?

关于这个问题,其实我们可以想一下,我们在开发过程中可能会用到 PackageManagerService、ActivityManagerService、InputManagerService 等系统服务,这些系统服务是 Android 系统启动时就被初始化完成,他们彼此存在于单独的进程当中,当我们使用这些系统服务的时候,就会 “跨进程” 去访问他们。

而在获取到这些系统服务的过程中,SystemService 这个系统服务发挥了很重要的作用,他就像一个平台一样,帮助我们得到我们想要的系统服务,然后完成我们想要完成的操作。

这个时候,我们想一下,上一篇文章中编写的 AIDL 实例,还记得我们是如何从 Client 端绑定到 Server 端的吗?

Server 端是一个 service ,我们想要使用 Server 端的逻辑,需要先绑定服务即 bindService() ,然后开始通过上图中第一步 asInterface() 拿到服务端的代理 Proxy,然后才开始进行我们想要的操作,所以 bindService() 是我们实现 binder 跨进程通信的出发点。

此外我们使用系统服务,其出发点也是 bindService(),我们在使用 bindService() 时,本质也是在使用 ActivityManagerService 的 bindService() 方法,所以研究这个 bindService() 方法本身就是跨进程通信。

好了,废话不多说了,我们开始吧。

① 从我们的实例 bindService() 方法开始

进入 ContextWrapper 中的 bindService()

这里需要提一下,ContextWrapper 是 Context 类的包装实现类,而Context的另一个实现类是 功能实现类 ContextImpl 类。

继续点击,进入 Context 的 bindService() 方法

但是看到没有,这里面bindService() 方法是抽象方法,所以我们需要跳到 Context 的功能实现类去

进入 ContextImpl 的 bindService() 方法

其中 warnIfCallingFromSystemProcess() 是判断是否是由系统内部调用的,我们这里直接忽略,看下方的 bindServiceCommon() 逻辑。

绿框的是一些安全校验,红框的是我们重点要看的。

ActivityManagerNative.getDefault().bindService();

进入 ActivityManagerNative.getDefault()

那么 gDefault 是什么呢?

而 Singleton.java 是这么定义的

分析:gDefault 是一个Singleton 类型的类,通过 create() 方法创建出对象,然后通过 get() 方法返回。

查看 Singleton 方法的 create() 内部

IBinder b = ServiceManager.getService("activity");

此方法返回了一个 IBinder 对象。

查看 ServiceManager 中的 getService() 方法

返回的 IBinder 对象是通过 sCache 中查到对应的元素返回的

而 sCache 是这样的

private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();

是一个由名字和 IBinder 为 key、value 的 Map 。

sCache 的初始化时是程序启动时自动初始化的

所以,我们可以先理解为 这里就是拿到了一个 key 为 "activity" 的 IBinder 对象。

再来看

  IActivityManager am = asInterface(b);

asInterface() 这个方法是不是很熟悉,我们上一篇文章中就是通过

asInterface() 方法从客户端获取到 aidl 的 Proxy 代理类,进而访问到服务端代码的。

这里其实也是相通的。

那么 IActivityManager 是什么呢?

继承自 IInterface ,所以我们可以推理出他就是一个 aidl 文件,这个就跟我们定义好 aidl 文件之后,通过 make project 得到了Android Studio 为我们生成的 aidl 的 “.java” 文件是一样的原理。

我们先来看一下我们上篇文章的 aidl 文件的结构 IMyAidlInterface.java 文件

这个生成的 aidl 的 .java 文件既包括了 Stub 类,也包括了 Proxy 类。

并且在生成的 .java 文件的 Stub 和 Proxy 都实现了 aidl 的接口,如下

好了,到这里,我们再来看一下系统给我们提供的 ActivityManager 的 aidl 的 .java 文件

他就是一个单纯的 interface 接口文件,内部并没有定义 Stub 类和 Proxy 类。

而我们想看的是

  IActivityManager am = asInterface(b);

实际上就是 IActivityManager 的实现类

根据类的关系,我们知道 ActivityManagerNative 就是 IActivityManager 的 Stub 类,所以

 IActivityManager am = asInterface(b);

会调用到这个地方

ActivityManagerNative.asInterface(b);

作用就是得到 ActivityManager 的代理 ActivityManagerProxy 类对象。

那么续上步

ActivityManagerNative.getDefault().bindService();

实际上就是

ActivityManagerProxy.bindService();

那么就很清晰了,此时 ActivityManagerProxy 像上篇文章一样通过 transact 方法调用到 Stub 中的方法,进而连接到真正的 Server 端的处理逻辑,我们继续看。

调用

mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);

看到这里,回想一下上篇文章中,我们分析过 Proxy 调用 transact 方法,会调用 Stub 端的 onTransact() 方法,所以我们今天就不分析过程了,直接跳到 Stub 端的 onTransact()。

onTransact() 方法 会对传入的 code 进行判断

由于我们传入的是 BIND_SERVICE_TRANSACTION

所以我们直接跳到对应的位置:

可以看到 Stub 调用了bindService 的方法,由上篇文章的分析我们知道,这个时候 Stub 会直接调用 Server 端的逻辑了,我们直接跳到 ActivityManagerNative 的实现类 ActivityManagerService。

找到对应的 bindService() 方法

忽略前面的校验,我们看到这个方法

mServices.bindServiceLocked();

mServices 类型就是 ActiveServices,好,我们进入

进入 ActiveServices 中的 bindServiceLocked() 方法

这个方法很长,截取主要逻辑:

我们先看第一个红框中的关键方法

// 创建 ServicebringUpServiceLocked()

方便起见,直接定位到关键代码

// 当 app 启动时,创建 Service 逻辑realStartServiceLocked()

我们继续进入

红框内为关键代码

app:

进入

定位到 thread:

可以看出这又是一个 aidl ,红框内

scheduleCreateService();

是创建 Service 的方法,而这个也是通过 aidl 完成访问的,这里 aidl 的调用过程就不再详述了,直接列出调用逻辑

IApplicationThread -> aidl接口;IApplicationThread aidl 文件的 Stub -> ApplicationThreadNative;IApplicationThread aidl 文件的 Proxy -> ApplicationThreadProxy;IApplicationThread aidl 文件(ApplicationThreadNative)他的 Stub 的实现类 -> ActivityThread.ApplicationThread(是个内部类)

所以我们直接定位到

ApplicationThreadProxy.scheduleCreateService()

进而定位到 Stub 的 onTransact(),这里对应的就是

ApplicationThreadNative.onTransact();

这个方法中的

scheduleCreateService()

即为真正创建 Service 的方法,也就是 Stub 的实现类处理的。

也就是

ActivityThread.ApplicationThread.scheduleCreateService();

而其内部又是由

 sendMessage(H.CREATE_SERVICE,s);

实现的。那么我们应该去 Handler 中去找他的处理方法了。

找到对应的

handleMessage()方法

定位到

handleCreateService();

到这里,我们想要连接的 Service 就通过类加载器创建 并且启动了,此实例也被存放到mServices中方便后续的创建和绑定(服务只能创建和绑定一次)。

回想一下,我们在上篇文章中,仅仅是将 Server 端安装到了手机上,并未开启的情况下,就能通过 Client 端 “绑定并且启动” ,就是因为“服务端的Service” 是通过类加载器的方法创建出来的。

好,我们继续看

第二个红框的方法 ActiveServices.requestServiceBindingLocked();

ActiveServices.requestServiceBindingLocked();

既然第一个方法是创建并且启动 Service,那么这个方法应该就是绑定 Service 的处理了。

其他逻辑先忽略我们直接进入主要的逻辑

r.app.thread.scheduleBindService();

仍然是创建 Service 类内部的逻辑

进入

再进入

再进入 handleMessage()

再进入

红框内区分了两种情况:未绑定、已绑定。

如果未绑定,那么会调用

IBinder binder = s.onBind(data.intent);ActivityManagerNative.getDefault().publishService(data.token, data.intent, binder);

否则会调用

s.onRebind();

我们先看第一个

// 通过 intent 获取到服务端 onBind()的返回值 IBinderIBinder binder = s.onBind(data.intent);

然后将此服务端的 IBinder 对象通过下方代码传递给客户端

ActivityManagerNative.getDefault().publishService(data.token, data.intent, binder);

好,我们深入一下看看

ActivityManagerNative.getDefault();

上文已经分析过,此方法会直接调用 ActivityManagerService 的方法:

跳转

内部的逻辑在这里

//连接我们传递过来的 Service(服务端的 IBinder)c.conn.connected(r.name, service);

c: ConnectionRecord

conn:

再进入 IServiceConnection 发现他也是一个 aidl 文件

通过关联搜索定位到 IServiceConnection 的引用位置

发现

InnerConnection 是 IserviceConnection.Stub 的实现类,也就是真正IServiceConnection 的 connected 方法的实现。

sd 的 connected(); 方法

doConnected 方法

所以,我们推论最终的绑定服务的实现是这样的

c.conn.connected(r.name, service);==>MainActivity 中的 onServiceConnected()

其实我们从MainActivity 中的 bindService 追踪 conn 的路径也能得到这个结论。

MainActivity.bindService(intent, conn, BIND_AUTO_CREATE);              ContextWrapper.bindService(Intent service, ServiceConnection conn,            int flags);ContextImpl.bindService(Intent service, ServiceConnection conn,            int flags);ContextImpl.bindServiceCommon(Intent service, ServiceConnection conn, int flags,            UserHandle user);

进入

此方法最终会调用到 MainActivity 中 ServiceConnetion 的回调

onServiceConnected(ComponentName name, IBinder service)

这样,我们就把 bindService 从开始到结束变成一个环路,这个过程其实就是 Binder 机制。

好了,绕了这么大圈,其实简单总结一下就是这样的。

抽空画了个流程图,方便梳理过程:

标签: #bind绑定器