让我为您深入剖析bindService
的完整流程,特别是其核心------Binder对象的传递机制。这个过程堪称Android系统架构中跨进程通信(IPC) 的典范之作。
我们将遵循一个清晰的脉络进行分析:客户端发起请求 -> 系统服务处理 -> 目标服务响应 -> Binder对象返回 -> 客户端接收。
核心脉络总览
bindService
的本质是客户端(如Activity)向系统请求一个来自目标Service的Binder代理对象。整个流程涉及三次跨进程通信(IPC) ,最终将一个代表Service的Binder代理对象传递回客户端。
- IPC 1 : 客户端进程 ->
system_server
进程(AMS)。客户端向ActivityManagerService发起bindService请求。 - IPC 2 :
system_server
进程(AMS)-> 目标Service进程。如果Service未启动,AMS会先启动它,然后要求它返回一个Binder对象。 - IPC 3 : 目标Service进程 ->
system_server
进程(AMS)-> 客户端进程。Service将Binder对象通过AMS中转,最终传递回客户端的ServiceConnection
中。
下面的序列图清晰地描绘了这一复杂过程的核心交互:

源码深度剖析
我们将沿着上图所示的流程,深入关键源码。
阶段一:客户端发起绑定请求 (IPC 1)
调用起点通常是Context.bindService(Intent, ServiceConnection, int)
。具体的实现在ContextImpl
中。
文件:frameworks/base/core/java/android/app/ContextImpl.java
java
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
// ... 参数检查 ...
return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null, getUser());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, String instanceName,
Handler handler, Executor executor, UserHandle user) {
// 1. 将客户端的ServiceConnection包装成一个可跨进程传递的接口
IServiceConnection sd;
if (executor != null) {
sd = new ServiceConnectionWrapper(conn, executor);
} else {
// 关键点:创建一个LoadedApk.ServiceDispatcher.InnerConnection对象
// 它继承了IServiceConnection.Stub,是一个Binder对象,用于接收回调
sd = mMainThread.getHandler().getLooper();
if (sd == null) {
throw new IllegalStateException(...);
}
// getServiceDispatcher() 会创建一个ServiceDispatcher,
// 其内部类InnerConnection是IServiceConnection.Stub的实现。
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
// 2. 解析Intent,为启动服务做准备
validateServiceIntent(service);
ResolveInfo rInfo = mPackageInfo.getPackageManager().resolveService(...);
// 3. 调用ActivityManagerService的bindService方法
try {
// 获取AMS的Binder代理对象
IBinder token = getActivityToken();
if (token == null && ...) {
token = mMainThread.getApplicationThread();
}
// 发起远程调用!这是第一次IPC。
int res = ActivityManager.getService().bindIsolatedService(
mMainThread.getApplicationThread(), // IApplicationThread,代表客户端进程
getActivityToken(), // IBinder
service, // Intent
service.resolveTypeIfNeeded(getContentResolver()), // String
sd, // IServiceConnection,回调接口
flags, // int
instanceName, // String
getOpPackageName(), // String
user.getIdentifier()); // int
// ... 处理返回值 ...
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
关键点 1: IServiceConnection sd
这是一个Binder接口,其具体实现是LoadedApk.ServiceDispatcher.InnerConnection
。它被传递给AMS,这样AMS就拥有了一个可以回调到客户端进程的"遥控器"。当AMS拿到Service的Binder后,就会通过这个"遥控器"通知客户端。
关键点 2: ActivityManager.getService()
这是获取AMS(运行在system_server
进程)的Binder代理对象。bindIsolatedService
调用是一次从客户端到system_server
进程的IPC。
阶段二:AMS处理并转发请求 (IPC 2)
请求现在到了system_server
进程的AMS中。
文件:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
java
public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service, ...) {
// ... 权限检查等 ...
synchronized(this) {
// 调用ActiveServices的方法
return mServices.bindServiceLocked(caller, token, service, ...);
}
}
后续逻辑在ActiveServices
中,我们关注requestServiceBindingLocked
方法。
文件:frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
java
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord ibr, ...) {
// ... 各种状态检查 ...
if ((!r.getAppInfo().isSystemApp() || isSideEffect) && !r.isBoundToCaller(...)) {
// 计算时间等...
}
// 关键:向目标Service进程发送请求,要求其返回Binder对象
if (r.connections.contains(ibr) && !ibr.requested) {
try {
// r.app: ProcessRecord,代表目标Service所在进程
// r.app.getThread(): IApplicationThread,代表目标Service进程的Binder代理对象
// 这里调用scheduleBindService,是第二次IPC。
r.app.getThread().scheduleBindService(r, ibr.intent.getIntent(), rebind, r.app.getReportedProcState());
ibr.requested = true;
} catch (RemoteException e) {
// ...
}
}
return true;
}
关键点: r.app.getThread().scheduleBindService(...)
r.app.getThread()
是目标Service所在进程的IApplicationThread
代理对象。这行代码发起了一次从system_server
进程到目标Service进程 的IPC,通知它执行bindService
操作。
阶段三:目标Service创建并返回Binder (IPC 3的起点)
请求现在到了目标Service进程。IApplicationThread
的实现是ActivityThread
中的内部类ApplicationThread
。
文件:frameworks/base/core/java/android/app/ActivityThread.java
java
// class ActivityThread
private class ApplicationThread extends IApplicationThread.Stub {
public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) {
// 发送一个BIND_SERVICE消息到主线程Handler
sendMessage(H.BIND_SERVICE, s);
}
}
public void handleMessage(Message msg) {
switch (msg.what) {
case BIND_SERVICE:
handleBindService((BindServiceData) msg.obj);
break;
// ...
}
}
private void handleBindService(BindServiceData data) {
// 1. 根据token获取之前已创建的Service
Service s = mServices.get(data.token);
if (s != null) {
try {
// 2. 调用Service的onBind方法!这是开发者实现返回IBinder对象的地方。
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
IBinder binder = s.onBind(data.intent);
// 3. 关键:将onBind返回的IBinder对象通知给AMS
ActivityManager.getService().publishService(
data.token, // ServiceRecord的token
data.intent, // Intent
binder); // 真正的Binder对象!!!
// ...
} catch (RemoteException e) {
// ...
}
}
}
关键点 1: IBinder binder = s.onBind(data.intent);
这里调用了开发者重写的onBind
方法,返回了我们自定义的Binder对象。
关键点 2: ActivityManager.getService().publishService(...)
这行代码极其重要!它再次获取AMS的代理,并调用其publishService
方法,将刚从onBind
获取的原始Binder对象 作为参数传递过去。这是第三次IPC的起点,从目标Service进程 回到**system_server
进程(AMS)** 。
阶段四:AMS将Binder传递回客户端 (IPC 3的终点)
现在我们回到AMS的publishService
方法。
文件:frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
java
public void publishService(IBinder token, Intent intent, IBinder service) {
synchronized(this) {
// 1. 根据token找到对应的ServiceRecord和IntentBindRecord
ServiceRecord r = (ServiceRecord) token;
IntentBindRecord b = r.bindings.get(intent.getFilter());
if (b != null && !b.received) {
b.binder = service; // 保存Service返回的Binder对象
b.requested = true;
b.received = true;
// 2. 遍历所有连接到这个Service的客户端
for (int conni = b.connections.size() - 1; conni >= 0; conni--) {
ConnectionRecord c = b.connections.get(conni);
// 3. 关键:调用客户端的connected方法
try {
// c.conn: 就是第一阶段传来的IServiceConnection代理对象
// 这里调用connected,发起第三次IPC的后续部分:system_server -> 客户端进程
c.conn.connected(r.name, service, false);
} catch (RemoteException e) {
// ...
}
}
}
// ...
}
}
关键点: c.conn.connected(r.name, service, false);
c.conn
就是第一阶段由客户端创建并传递给AMS的IServiceConnection
代理对象。此时,AMS通过调用它的connected
方法,将从Service那里拿到的原始Binder对象作为参数传递回去。
这发起了第三次IPC的后半部分:从system_server
进程到最初的客户端进程。
阶段五:客户端在回调中接收Binder对象
现在我们回到客户端进程。还记得第一阶段创建的IServiceConnection
实现吗?它叫LoadedApk.ServiceDispatcher.InnerConnection
。
文件:frameworks/base/core/java/android/app/LoadedApk.java
java
private static final class ServiceDispatcher {
// 这个内部类继承了IServiceConnection.Stub
private final class InnerConnection extends IServiceConnection.Stub {
@Override
public void connected(ComponentName name, IBinder service, boolean dead) {
// 将调用转发给外部的ServiceDispatcher
mDispatcher.connected(name, service, dead);
}
}
// ServiceDispatcher的方法
public void connected(ComponentName name, IBinder service, boolean dead) {
// 1. 通过Handler抛到主线程执行
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, dead, 0));
} else {
// ...
}
}
private final class RunConnection implements Runnable {
public void run() {
// 2. 最终在这里调用到开发者传入的ServiceConnection对象的onServiceConnected方法!
if (mCommand == 0) {
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
}
public void doConnected(ComponentName name, IBinder service, boolean dead) {
// ... 旧的连接处理 ...
if (service != null) {
// 3. 最终回调!将AMS传过来的原始Binder对象交给开发者
mConnection.onServiceConnected(name, service);
}
}
}
关键点: mConnection.onServiceConnected(name, service);
这个mConnection
就是开发者最初在bindService
时传入的ServiceConnection
对象。参数service
就是来自目标Service的原始Binder对象 。对于客户端来说,如果Service在另一个进程,这个service
实际上是一个Binder代理对象;如果在同一进程,则是直接的对象引用。
至此,整个Binder传递流程圆满结束。
总结与核心要点
- 三次IPC:流程清晰地分为三次跨进程调用,环环相扣。
- Binder对象传递 :Service的
onBind
返回的IBinder
对象,通过AMS中转,最终原封不动地传递给了客户端的onServiceConnected
。AMS并不关心这个Binder对象的具体内容,它只负责传递。 - 回调桥梁 :客户端在第一步构造的
IServiceConnection
(InnerConnection
)是整个回调机制的关键。它是一个Binder对象,让AMS拥有了"呼叫"客户端的能力。 - 代理与Stub :如果Service在远程,客户端在
onServiceConnected
中拿到的是Binder代理对象(Proxy),开发者需要将其转换为自定义的AIDL接口,后续的方法调用将直接与远程Service通信,不再经过AMS。如果在同一进程,则是直接的对象调用。 - 线程切换 :所有从Binder线程(IPC调用到达的线程)到主线程的切换,都是由
ActivityThread
的Handler
和ServiceDispatcher
完成的,确保了开发者的回调发生在主线程。
通过这次源码之旅,我们可以看到Android系统如何通过Binder这一核心机制,精巧地实现了组件间的解耦和通信。希望这份分析能让你对bindService
的理解提升到一个新的高度。