Service的绑定过程

基于Android U

ContextImpl到AMS的调用过程

我们可以用bindService()方法来绑定Service,它在ContextWrapper中实现。

1
2
3
4
5
frameworks/base/core/java/android/content/ContextWrapper.java
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}

mBase指的是ContextImpl,Activity的attach()方法中将ContextImpl赋值给ContextWrapper的成员变量mBase。

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
frameworks/base/core/java/android/app/ContextImpl.java
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, Integer.toUnsignedLong(flags), null,
mMainThread.getHandler(), null, getUser());
}

private boolean bindServiceCommon(Intent service, ServiceConnection conn, long flags,
String instanceName, Handler handler, Executor executor, UserHandle user) {
IServiceConnection sd;
...
if (mPackageInfo != null) {
// 1
if (executor != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
} else {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
} else {
...
}
validateServiceIntent(service);
try {
...
int res = ActivityManager.getService().bindServiceInstance(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, instanceName, getOpPackageName(), user.getIdentifier()); // 2
...
} catch (RemoteException e) {
...
}
}

在bindService()方法中会返回bindServiceCommon()方法。

注释1处调用了LoadedApk类型的对象mPackageInfo的getServiceDispatcher()方法,它的主要作用是将ServiceConnection封装成IServiceConnection类型的对象sd,从IServiceConnection的名字我们就能得知它实现了Binder机制,这样Service的绑定就支持了跨进程。

注释2处调用了AMS的bindServiceInstance()方法。

Service的绑定过程

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
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, long flags, String instanceName,
String callingPackage, int userId) throws TransactionTooLargeException {
return bindServiceInstance(caller, token, service, resolvedType, connection, flags,
instanceName, false, INVALID_UID, null, null, callingPackage, userId);
}

private int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, long flags, String instanceName,
boolean isSdkSandboxService, int sdkSandboxClientAppUid,
String sdkSandboxClientAppPackage,
IApplicationThread sdkSandboxClientApplicationThread,
String callingPackage, int userId)
throws TransactionTooLargeException {
...
try {
...
synchronized (this) {
return mServices.bindServiceLocked(caller, token, service, resolvedType, connection,
flags, instanceName, isSdkSandboxService, sdkSandboxClientAppUid,
sdkSandboxClientAppPackage, sdkSandboxClientApplicationThread,
callingPackage, userId); // 1
}
} finally {
...
}
}

注释1处调用mServices的bindServiceLocked()方法,mServices的类型是ActiveServices。

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, long flags,
String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid,
String sdkSandboxClientAppPackage, IApplicationThread sdkSandboxClientApplicationThread,
String callingPackage, final int userId)
throws TransactionTooLargeException {
...
ServiceLookupResult res = retrieveServiceLocked(service, instanceName,
isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg,
isBindExternal, allowInstant, null /* fgsDelegateOptions */,
inSharedIsolatedProcess); // 1
...
ServiceRecord s = res.record; // 2
final AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp, attributedApp); // 3
...
try {
...
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent,
callerApp.uid, callerApp.processName, callingPackage, res.aliasComponent);
...
if (c.hasFlag(Context.BIND_AUTO_CREATE)) { // 4
...
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired, packageFrozen, true) != null) { // 5
mAm.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_BIND_SERVICE);
return 0;
}
}
...
if (s.app != null && b.intent.received) { // 6
final ComponentName clientSideComponentName =
res.aliasComponent != null ? res.aliasComponent : s.name;
try {
c.conn.connected(clientSideComponentName, b.intent.binder, false); // 7
} catch (Exception e) {
...
}

// If this is the first app connected back to this binding,
// and the service had previously asked to be told when
// rebound, then do so.
if (b.intent.apps.size() == 1 && b.intent.doRebind) { // 8
requestServiceBindingLocked(s, b.intent, callerFg, true); // 9
}
} else if (!b.intent.requested) { // 10
requestServiceBindingLocked(s, b.intent, callerFg, false); // 11
}
...
} finally {
...
}
...
return 1;
}

ServiceRecord:用于描述一个Service;

ProcessRecord:一个进程的信息;

ConnectionRecord:用于描述应用程序进程和Service建立的一次通信;

IntentBindRecord:用于描述绑定Service的Intent;

AppBindRecord:应用程序进程通过Intent绑定Service时,会通过AppBindRecord来维护Service与应用程序进程之间的关联。其内部存储了谁绑定的Service(ProcessRecord)、被绑定的Service(ServiceRecord)、绑定Service的Intent(IntentBindRecord)和所有绑定通信记录的信息(ArrayMap<ConnectionRecord>)。

注释1处的retrieveServiceLocked()方法会查找是否有与参数service对应的ServiceRecord,如果没有找到,就会调用PackageManagerService去获取参数service对应的Service信息,并封装到ServiceRecord中,最后将ServiceRecord封装为ServiceLookupResult返回。其中ServiceRecord用于描述一个Service,和ActivityRecord类似。

