源码分析:Service的绑定过程(bindService)

ContextWrapper#bindService(除特殊说明外,以下代码都基于API25)

和Service的启动过程一样,Service的绑定过程也是从ContextWrapper开始的,mBase同样是ContextImpl类型的对象,所以真正调用的是ContextImpl的bindService方法。

1
2
3
4
5
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}

ContextImpl#bindService

1
2
3
4
5
6
7
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}

继续调用自己的bindServiceCommon方法。

ContextImpl#bindServiceCommon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd; //IServiceConnection是一个aidl文件
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
//mPackageInfo是一个LoadedApk类型的对象
//最终sd的类型是LoadedApk.ServiceDispatcher.InnerConnection
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}

//验证Service的有效性,Android 5.0版本以后不允许使用隐式调用
validateServiceIntent(service);

try {
//...

// 准备离开应用程序进程,进人ActivityManagerService进程
service.prepareToLeaveProcess(this);

//调用AMS的bindService方法来完成具体的绑定过程
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

bindServiceCommon方法主要完成了如下两件事情:

  1. 首先将客户端的ServiceConnection对象转化为LoadedApk.ServiceDispatcher.InnerConnection对象。这是通过LoadedApk的getServiceDispatcher方法来实现。

为什么不能直接使用ServiceConnection对象?

因为服务的绑定可能是跨进程的,因此ServiceConnection必须借助Binder才能让远程服务端回调自己的方法。InnerConnection就充当了Binder这个角色。而ServiceDispatcher起着连接ServiceConnection和InnerConnection的作用。

  1. 调用AMS的bindService方法来完成具体的绑定过程。

LoadedApk#getServiceDispatcher

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
/*
* mServices是一个ArrayMap对象,它的key是Context类型,value是ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>类型
* 所以存储的是当前活动的ServiceConnection和ServiceDispatcher的映射关系
*/
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
sd = map.get(c); //查找当前ServiceConnection对应的ServiceDispatcher
}
if (sd == null) { //若没有找到ServiceDispatcher
sd = new ServiceDispatcher(c, context, handler, flags); //初始化ServiceDispatcher
//若当前活动还没有ServiceConnection和ServiceDispatcher的映射关系,先创建该映射关系
if (map == null) {
map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mServices.put(context, map);
}
//在本活动新增映射关系
map.put(c, sd);
} else {
sd.validate(context, handler); //验证ServiceDispatcher
}
//返回IServiceConnection对象,该对象的真正类型是ServiceDispatcher.InnerConnection
return sd.getIServiceConnection();
}
}

该方法先是得到与当前ServiceConnection对应的LoadedApk.ServiceDispatcher对象,并最终返回ServiceDispatcher中保存的InnerConnection对象。

LoadedApk.ServiceDispatcher.InnerConnection

InnerConnection是ServiceDispatcher的静态内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private 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
15
private 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
2
3
4
5
6
7
8
9
10
11
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String callingPackage,
int userId) throws TransactionTooLargeException {
//...

synchronized(this) {
//mServices是一个ActiveServices对象
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}

然后调用ActiveServices的bindServiceLocked方法

ActiveServices#bindServiceLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
//...

//retrieveServiceLocked方法解析Service,解析结果保存在res.record中
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
if (res == null) {
return 0;
}
if (res.record == null) {
return -1;
}
ServiceRecord s = res.record; //res.record是一个ServiceRecord对象

//...

try {
//...

if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();

//当标志位为BIND_AUTO_CREATE时,正常启动服务
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}

//...

}

return 1;
}

继续调用bringUpServiceLocked,到这里开始和Service的启动过程类似,最终都是通过ApplicationThread来完成Service实例的创建并执行其onCreate方法。

ActiveServices#bringUpServiceLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
//...

final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;

if (!isolated) {
if (app != null && app.thread != null) { //如果服务所在进程已经启动
try {
realStartServiceLocked(r, app, execInFg);
return null;
}
}
}
//...

return null;
}

