在前面文章我们分析了四大组件中的两个:Broadcast和Activity,这章我们分析四大组件中的服务(Service)的启动过程。Service的启动方式有两种:一种是startService,一种是bindService;第一种通常是开启一个服务执行后台任务,不进行通信,第二章通过是启动服务进行通信。下面我们就根据这两种启动方式来讲Service的启动流程以及unbindService和stopService流程。

Service启动流程-startService

首先来看启动流程时序图:

Service启动时序图

Step0.ContextImpl.startService

1
2
3
4
5
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}

调用当前类中的startServiceCommon方法。

Step1.ContextImpl.startServiceCommon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
// 检验Intent,组件和包名不能为空
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
// 通过getDefault方法获取AMS的一个代理对象(ActivityManagerProxy),然后调用这个代理对象
// 的startService方法来请求AMS启动Service
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), getOpPackageName(), user.getIdentifier());
...
return cn;
} catch (RemoteException e) {
...
}
}

首先验证Intent中传递的组件名是否为空,为什么判断下面我们介绍,接着通过代理对象ActivityManagerProxy,通过Binder调用AMS(ActivityManagerService)中的对应方法startService。我们先看包名验证。

Step2.ContextImpl.validateServiceIntent

1
2
3
4
5
6
7
8
9
10
11
12
private void validateServiceIntent(Intent service) {
if (service.getComponent() == null && service.getPackage() == null) {
if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
IllegalArgumentException ex = new IllegalArgumentException(
"Service Intent must be explicit: " + service);
throw ex;
} else {
Log.w(TAG, "Implicit intents with startService are not safe: " + service
+ " " + Debug.getCallers(2, 3));
}
}
}

这里给出了如果系统在Android5.0及以上版本,启动服务必须为显式启动,否则抛出异常,这个情况我们在刚开始在高于5.0系统都会遇到过,限制就在这里,所以,5.0及以上系统必须用显式的方式启动服务。

3.AMP.startService

1
2
3
4
5
6
7
8
9
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId) throws RemoteException {
...
// 通过Binder对象mRemote向AMS发送一个类型为START_SERVICE_TRANSACTION的进程间通信请求,
// 然后会调用AMS中的对应的startService方法
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
...
return res;
}

看过前面文章的对这一段代码应该很熟悉了,这个就是通过Binder调用AMS中对应方法的。所以我们直接看AMS。

4.AMS.startService

1
2
3
4
5
6
7
8
9
10
11
12
13
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId)
throws TransactionTooLargeException {

...
synchronized (this) {
...
ComponentName res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}

这里的mServices是ActiveServices,因此调用的是ActiveServices中的startServiceLocked方法。

5.ActiveServices.startServiceLocked

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
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, String callingPackage, final int userId)
throws TransactionTooLargeException {
...

// 解析service这个Intent,就是解析在AndroidManifest.xml定义的Service标签的intent-filter相关内容
// 并将其内容保存在Service的record(ServiceRecord)中
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
...

// 每一个Service组件都使用一个ServiceRecord对象来描述,就像每一个Activity都是用一个ActivityRecord
// 对象来描述一样
ServiceRecord r = res.record;
...
// 加入启动服务列表
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
service, neededGrants));

final ServiceMap smap = getServiceMap(r.userId);
boolean addToStarting = false;
// 如果是非前台(后台)进程调用
if (!callerFg && r.app == null
&& mAm.mUserController.hasStartedUserState(r.userId)) {
// 获取启动服务所在进程
ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
...
} else if (DEBUG_DELAYED_STARTS) {
...
}

return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}

这里做的主要是启动服务前的准备工作,首先是解析Intent携带的参数,并将这些内容保存在用来描述Service的ServiceRecord对象中保存起来,并将该对象放到等待启动服务的列表中。然后调用startServiceInnerLocked启动服务。在上面调用retrieveServiceLocked函数解析的过程中先去判断AMS中是否存在参数为service对应的ServiceRecord对象,如果存在说明已经启动过该服务,如果不存在,说明是第一次启动该服务。