在注释2处通过注释1处返回的ServiceLookupResult得到参数service对应的ServiceRecord。

注释3处根据callerApp来获取其中某个发起端信息AppBindRecord:intent、ServiceRecord、ProcessRecord。一个服务可以被多个发起端绑定。

注释4处如果设置了标记BIND_AUTO_CREATE,则注释5处调用bringUpServiceLocked()拉起服务,一般bindService()中flag都会设置。bringUpServiceLocked()中又调用realStartServiceLocked()方法,最终由ActivityThread来调用Service的onCreate()方法启动Service,这也说明了bindService()方法内部会启动Service。

注释6处s.app != null表示Service已经运行,其中s时ServiceRecord类型对象,app是ProcessRecord类型对象。b.intent.received表示当前应用程序进程已经接收到绑定Service时返回的Binder,这样应用程序进程就可以通过Binder来获取要绑定的Service的访问接口。在注释7处调用c.conn的connected()方法,其中c.conn指的是IServiceConnection,它的具体实现为ServiceDispatcher.InnerConnection,其中ServiceDispatcher是LoadedApk的内部类,InnerConnection的connected()方法内部会调用H的post()方法向主线程发送消息,并且解决当前应用程序进程和Service跨进程通信的问题。

在注释8处如果当前应用程序进程是第一个与Service进行绑定的,并且Service已经调用过onUnBind()方法,则需要调用注释9处的代码。

在注释10处如果应用程序进程的Client端没有发送过绑定Service的请求,则会调用注释11处的代码,注释11处和注释9处的代码区别就是最后一个参数rebind为false,表示不是重新绑定。

1
2
3
4
5
6
7
8
9
10
11
12
13
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen,
boolean enqueueOomAdj)
throws TransactionTooLargeException {
try {
...
return bringUpServiceInnerLocked(r, intentFlags, execInFg, whileRestarting,
permissionsReviewRequired, packageFrozen, enqueueOomAdj);
} finally {
...
}
}

调用bringUpServiceInnerLocked()。

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
39
40
41
42
43
44
45
46
47
48
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private String bringUpServiceInnerLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen,
boolean enqueueOomAdj)
throws TransactionTooLargeException {
...
final String procName = r.processName; // 1
...
ProcessRecord app;

if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid); // 2
...
if (app != null) {
final IApplicationThread thread = app.getThread();
final int pid = app.getPid();
final UidRecord uidRecord = app.getUidRecord();
if (thread != null) { // 3
try {
...
realStartServiceLocked(r, app, thread, pid, uidRecord, execInFg,
enqueueOomAdj); // 4
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
}
} else {
...
}

if (app == null && !permissionsReviewRequired && !packageFrozen) { // 5
if (r.isSdkSandbox) {
...
} else {
app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated); // 6
}
...
}
...
return null;
}

注释1处得到ServiceRecord的processName值并赋给procName,其中processName用来描述Service想要在哪个进程中运行,默认是当前进程,我们也可以在AndroidManifest.xml文件中设置android:process属性来新开启一个进程运行Service。

在注释2处将procName和Service的uid传入到AMS的getProcessRecordLocked()方法中,查询是否存在一个与Service对应的ProcessRecord类型的对象app,ProcessRecord主要用来描述运行的应用程序进程的信息。

在注释5处判断Service对应的app为null则说明用来运行Service的应用程序进程不存在,则调用注释6处的AMS的startProcessLocked()方法来创建对应的应用程序进程。

这里只讨论没有设置android:process属性,即应用程序进程存在的情况。在注释3处判断如果用来运行Service的应用程序进程存在,则调用注释4处的realStartServiceLocked()方法来启动Service。

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
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,
boolean enqueueOomAdj) throws RemoteException {
...

final ProcessServiceRecord psr = app.mServices;
final boolean newService = psr.startService(r);
bumpServiceExecutingLocked(r, execInFg, "create",
OOM_ADJ_REASON_NONE /* use "none" to avoid extra oom adj */); // 1
...
try {
...
thread.scheduleCreateService(r, r.serviceInfo,
null /* compatInfo (unused but need to keep method signature) */,
app.mState.getReportedProcState()); // 2
...
} catch (DeadObjectException e) {
...
} finally {
...
}
...
requestServiceBindingsLocked(r, execInFg); // 3
...
}

注释1处发送延时消息,前台服务20s,后台服务200s。

注释2处scheduleCreateService()回调app端创建service对象,执行onCreate()。

注释3处开始执行bind流程。

1
2
3
4
5
6
7
8
9
10
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
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;
}
}
}

遍历bindings集合,开始绑定流程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
...
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind", OOM_ADJ_REASON_BIND_SERVICE); // 1
...
r.app.getThread().scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.mState.getReportedProcState(), mBindServiceSeqCounter++); // 2
...
} catch (TransactionTooLargeException e) {
...
} catch (RemoteException e) {
...
}
}
return true;
}

注释1处设置绑定超时;

注释2处scheduleBindService()回调到app端的onBind()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
frameworks/base/core/java/android/app/ActivityThread$ApplicationThread