继续调用realStartServiceLocked,同样和Service的启动过程类似

ActiveServices#realStartServiceLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
//...

try {
//...

app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);

//...
}

requestServiceBindingsLocked(r, execInFg);

//...

sendServiceArgsLocked(r, execInFg, true);

//...
}

同样和Service的启动过程类似,这里说一下不同的,首先看requestServiceBindingsLocked方法

ActiveServices#requestServiceBindingsLocked

1
2
3
4
5
6
7
8
9
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
throws TransactionTooLargeException {
for (int i=r.bindings.size()-1; i>=0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
break;
}
}
}

其中调用了requestServiceBindingLocked方法

ActiveServices#requestServiceBindingLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if (r.app == null || r.app.thread == null) {
// If service is not currently running, can't yet bind.
return false;
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
//...

r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);

//...
} //...
}
return true;
}

r.app.thread的实现类是ActivityThread.ApplicationThread,调用其scheduleBindService方法进行Service的绑定

ActivityThread.ApplicationThread#scheduleBindService

1
2
3
4
5
6
7
8
9
10
11
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
updateProcessState(processState, false);
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;

//发送消息给H
sendMessage(H.BIND_SERVICE, s);
}

H对这个消息的处理是

1
2
3
4
5
case 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  private void handleBindService(BindServiceData data) {
//mServices是一个ArrayMap<IBinder, Service>对象,这里根据token取出相应的service
//这里的service是在前面执行handleCreateService方法时存进去的
Service s = mServices.get(data.token);

//...
if (s != null) {
try {
//...

try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent); //回调service的onBind方法
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder); //调用AMS的publishService方法
} else {
s.onRebind(data.intent); //如果多次绑定同一个service,回调onRebind方法
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}

//...
} //...
} //...
}
}

可以看到在该方法中回调了Service的onBind方法。原则上来说,这时service已经处于绑定状态,但是客户端还不知道已经成功连接service,所以继续看AMS的publishService方法

ActivityManagerService#publishService

1
2
3
4
5
6
7
8
9
10
 public void publishService(IBinder token, Intent intent, IBinder service) {
//...

synchronized(this) {
//...

//mServices是一个ActiveServices对象
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}

调用ActiveServices的publishServiceLocked方法

ActiveServices#publishServiceLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {

try {
//...

if (r != null) {
Intent.FilterComparison filter
= new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
if (b != null && !b.received) {
//...

for (int conni=r.connections.size()-1; conni>=0; conni--) {
ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);

//...

try {
//执行连接成功的回调,其中c.conn是IServiceConnection对象,
//其实现类是LoadedApk.ServiceDispatcher.InnerConnection
c.conn.connected(r.name, service);

}//...
}
}
}

//...
}
}//...
}

又跳转到了LoadedApk.ServiceDispatcher.InnerConnection的connected方法

LoadedApk.ServiceDispatcher.InnerConnection#connected

1
2
3
4
5
6
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service); //调用LoadedApk.ServiceDispatcher的connected方法
}
}

InnerConnection的connected方法又调用LoadedApk.ServiceDispatcher的connected方法

LoadedApk.ServiceDispatcher#connected

1
2
3
4
5
6
7
8
9
 public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
//mActivityThread是一个Handler对象,其实它就是ActivityThread中的H
//RunConnection就可以通过H的post方法运行在主线程
mActivityThread.post(new RunConnection(name, service, 0));
} else {
doConnected(name, 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
19
private 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
2
3
4
5
6
7
8
9
public void doConnected(ComponentName name, IBinder service) {
//...

// If there is a new service, it is now connected.
if (service != null) {
//mConnection是一个ServiceConnection对象,其保存了客户端的ServiceConnection
mConnection.onServiceConnected(name, service);
}
}

可以看到,最终是在ServiceDispatcher的doConnected方法中回调了ServiceConnection的onServiceConnected方法。至此,service的绑定过程分析完毕。

参考

-------------    本文到此结束  感谢您的阅读    -------------
0%