8.ActiveServices.startServiceInnerLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
ServiceState stracker = r.getTracker();// 获取服务状态
...
r.callStart = false;// 是否调用onStart方法
...

// 启动ServiceRecord对象r所描述的一个Service组件,即Server组件
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
...

return r.name;
}

这里比较简单主要是调用bringUpServiceLocked唤起服务。

Step9.ActiveServices.bringUpServiceLocked

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {

// 这里的r.app.thread是一个ApplicationThread对象,ApplicationThread是用来AMS和应用进程通信的工具,
// 如果服务中的这个thread不为空说明已经和该Service存在通信了,也就是说已经启动了该服务了。
// 如果服务已经存在,调用startService的时候会执行Service.onStartCommand,
// 只有首次启动服务才会调用onCreate方法
if (r.app != null && r.app.thread != null) {
// 执行Service.onStartCommand方法过程
sendServiceArgsLocked(r, execInFg, false);
return null;
}

...

// Make sure that the user who owns this service is started. If not,
// we don't want to allow it to run.
// 确保正在启动服务的用户已经启动,否则不允许执行
if (!mAm.mUserController.hasStartedUserState(r.userId)) {
...
bringDownServiceLocked(r);
return msg;
}

...

// 是不是独立进程
final boolean isolated = (r.serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
// 首先获取ServiceRecord对象r所描述的Service组件的android:process属性,并保存在procName中
final String procName = r.processName;
ProcessRecord app;

if (!isolated) {// 要启动的服务不是独立进程
// 如果不是独立进程,通过进程名称和uid查找是否已经存在一个对应的ProcessRecord对象app,如果存在,
// 说明用来运行这个Service组件的应用进程已经存在了,因此下面的realStartServiceLocked函数在
// ProcessRecord对象app所描述的应用程序进程中启动这个Service组件。
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app != null && app.thread != null) {// 进程存在,并且该进程已经与AMS通信过,那么直接启动服务
try {
...
// 启动服务
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
...
}

// If a dead object exception was thrown -- fall through to
// restart the application.
}
} else {// 如果要启动的进程是独立进程
...
}

// 如果要启动的Service所在进程没有启动
if (app == null && !permissionsReviewRequired) {
// 启动Service所需要的进程
if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated, false)) == null) {
...
// 启动失败
bringDownServiceLocked(r);
return msg;
}
...
}

...

if (r.delayedStop) {// 如果是延迟停止的服务
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
// 停止服务
stopServiceLocked(r);
}
}

return null;
}

这里是启动服务最重要的部分,根据不同的情况进行不同的处理。首先是判断服务所在进程是否存在,如果存在调用sendServiceArgsLocked方法,最终根据条件,如果服务存在调用服务的onStartCommand方法;然后判断被启动服务的用户是否已经被启动,如果没有则停止服务,也就是调用bringDownServiceLocked方法,最终调用服务的onDestroy方法;然后判断非独立进程的服务,如果进程存在并且服务未启动的开始正式启动服务,调用realStartServiceLocked方法,最终调用onCreate方法;然后判断如果进程不存在,要启动进程,并且在app启动后启动服务,这里会调用启动失败,停止启动,因为进程启动后会启动该服务,这个过程在前面我们讲过,这里不再分析这种情况。最后是如果是延迟停止的服务这里直接停止该服务。下面我们按顺序分析这几种情况。

Step10.ActiveServices.sendServiceArgsLocked

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 sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
// 等待启动服务个数
final int N = r.pendingStarts.size();
if (N == 0) {
return;
}

while (r.pendingStarts.size() > 0) {
...
try {
..
// 标记启动服务开始
bumpServiceExecutingLocked(r, execInFg, "start");
...
// 发送消息,传动到ApplicationThread中的scheduleServiceArgs方法,最终会调用onStartCommand
r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
} catch (TransactionTooLargeException e) {
...
}
}
}