private class ApplicationThread extends IApplicationThread.Stub {
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState, long bindSeq) {
updateProcessState(processState, false);
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;
s.bindSeq = bindSeq;
...
sendMessage(H.BIND_SERVICE, s);
}
}

首先将Service的信息封装成BindServiceData对象,BindServiceData的成员变量rebind的值为false。接着将BindServiceData传入到sendMessage()方法中。sendMessage()向H发送消息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
frameworks/base/core/java/android/app/ActivityThread.java
class H extends Handler {
public void handleMessage(Message msg) {
...
switch (msg.what) {
...
case BIND_SERVICE:
...
handleBindService((BindServiceData)msg.obj);
...
break;
...
}
...
}
}

H在接收到BIND_SERVICE类型消息时,会在handleMessage()方法中调用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
27
28
frameworks/base/core/java/android/app/ActivityThread.java
private void handleBindService(BindServiceData data) {
CreateServiceData createData = mServicesData.get(data.token);
Service s = mServices.get(data.token); // 1
...
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess(isProtectedComponent(createData.info),
s.getAttributionSource());
try {
if (!data.rebind) { // 2
IBinder binder = s.onBind(data.intent); // 3
ActivityManager.getService().publishService(
data.token, data.intent, binder); // 4
} else {
s.onRebind(data.intent); // 5
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
} catch (RemoteException ex) {
...
}
} catch (Exception e) {
...
}
}
}

注释1处获取要绑定的Service。注释2处的BindServiceData的成员变量rebind值为false,这样会调用注释3处的代码来调用Service的onBind()方法,到这里Service处于绑定状态了。

如果rebind的值为true就会调用注释5处的Service的onRebind()方法,结合前面bindServiceLocked()方法的注释8,得出的结论是:如果当前应用程序进程第一个与Service进行绑定,并且Service已经调用过onUnBind()方法,则会调用Service的onRebind()方法。handlerBindService()有两个分支,一个是绑定过Service的情况,另一个是未绑定的情况,这里分析未绑定的情况。查看注释4处的代码,实际上是调用AMS的publishService()方法。

1
2
3
4
5
6
7
8
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void publishService(IBinder token, Intent intent, IBinder service) {
...
synchronized(this) {
...
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}

在publishService()中调用了ActiveServices类型的mServices对象的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
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
...
if (r != null) {
...
if (b != null && !b.received) {
...
ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
for (int conni = connections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
...
final ComponentName clientSideComponentName =
c.aliasComponent != null ? c.aliasComponent : r.name;
try {
c.conn.connected(clientSideComponentName, service, false); // 1
} catch (Exception e) {
...
}
}
}
}
...
}
} finally {
...
}
}

注释1处的代码前面介绍过,c.conn指的是IServiceConnection,它是ServiceConnection在本地的代理,用于解决当前应用程序进程和Service跨进程通信的问题,具体实现为ServiceDispatcher.InnerConnection,其中ServiceDispatcher是LoadedApk的内部类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
frameworks/base/core/java/android/app/LoadedApk.java
static final class ServiceDispatcher {
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, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead); // 1
}
}
}
}

注释1处调用了ServiceDispatcher类型的sd对象的connected()方法。

1
2
3
4
5
6
7
8
9
10
11
12
frameworks/base/core/java/android/app/LoadedApk.java
static final class ServiceDispatcher {
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityExecutor != null) {
mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
} else if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead)); // 1
} else {
doConnected(name, service, dead);
}
}
}

在注释1处调用Handler类型的对象mActivityThread的post()方法,mActivityThread实际上指向的是H。因此,通过调用H的post()方法将RunConnection对象的内容运行在主线程中。RunConnection是LoadedApk的内部类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
frameworks/base/core/java/android/app/LoadedApk.java
static final class ServiceDispatcher {
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
mName = name;
mService = service;
mCommand = command;
mDead = dead;
}

public void run() {
if (mCommand == 0) {
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}

final ComponentName mName;
final IBinder mService;
final int mCommand;
final boolean mDead;
}
}

在RunConnection的run()方法中调用了doConnected()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
frameworks/base/core/java/android/app/LoadedApk.java
static final class ServiceDispatcher {
public void doConnected(ComponentName name, IBinder service, boolean dead) {
...
// If there was an old service, it is now disconnected.
if (old != null) {
mConnection.onServiceDisconnected(name);
}
if (dead) {
mConnection.onBindingDied(name);
} else {
// If there is a new viable service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service); // 1
} else {
// The binding machinery worked, but the remote returned null from onBind().
mConnection.onNullBinding(name);
}
}
}
}

在注释1处调用了ServiceConnection类型的对象mConnection的onServiceConnected()方法,这样在客户端实现了ServiceConnection接口类的onServiceConnected()就会被执行。


Service的绑定过程
https://citrus-maxima.github.io/2024/03/10/Service的绑定过程/
作者
柚子树
发布于
2024年3月10日
许可协议