ContextWrapper#bindService(除特殊说明外,以下代码都基于API25)
和Service的启动过程一样,Service的绑定过程也是从ContextWrapper开始的,mBase同样是ContextImpl类型的对象,所以真正调用的是ContextImpl的bindService方法。1
2
3
4
5
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
ContextImpl#bindService
1 |
|
继续调用自己的bindServiceCommon方法。
ContextImpl#bindServiceCommon
1 | private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler |
bindServiceCommon方法主要完成了如下两件事情:
- 首先将客户端的ServiceConnection对象转化为LoadedApk.ServiceDispatcher.InnerConnection对象。这是通过LoadedApk的getServiceDispatcher方法来实现。
为什么不能直接使用ServiceConnection对象?
因为服务的绑定可能是跨进程的,因此ServiceConnection必须借助Binder才能让远程服务端回调自己的方法。InnerConnection就充当了Binder这个角色。而ServiceDispatcher起着连接ServiceConnection和InnerConnection的作用。
- 调用AMS的bindService方法来完成具体的绑定过程。
LoadedApk#getServiceDispatcher
1 | public final IServiceConnection getServiceDispatcher(ServiceConnection c, |
该方法先是得到与当前ServiceConnection对应的LoadedApk.ServiceDispatcher对象,并最终返回ServiceDispatcher中保存的InnerConnection对象。
LoadedApk.ServiceDispatcher.InnerConnection
InnerConnection是ServiceDispatcher的静态内部类1
2
3
4
5
6
7
8
9
10
11
12
13
14private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service);
}
}
}
系统会通过InnerConnection来调用ServiceConnection的onServiceConnected方法,这个过程有可能是跨进程的。
ContextImpl#bindServiceCommon(API26)
在API26中,bindServiceCommon方法有一处小改变1
2
3
4
5
6
7
8
9
10
11
12
13
14
15private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
//...
try {
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
//...
return res != 0;
} //...
}
可以看出,主要是获取AMS的方法变了,但是最终都是获取到AMS,然后调用AMS的bindService方法。
ActivityManagerService#bindService
1 | public int bindService(IApplicationThread caller, IBinder token, Intent service, |
然后调用ActiveServices的bindServiceLocked方法
ActiveServices#bindServiceLocked
1 | int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, |
继续调用bringUpServiceLocked,到这里开始和Service的启动过程类似,最终都是通过ApplicationThread来完成Service实例的创建并执行其onCreate方法。
ActiveServices#bringUpServiceLocked
1 | private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, |
继续调用realStartServiceLocked,同样和Service的启动过程类似
ActiveServices#realStartServiceLocked
1 | private final void realStartServiceLocked(ServiceRecord r, |
同样和Service的启动过程类似,这里说一下不同的,首先看requestServiceBindingsLocked方法
ActiveServices#requestServiceBindingsLocked
1 | private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg) |
其中调用了requestServiceBindingLocked方法
ActiveServices#requestServiceBindingLocked
1 | private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, |
r.app.thread的实现类是ActivityThread.ApplicationThread,调用其scheduleBindService方法进行Service的绑定
ActivityThread.ApplicationThread#scheduleBindService
1 | public final void scheduleBindService(IBinder token, Intent intent, |
H对这个消息的处理是1
2
3
4
5case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
接着调用handleBindService方法
ActivityThread.ApplicationThread#handleBindService
1 | private void handleBindService(BindServiceData data) { |
可以看到在该方法中回调了Service的onBind方法。原则上来说,这时service已经处于绑定状态,但是客户端还不知道已经成功连接service,所以继续看AMS的publishService方法
ActivityManagerService#publishService
1 | public void publishService(IBinder token, Intent intent, IBinder service) { |
调用ActiveServices的publishServiceLocked方法
ActiveServices#publishServiceLocked
1 | void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { |
又跳转到了LoadedApk.ServiceDispatcher.InnerConnection的connected方法
LoadedApk.ServiceDispatcher.InnerConnection#connected
1 | public void connected(ComponentName name, IBinder service) throws RemoteException { |
InnerConnection的connected方法又调用LoadedApk.ServiceDispatcher的connected方法
LoadedApk.ServiceDispatcher#connected
1 | public void connected(ComponentName name, IBinder service) { |
接着看下RunConnection的定义
LoadedApk.ServiceDispatcher.RunConnection
RunConnection是ServiceDispatcher的内部类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command) {
mName = name;
mService = service;
mCommand = command;
}
public void run() {
if (mCommand == 0) {
doConnected(mName, mService);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
final ComponentName mName;
final IBinder mService;
final int mCommand;
}
其run方法在传入的command为0时调用了doConnected方法
LoadedApk.ServiceDispatcher#doConnected
1 | public void doConnected(ComponentName name, IBinder service) { |
可以看到,最终是在ServiceDispatcher的doConnected方法中回调了ServiceConnection的onServiceConnected方法。至此,service的绑定过程分析完毕。
参考
- 《Android开发艺术探索》
- Android服务之bindService源码分析