上面Step5提到启动的服务都要先放到等待启动服务列表中,因此这里先判断服务列表是否存在要启动的服务,如果不存在则不再继续执行,如果存在,循环启动服务,这里调用scheduleServiceArgs方法,其实在前面分析了很多遍,最终会发送消息ActivityThread中的Handler中的handleMessage中进行处理,然后调用ActivityThread中的handleServiceArgs方法。

Step13.ActivityThread.handleServiceArgs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void handleServiceArgs(ServiceArgsData data) {
// 获取Service对象
Service s = mServices.get(data.token);
if (s != null) {
try {
...
if (!data.taskRemoved) {// 任务没有被移除的话,调用Service.onStartCommand方法
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {// 否则调用被移除方法
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}

...
} catch (Exception e) {
...
}
}
}

根据Service对应的token去缓存中获取服务,如果有该服务那么调用服务的onStartCommand方法,如果不存在那么就要继续往下走创建服务。

Step15.ActiveServices.bringDownServiceLocked

这个方法主要是处理停止服务的方法,里面主要是断开连接,解除绑定,然后销毁服务,因为这个过程是在服务停止时会调用,所以在后面介绍,这里先不介绍了。

Step16.ActiveServices.realStartServiceLocked

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
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
...

boolean created = false;
...
// 发送信息到主线程,准备调用Service.onCreate方法
// 请求ProcessRecord对象app描述的应用程序进程将ServiceRecord独享r所描述的Service组件启动起来。
// ServiceRecord对象r所描述的Service组件启动完成之后,AMS就需要将它连接到一个请求绑定它的一个
// Activity组件中,这是通过调用AMS类的另一个成员函数requestServiceBindingLocked来实现的
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
...

// 准备调用Service.onBind方法
requestServiceBindingsLocked(r, execInFg);

...

// 准备调用Service.onStartCommand方法
sendServiceArgsLocked(r, execInFg, true);

...
}

启动服务调用三个方法,首先是通过app.thread.scheduleCreateService方法调用onCreate方法,然后通过requestServiceBindingsLocked方法调用Service.onBind方法,然后通过sendServiceArgsLocked方法调用Service.onStartCommand方法,其中最后一个方法我们分析过了,所以我们只分析前两个。第一很简单了,最终调用ActivityThread中的handleCreateService方法。

Step18.ActivityThread.handleCreateService

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
private void handleCreateService(CreateServiceData data) {
...

// 获取一个用来描述即将要启动的Service组件所在的应用程序的LoadedApk对象,并将它保存在packageInfo
// 变量中(每一个应用程序都使用一个LoadedApk对象来描述,通过它就能方位到它所描述的应用程序的资源)
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
...
// 获取类加载器
java.lang.ClassLoader cl = packageInfo.getClassLoader();
// 通过类加载器将CreateServiceData对象data描述的一个Service组件加载的内存中,并且创建它的一个
// 实例,保存在Service对象service中。因为CreateServiceData对象data描述的Service组件即为应用
// 程序的Ashmem中的Server组件,因此,Service对象service指向的Service组件实际上是一个Server组件
service = (Service) cl.loadClass(data.info.name).newInstance();
...
// 初始化一个ContextImpl对象context,用来为前面所创建的Service对象service的运行上下文环境,
// 通过它可以访问特定的应用程序资源,以及启动其他应用程序组件
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);

// 创建一个Application对象app,用来描述Service对象service所属的应用程序。
Application app = packageInfo.makeApplication(false, mInstrumentation);
// 使用Application对象app,ContextImpl对象context和CreateServiceData对象data来初始化
// Service对象service
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
// 调用Service的onCreate方法
service.onCreate();
// 以token为关键字保存Service对象service到mServices中,服务启动完成
mServices.put(data.token, service);
...
} catch (Exception e) {
...
}
}

首先获取LoadedApk对象,然后通过类加载器加载Service类,初始化Context,获取对应的Application,如果存在直接返回,如果该应用还没启动则直接创建该Application,然后通过Service的attach方法将对应的信息放置到Service中,这里面就包含ActivityThread,因此我们在Step9中可以通过这个来判断Service是不是被启动了,然后调用onCreate方法,创建完成后,将该服务以token为键,Service为值放入到缓存中,这样我们前面获取的时候就只从这里获取的,因此如果服务启动了换粗就会存在,否则不存在。下面我们分析onBind方法。

Step20.ActiveServices.requestServiceBindingsLocked

1
2
3
4
5
6
7
8
9
10
11
12
// 参数r指向一个ServiceRecord,表示一个已经启动的Service组件
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
throws TransactionTooLargeException {
for (int i = r.bindings.size() - 1; i >= 0; i--) {
// 每一个IntentBindRecord对象都用来描述若干个需要将ServiceRecord对象r所描述的Service组件
// 绑定到它们里面的应用程序进程
IntentBindRecord ibr = r.bindings.valueAt(i);
if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
break;
}
}
}

for循环调用onBind。

Step21.ActiveServices.requestServiceBindingLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 参数rebind表示是否需要将ServiceRecord对象r所描述的Service组件重新绑定到IntentBindRecord对象i
// 所描述的应用程序进程中如果为false,则说明为第一绑定
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
...
// 检查AMS是否已经为IntentBindRecord对象i所描述的应用程序进程请求过ServiceRecord对象r所描述的
// Service组件返回其内部的一个Binder本地对象。如果还没有请求requested为false并且apps的数量大于0
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
...
//会执行到Service的onBind方法
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
if (!rebind) {
// 设置为true,防止重复请求
i.requested = true;
}
...
}
}
return true;
}

这里通过调用r.app.thread.scheduleBindService方法,最终调用到ActivityThread中的handleBindService方法。

Step23.ActivityThread.handleBindService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void handleBindService(BindServiceData data) {
// 通过token来获得一个描述Service组件的Service对象
Service s = mServices.get(data.token);
if (s != null) {
try {
...
if (!data.rebind) {// 首次绑定
// 获取一个实现了IBinder接口的Binder对象
IBinder binder = s.onBind(data.intent);
...
} else {
s.onRebind(data.intent);
...
}
...
} catch (Exception e) {
...
}
}
}

现获取服务,然后判断是再次绑定还是首次绑定,如果是首次绑定调用Service.onBind方法,如果是再次绑定调用Service.onRebind方法。到这里服务的启动就完成了,其他一些操作就不分析了。下面我们先分析另外一个启动流程bindService,最后分析停止服务流程。

Service启动流程-bindService

首先来看绑定流程时序图:

Service启动时序图

Step1.ContextImpl.bindService

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

这里是绑定服务的入口位置,调用bindServiceCommon方法。

Step2.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
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd;
...
// mPackageInfo类型是LoadedApk
if (mPackageInfo != null) {
// 将ServiceConnection对象conn封装成一个实现了IServiceConnection接口的Binder本地对象sd
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
...
}
...
try {
IBinder token = getActivityToken();
...
// 通过调用代理对象ActivityManagerProxy的bindService方法将前面获得的sd对象,以及Intent对象
// service等信息发送给AMS,以便AMS可以将ServiceConnection组件启动起来
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
...
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

首先调用LoadedApk中的getServiceDispatcher方法获取实现IServiceConnection接口的Binder对象ServiceDispatcher.InnerConnection。然后调用AMP中的bindService方法,然后通过Binder通信调用AMS中的bindService方法。

Step3.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
// 每一个绑定过Service组件的Activity组件在LoadedApk类中都有一个对应的ServiceDispatcher对象,它负责将
// 这个被绑定的Service组件与绑定它的Activity组件关联起来,这些ServiceDispatcher保存在map中
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
// 检查成员变量mServices中是否存在一个以ServiceConnection对象c为关键字的ServiceDispatcher
// 对象sd,如果不存在,则创建一个并且以context为关键字保存到mServices中
if (map != null) {
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
// 调用前面获取到的ServiceDispatcher对象sd的成员函数getIServiceConnection来获取一个实现了
// IServiceConnection接口的本地Binder对象
return sd.getIServiceConnection();
}
}

首先根据ServiceConnection取缓存中获取,如果没有要初始化一个ServiceDispatcher对象,然后获取ServiceDispatcher.InnerConnection对象并且返回。

Step6.AMP.bindService

1
2
3
4
5
6
7
8
9
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection,
int flags, String callingPackage, int userId) throws RemoteException {
...
// 通过Binder对象mRemote向AMS发送一个类型为BIND_SERVICE_TRANSACTION的进程间通信请求
mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
...
return res;
}

这里通过Binder调用AMS中对应的方法。

Step7.AMS.bindService

1
2
3
4
5
6
7
8
9
10
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String callingPackage,
int userId) throws TransactionTooLargeException {
...

synchronized (this) {
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}

这里调用ActiveServices.bindServiceLocked方法。

Step8.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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
+ " type=" + resolvedType + " conn=" + connection.asBinder()
+ " flags=0x" + Integer.toHexString(flags));
// 根据caller来获取一个ProcessRecord对象callerApp用来描述AMS执行绑定Service组件操作的一个Activity
// 组件所运行在的应用程序进程
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
...

ActivityRecord activity = null;
if (token != null) {
// 通过token来获得一个ActivityRecord对象activity,用来描述正在请求AMS执行绑定Service组件
// 操作的一个Activity组件
activity = ActivityRecord.isInStackLocked(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
}

...

final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
// 是否是绑定了外部服务,这个服务不是应用中的服务,而是外部独立的服务(我们通常启动服务都是应用内部的服务)
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;

// 根据参数service来得到一个ServiceRecord对象s,用来描述即将被绑定的Service组件
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
...
// 调用ServiceRecord对象s的成员函数retrieveAppBindingLocked来得到一个AppBindRecord对象b,
// 表示ServiceRecord对象s所描述的Service组件是绑定在ProcessRecord对象callerApp所描述的一个
// 应用程序进程中的
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
// 将前面获得的APPBindRecord对象、ActivityRecord对象Activity以及参数connection封装成一个
// ConnectionRecord对象s所描述的一个Service组件,并且这个Activity组件是运行在
// ProcessRecord对象callerApp所描述的一个应用进程中的
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);

// 由于一个Service组件可能会被同一个应用程序进程中的多个Activity组件使用同一个InnerConnection
// 对象来绑定,因此,在AMS中,用来描述该Service组件的ServiceRecord对象就有可能会对应有多个
// ConnectionRecord对象。在这种情况下,这些ConnectionRecord对象就会被保存在一个列表中。
// 这个列表最终会保存在对应的ServiceRecord对象的成员变量Connection所描述的HashMap中,并且以
// 它里面的ConnectionRecord对象共同使用的一个InnerConnection代理对象的IBinder接口为关键字

// 参数connection是一个InnerConnection代理对象,因此可以获取它的一个IBinder接口binder
IBinder binder = connection.asBinder();
// 检测在ServiceRecord对象s中是否存在一个以IBinder接口binder为关键字的列表clist,如果不存在
// 创建一个,并且将clist以binder为关键字放到ServiceRecord对象成员变量connections中
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {// 没有绑定过
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
clist.add(c);// 添加绑定列表
b.connections.add(c);// 添加到关联应用和服务的对象AppBindRecord中记录绑定列表中
if (activity != null) {
if (activity.connections == null) {// 这里判断Activity里面是否绑定过服务
activity.connections = new HashSet<ConnectionRecord>();
}
// 添加到描述Activity的ActivityRecord对象中记录绑定服务的列表中
activity.connections.add(c);
}
...
// 从记录该服务所有绑定列表中获取是否存在绑定列表
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);// 添加都所有列表中

// 从前面可知flags的Context.BIND_AUTO_CREATE位等于1,因此会调用bringUpServiceLocked来启动
// ServiceRecord对象s所描述的一个Service组件,等到这个Service组件启动以后,AMS再将它与
// ActivityRecord对象Activity所描述的一个Activity绑定自来
if ((flags & Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}

...

if (s.app != null && b.intent.received) {
// Service is already running, so we can immediately
// publish the connection.
try {
// 这里的c.conn是ServiceDispatcher.InnerConnection对象,这里最终调用
// ServiceDispatcher中的doConnected方法
c.conn.connected(s.name, b.intent.binder);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", 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) {// 重新绑定
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {// 首次绑定
requestServiceBindingLocked(s, b.intent, callerFg, false);
}

getServiceMap(s.userId).ensureNotStartingBackground(s);

} finally {
Binder.restoreCallingIdentity(origId);
}

return 1;
}

这里代码比较多,所以写的注释也比较多,前面主要是判断是否绑定过该服务,并对InnerConnection进行缓存,放置到各个列表中,让Activity,Service进行联系。最后调用requestServiceBindingLocked方法,这个方法调用两次,一次是首次绑定,一个是重新绑定。

Step9.AMS.requestServiceBindingLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 参数rebind表示是否需要将ServiceRecord对象r所描述的Service组件重新绑定到IntentBindRecord对象i
// 所描述的应用程序进程中如果为false,则说明为第一绑定
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
...
// 检查AMS是否已经为IntentBindRecord对象i所描述的应用程序进程请求过ServiceRecord对象r所描述的
// Service组件返回其内部的一个Binder本地对象。如果还没有请求requested为false并且apps的数量大于0
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
// 会执行到Service的onBind方法
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
if (!rebind) {
// 设置为true,防止重复请求
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
...
}
return true;
}

这里是判断首次绑定还是重新绑定,这两种绑定都会执行绑定步骤,这里有个参数i.requested,代表是否是首次绑定,如果默认值是false,如果不是重新绑定,那么执行完绑定就会设置为true。然后调用thread.scheduleBindServic方法,这个方法讲了很多次了,最终调用ApplicationThread.scheduleBindService方法,然后通过handler调用ActivityThread.handleBindService方法。

Step10.ActivityThread.handleBindService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void handleBindService(BindServiceData data) {
// 通过token来获得一个描述Service组件的Service对象
Service s = mServices.get(data.token);
...
if (!data.rebind) {// 首次绑定
// 获取一个实现了IBinder接口的Binder对象
IBinder binder = s.onBind(data.intent);
// 调用AMS代理对象的成员函数publishService,将前面得到的Binder本地对象传递给AMS
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
}

这里如果是首次绑定调用onBind方法,否则调用onRebind方法,在首次调用绑定后还有publishService方法,自己看一下,不在详细分析了。这样绑定流程就分析完了,难度不大。下面我们开分析解绑过程。

Service解绑流程-unbindService

首先来看解绑流程时序图:

Service解绑时序图

Step1.ContextImpl.unbindService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void unbindService(ServiceConnection conn) {
...
if (mPackageInfo != null) {
// 获取将ServiceConnection对象conn封装成一个实现了IServiceConnection接口的Binder
// 本地对象sd(ServiceDispatcher.InnerConnection)
IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
getOuterContext(), conn);
try {
ActivityManagerNative.getDefault().unbindService(sd);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} else {
throw new RuntimeException("Not supported in system context");
}
}

IServiceConnection对象的获取我们前面分析过了,这里直接过,然后调用AMP.unbindService方法,最终调用AMS.unbindService方法。

Step3.AMS.unbindService

1
2
3
4
5
public boolean unbindService(IServiceConnection connection) {
synchronized (this) {
return mServices.unbindServiceLocked(connection);
}
}

这里调用ActiveServices.unbindServiceLocked方法。

Step4.ActiveServices.unbindServiceLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
boolean unbindServiceLocked(IServiceConnection connection) {
IBinder binder = connection.asBinder();
// 获取缓存中绑定列表
ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
...
try {
while (clist.size() > 0) {
ConnectionRecord r = clist.get(0);
removeConnectionLocked(r, null, null);
if (clist.size() > 0 && clist.get(0) == r) {
// In case it didn't get removed above, do it now.
Slog.wtf(TAG, "Connection " + r + " not removed for binder " + binder);
clist.remove(0);
}

....
}
} finally {
Binder.restoreCallingIdentity(origId);
}

return true;
}

首先从AMS中获取绑定过的列表,如果存在说明绑定过,然后调用removeConnectionLocked移除连接。

Step5.ActiveServices.removeConnectionLocked

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
void removeConnectionLocked(
ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
// 获取连接中的Binder对象
IBinder binder = c.conn.asBinder();
// 获取连接应用、服务和连接列表的客户端
AppBindRecord b = c.binding;
// 获取描述服务的对象
ServiceRecord s = b.service;
// 根据Binder对象获取服务绑定的连接列表
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist != null) {
clist.remove(c);// 移除该连接对象
if (clist.size() == 0) {// 如果列表为空,移除该列表
s.connections.remove(binder);
}
}
// 从连接应用、服务和连接列表的客户端中的连接列表中移除
b.connections.remove(c);
...
// 从总的缓存列表中移除
clist = mServiceConnections.get(binder);
if (clist != null) {
clist.remove(c);
if (clist.size() == 0) {
mServiceConnections.remove(binder);
}
}

mAm.stopAssociationLocked(b.client.uid, b.client.processName, s.appInfo.uid, s.name);

// 如果连接应用、服务和连接列表的客户端中的连接列表为空了,说明没有绑定了,那么移除该客户端
if (b.connections.size() == 0) {
b.intent.apps.remove(b.client);
}

if (!c.serviceDead) {// 服务还存在
if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
&& b.intent.hasBound) {
try {
...
b.intent.doRebind = false;
s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
} catch (Exception e) {
Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
serviceProcessGoneLocked(s);
}
}

...
}
}

在绑定服务的时候进行各种缓存,加入各种列表,那么在接触绑定的时候就有从之前加入的列表中删除,然后执行接触绑定。

Step7.ActivityThread.handleUnbindService

1
2
3
4
5
6
7
8
9
10
11
12
private void handleUnbindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
...
boolean doRebind = s.onUnbind(data.intent);// 调用解绑回调
...
} catch (Exception e) {
...
}
}
}

调用Service的onUnbind接触绑定。到这里接触绑定就分析完了,过程比较简单,只是上面的各种列表搞清楚要多看看。最后就剩下了stopService,我们一口气就将它分析完。

Service停止流程-stopService

首先来看停止服务流程时序图:

Service停止时序图

Step1.ContextImpl.stopSevice

1
2
3
4
5
6
// 停止服务
@Override
public boolean stopService(Intent service) {
warnIfCallingFromSystemProcess();
return stopServiceCommon(service, mUser);
}

调用stopServiceCommon停止服务。

Step2.ContextImpl.stopServiceCommon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private boolean stopServiceCommon(Intent service, UserHandle user) {
try {
// 检验Intent,组件和包名不能为空
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
int res = ActivityManagerNative.getDefault().stopService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
...
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

这里最终调用AMS的stopService方法。

Step3.AMS.stopService

1
2
3
4
5
6
7
8
public int stopService(IApplicationThread caller, Intent service,
String resolvedType, int userId) {
...

synchronized (this) {
return mServices.stopServiceLocked(caller, service, resolvedType, userId);
}
}

这里就是简单的调用ActiveServices.stopServiceLocked方法。

Step4.ActiveServices.stopServiceLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int stopServiceLocked(IApplicationThread caller, Intent service,
String resolvedType, int userId) {

// 根据caller获取调用者进程
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
...
if (r != null) {
...
stopServiceLocked(r.record);
...
return -1;
}

return 0;
}

简单的调用了stopServiceLocked方法。

Step6.ActiveServices.stopServiceLocked

1
2
3
4
private void stopServiceLocked(ServiceRecord service) {
...
bringDownServiceIfNeededLocked(service, false, false);
}

我们前面分析过bringUp的是启动服务,因此对应的bringDown的是结束服务。

Step7.ActiveServices.bringDownServiceIfNeededLocked

1
2
3
4
5
6
7
// 停止服务
private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
boolean hasConn) {
...

bringDownServiceLocked(r);
}

这里只是简单的调用了bringDownServiceLocked方法,这个方法我们在服务启动时也遇到过,只是没有分析,我们放到了停止服务的流程中来分析,下面我们看看详细代码。

Step8.ActiveServices.bringDownServiceLocked

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
private final void bringDownServiceLocked(ServiceRecord r) {

for (int conni = r.connections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> c = r.connections.valueAt(conni);
for (int i = 0; i < c.size(); i++) {
...
// 断开服务连接
cr.conn.connected(r.name, null);
...
}
}

// Tell the service that it has been unbound.
if (r.app != null && r.app.thread != null) {
for (int i = r.bindings.size() - 1; i >= 0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (ibr.hasBound) {// 所有服务与客户端已经解绑
try {
...
// 调用Service的onUnbind方法
r.app.thread.scheduleUnbindService(r,
ibr.intent.getIntent());
} catch (Exception e) {
...
}
}
}
}

...

if (r.app != null) {// 服务进程存在
...
if (r.app.thread != null) {
updateServiceForegroundLocked(r.app, false);
try {
...
// 停止服务,调用onDestroy方法
r.app.thread.scheduleStopService(r);
} catch (Exception e) {
...
...
}

这里主要有三步,第一步,断开服务连接,这个方法我们前面提到过,可以根据前面提到的去看看如何断开连接的;第二步,如果已经绑定了服务要解除绑定,这个在上面解除绑定的时候分析了该过程,因此这里就不再重复了;第三步,如果服务存在,则停止服务。我们开始分析第三步,第三步这里最终调用ActivityThread的handleStopService方法。

Step13.ActivityThread.handleStopService

1
2
3
4
5
6
private void handleStopService(IBinder token) {
Service s = mServices.remove(token);
...
s.onDestroy();
...
}

这里如果服务存在则调用服务的onDestroy方法,到这里服务的停止也就结束了。从上面看服务的整个流程相对于Activity简单的多。很容易就看懂了。其实还有一个IntentService,整个服务继承Service,只不过里面多了一个Handler,我们看看这段代码:

1
2
3
4
5
6
7
8
9
10
11
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}

@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}

如果有Handler就有发送消息的地方,那么发送消息在哪里呢,我们知道当你调用服务的时候会走onStartCommand方法:

1
2
3
4
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

这里会调用onStart方法:

1
2
3
4
5
6
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}

这里就是发送消息的时候,消息发出后会由上面的ServiceHandler来处理,我们看到构造函数里传入了一个Looper,这个是在onCreate方法中初始化的:

1
2
3
4
5
6
7
8
9
10
11
12
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.

super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();

mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}

这里创建了一个Handler线程,并且获取了它的Looper,用来循环处理消息,因此我们知道同时只能处理一个消息,等前一个消息处理完了才会处理第二个,以此类推,因此需要同时处理的不能用这个Service,另外在ServiceHandler中有个stopSelf用来在消息处理完成后停止自己,因此该服务可以说是用完自动停止,不会一直存在,占用资源。

代码地址:

直接拉取导入开发工具(Intellij idea或者Android studio)

Android_Framework_Source

Android开发群:192508518

微信公众账号:Code-MX

注:本文原创,转载请注明出处,多谢。