本文基于 Android 7.1.1 源码分析,转载请说明出处!
0 综述
我们在应用中经常会启动 Service:
1 | context.bindService(intent, mConnection, Service.BIND_AUTO_CREATE); |
以前我们只是会调用,但是其底层的调用到底是什么样的呢?知其然知其所以然,今天我们就来学习下 bindService 的过程!
如果之前并不了解这块逻辑的话,那该如何去学习呢? follow the funtion path!
1 绑定者进程
1.1 ContextWrapper.bindService
1 | public class ContextWrapper extends Context { |
ContextWrapper 提供了两个方法来绑定 Service,其中一个是隐藏方法:bindServiceAsUser!
bindService 的第三个参数 flags 一般都会传 0 或 BIND_AUTO_CREATE,跨进程调用 bindService 会引起组件间的依赖,比如 A 进程的 Activity 中 bindService 调用 B 进程 service,则 B 进程的 service 的 oom_adj 值依赖于 A 进程 Activity 的 oom_adj 值,这个我们后面在说,这些 flags 也可以通过按位或的方式,进行搭配使用!!
接着来说 flags,这里的 flags 可以取值如下,Android 7.1.1 内置了如下的几个标志位:
标志位 | 解释 |
---|---|
0 | 无意义 |
BIND_AUTO_CREATE (0x0001) | 绑定服务时候,如果服务尚未创建,服务会自动创建,在 API LEVEL 14 以前的版本不支持这个标志,使用 Context.BIND_WAIVE_PRIORITY 可以达到同样效果 |
BIND_DEBUG_UNBIND (0x0002) | 通常用于 Debug,在 unbindService 时候,会将服务信息保存并打印出来,这个标记很容易造成内存泄漏,应该准备用于 debugging |
BIND_NOT_FOREGROUND (0x0002) | 表示不允许绑定操作将服务所在进程的优先级提升到前台进程优先级 |
BIND_ABOVE_CLIENT (0x0008) | 设置服务的进程优先级高于客户端的优先级,只有当需要服务晚于客户端被销毁这种情况才这样设置。 |
BIND_ALLOW_OOM_MANAGEMENT (0x0010) | 保持服务受默认的服务管理器管理,当内存不足时候,会销毁服务 |
BIND_WAIVE_PRIORITY (0x0020) | 绑定操作不会影响到服务所在进程的优先级 |
BIND_IMPORTANT (0x0040) | 标识服务对客户端是非常重要的,会将服务提升至前台进程优先级,通常情况下,即时客户端是前台优先级,服务最多也只能被提升至可见进程优先级 |
BIND_ADJUST_WITH_ACTIVITY (0x0080) | 如果绑定来自 Activity,服务优先级的提高取决于Activity的进程优先级,使用这个标识后,会无视其他标识 |
BIND_ALLOW_WHITELIST_MANAGEMENT (0x01000000) | |
BIND_FOREGROUND_SERVICE_WHILE_AWAKE (0x02000000) | |
BIND_FOREGROUND_SERVICE (0x04000000) | |
BIND_TREAT_LIKE_ACTIVITY (0x08000000) | |
BIND_VISIBLE (0x10000000) | |
BIND_SHOWING_UI (0x20000000) | 这种绑定方式会让目标服务所在进程显示出 UI 界面,当 UI 界面退出后会触发 UI_HIDDEN 类型的内存回收操作 |
BIND_NOT_VISIBLE (0x40000000) | |
BIND_EXTERNAL_SERVICE (0x80000000) | 1、通过这种方式绑定的服务是属于隔离的外部服务,服务将会被绑定到调用者应用的包内,而不是服务所在的应用包内! 2、使用这个标签进行绑定,服务的代码将会在调用者应用的包名和 uid 下执行!因为服务所在的进程是一个隔离进程,隔离进程是不能直接访问应用程序的数据的! |
具体标志位对于 Service 进程有什么影响,请看进程的优先级调度!!!
这里有一点,对于 BIND_AUTO_CREATE,如果服务没有被创建,会自动创建,而对于其他的 flags,是不会自动创建服务的!所以说我们从 Service 的生命周期的角度来说,可以把这些 flags 分为两大类,自动创建和非自动创建类!!
mBase 是 ContextImpl 对象,继续看!
1.2 ContextImpl.bindService
mMainThread 是应用进程主线程的 Handler!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
30class ContextImpl extends Context {
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}
/** @hide */
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), user);
}
/** @hide */
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
Handler handler, UserHandle user) {
if (handler == null) {
throw new IllegalArgumentException("handler must not be null.");
}
return bindServiceCommon(service, conn, flags, handler, user);
}
}
ContextImpl 和 ContextWrapper 的具体关系,请来看另一博文:Android 系统的 Context 分析,这里我们不再详细说明!
mUser:表示的是当前的设备 user!
最终,调用了 bindServiceCommon 方法;
1.3 ContextImpl.bindServiceCommon
1 | private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler |
getActivityToken 方法获得的是 ActivityClientRecord 对象,具体为什么是它,请去看 startActivity 相关的博文!!
1.3.1 LoadedApk.getServiceDispatcher
mPackageInfo 是 LoadedApk 类的实例,每一个进程都会有一个,这里调用了 LoadedApk 的 getServiceDispatcher 方法来获得一个 IServiceConnection 类型的对象,这里我们只需要知道,ServiceConnection 是应用进程中的创建的连接对象,ServiceDispatcher 用来托管 ServiceConnection 对象和 ServiceDispatcher.InnerConnection 对象的映射关系,InnerConnection 能够进行 binder 通信!!
这里会涉及一个集合:1
2private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
= new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
这个是 LoadedApk 的内部实例集合,每一个进程在创建后,都会有一个 LoadedApk 对象, mServices 集合的 key 值为 Context 对象,表示上下文运行环境,大家可以理解为特定的组件,value 是一个 ArrayMap 集合,封装了特定的组件所持有的所有服务连接对象 ServiceConnection 和服务分发对象 ServiceDispatcher!
1 | public final IServiceConnection getServiceDispatcher(ServiceConnection c, |
我们来看看 ServiceDispatcher 对象的创建:1
2
3
4
5
6
7
8
9
10
11
12
13
14ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
//【1】创建 InnerConnection 对象,用于跨进程调用!
mIServiceConnection = new InnerConnection(this);
// 初始化内部 ServiceConnection 对象!
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
mLocation = new ServiceConnectionLeaked(null);
mLocation.fillInStackTrace();
mFlags = flags;
}
接着再看看 InnerConnection 对象的创建!1
2
3
4
5InnerConnection(LoadedApk.ServiceDispatcher sd) {
//【1】持有 ServiceDispatcher 的弱引用!
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
这里就看这么多!!
我们来他通过一张图看看绑定者进程的数据结构之间的关系:
![绑定者进程中的数据结构关系.png-164.8kB][3]
其中,mActiveConnections 表示的是处于活跃中的连接信息,这个我们后面再看!
接着,调用 ActivityManagerNative.getDefault() 方法,获得 AMS 的代理对象 ActivityManagerProxy,调用代理的 bindService 方法!
1.5 ActivityManagerP.bindService
1 | public int bindService(IApplicationThread caller, IBinder token, |
通过 binder 进程间通信,进入系统进程,参数分析:
- IApplicationThread caller:调用者进程的 ApplicationThread 对象,实现了 IApplicationThread 接口;
- IBinder token:应用端的 mActivityToken;
- Intent service:启动的 intent
- String resolvedType:这个 intent 的 MIME 类型;
- IServiceConnection connection:服务连接对象 InnerConnection;
- String callingPackage:启动者所属包名;
- int userId:设备用户 id;
下面会进入系统进程!
2 系统进程
首先要进入 ActivityManagerN.onTransact 方法!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
29case BIND_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
//【1】获得 ApplicationThreadProxy 对象!
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
//【2】Activity 句柄!
IBinder token = data.readStrongBinder();
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
b = data.readStrongBinder();
int fl = data.readInt();
String callingPackage = data.readString();
int userId = data.readInt();
//【3】获得 InnerConnection 的代理对象!
IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
// 进入 AMS!
int res = bindService(app, token, service, resolvedType, conn, fl,
callingPackage, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
}
继续看!
2.1 ActivityManagerS.bindService
1 | public int bindService(IApplicationThread caller, IBinder token, Intent service, |
2.2 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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312int 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));
// 获得调用者进程 ProcessRecord 对象!
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when binding service " + service);
}
// 如果 token 不为 null 的话,就获得其对应的 ActivityRecord 对象!
ActivityRecord activity = null;
if (token != null) {
activity = ActivityRecord.isInStackLocked(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
}
int clientLabel = 0;
PendingIntent clientIntent = null;
// 判断是否是系统进程!
final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;
if (isCallerSystem) {
service.setDefusable(true);
clientIntent = service.getParcelableExtra(Intent.EXTRA_CLIENT_INTENT);
if (clientIntent != null) {
clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
if (clientLabel != 0) {
service = service.cloneFilter();
}
}
}
// 如果设置了 Context.BIND_TREAT_LIKE_ACTIVITY 的标签,
// 必须有权限 android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
mAm.enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"BIND_TREAT_LIKE_ACTIVITY");
}
// 非系统进程不能设置 BIND_ALLOW_WHITELIST_MANAGEMENT 的 flags!
if ((flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0 && !isCallerSystem) {
throw new SecurityException(
"Non-system caller " + caller + " (pid=" + Binder.getCallingPid()
+ ") set BIND_ALLOW_WHITELIST_MANAGEMENT when binding service " + service);
}
// callerFg 表示的是前台调用或者是后台调用!
final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
// 表示是否 bind 的是 isolated, external 类型的服务!
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
//【1】检索要 bind 的服务信息!
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!
ServiceRecord s = res.record;
boolean permissionsReviewRequired = false;
// 如果编译时,指定需要检测权限,那就先要通过权限的检测!
if (Build.PERMISSIONS_REVIEW_REQUIRED) {
if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
s.packageName, s.userId)) {
permissionsReviewRequired = true;
// 对于前台调用才要校验权限!
if (!callerFg) {
Slog.w(TAG, "u" + s.userId + " Binding to a service in package"
+ s.packageName + " requires a permissions review");
return 0;
}
final ServiceRecord serviceRecord = s;
final Intent serviceIntent = service;
// 校验权限后的回调!
RemoteCallback callback = new RemoteCallback(
new RemoteCallback.OnResultListener() {
public void onResult(Bundle result) {
synchronized(mAm) {
final long identity = Binder.clearCallingIdentity();
try {
if (!mPendingServices.contains(serviceRecord)) {
return;
}
if (!mAm.getPackageManagerInternalLocked()
.isPermissionsReviewRequired(
serviceRecord.packageName,
serviceRecord.userId)) {
try {
//
bringUpServiceLocked(serviceRecord,
serviceIntent.getFlags(),
callerFg, false, false);
} catch (RemoteException e) {
/* ignore - local call */
}
} else {
unbindServiceLocked(connection);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
});
// 创建 intent,启动 PackageInstaller,来校验权限!
final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName);
intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);
if (DEBUG_PERMISSIONS_REVIEW) {
Slog.i(TAG, "u" + s.userId + " Launching permission review for package "
+ s.packageName);
}
mAm.mHandler.post(new Runnable() {
public void run() {
// 启动权限校验界面!
mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
}
});
}
}
final long origId = Binder.clearCallingIdentity();
try {
//【2】取消服务的重启任务!
if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: " + s);
}
// 如果启动 flags 设置了 Context.BIND_AUTO_CREATE 标签!
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
// 更新服务的活跃时间!
s.lastActivity = SystemClock.uptimeMillis();
if (!s.hasAutoCreateConnections()) {
// 这是第一次 bind,通知服务状态监控器!
ServiceState stracker = s.getTracker();
if (stracker != null) {
stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
s.lastActivity);
}
}
}
mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState,
s.appInfo.uid, s.name, s.processName);
//【3】创建 AppBindRecord 对象,用来记录绑定到这个服务的应用的信息!
// s 是要绑定的 ServiceRecord!
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
// 创建 ConnectionRecord 对象,用来记本次的绑定连接!
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
// connection 是一个从应用进程传过来的 InnerConnection 对象!
IBinder binder = connection.asBinder();
// s.connections 记录了这个服务的 IServiceConnection 对象和 ConnectionRecord 对象的对应关系!
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
// 将 ConnectionRecord 保存到 s.connections 中!
clist.add(c);
// 将 ConnectionRecord 对象添加到对应的 AppBindRecord 的 connections 中!
b.connections.add(c);
// 如果 activity 不为 null,说明是 Activity 执行的 bind,所以要把 ConnectionRecord 添加到其 connections 中;
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
activity.connections.add(c);
}
// 将 ConnectionRecord 保存到调用者进程的 connections 列表中!
b.client.connections.add(c);
if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
b.client.hasAboveClient = true;
}
if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
s.whitelistManager = true;
}
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
// mServiceConnections 是 AS 的成员变量,记录着 IServiceConnection 和其 ConnectionRecord 的对应关系!
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
// 如果启动的 flags 设置了 Context.BIND_AUTO_CREATE 标志位,那么就进入这个分支,
// 如果服务没有被创建,就会自动创建服务!
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
// 再次更新服务的活跃时间!
s.lastActivity = SystemClock.uptimeMillis();
//【4】启动该服务,如果服务所在进程未启动,还要启动相应进程,其返回值为 null,说明启动成功!
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
// 如果服务所在进程的 ProcessRecord 不为 null,就要更新服务的优先级以及 oomAdj 的值!
if (s.app != null) {
if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
s.app.treatLikeActivity = true;
}
if (s.whitelistManager) {
s.app.whitelistManager = true;
}
mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
|| s.app.treatLikeActivity, b.client);
mAm.updateOomAdjLocked(s.app);
}
// 【*】接着进入这个分支,这里我们在下面分析:
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
+ ": received=" + b.intent.received
+ " apps=" + b.intent.apps.size()
+ " doRebind=" + b.intent.doRebind);
// 第一次自动创建方式的绑定,两个分支都不进入,多次自动创建方式的绑定,只会进入第二个分支!
if (s.app != null && b.intent.received) {
try {
//【5】服务已经在运行中了,那就尝试完成连接,会判断是否已经已有连接
// 如果有,就不会创建连接!
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.
// 【6】尝试拉起服务的 onRebind 方法!
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
// 【7】尝试拉起服务的 onBind 方法!
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
getServiceMap(s.userId).ensureNotStartingBackground(s);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
这个方法的逻辑很长,我们来简单总结一下重点!!
注意:
对于 Context.BIND_AUTO_CREATE 的方式,bringUpServiceLocked 方法中拉起 onCreate 和 onBind 方法的 Binder 通信是 IBinder.FLAGS_ONEWAY 方式,所以 Binder 服务端系统进程在触发方法后,无需等待,会立即向下执行!
这里来重点说下最后的分支部分:
这部分内容会涉及到下面的章节!!
对于 BIND_AUTO_CREATE 的这种 bindService 方式:
- 第一次绑定时,进入该分支前, received 为 false 而 requested 为 true(requested 是在 bringUpServiceLocked -> requestServiceBindingLocked 被置为 true 的),所以下面
IF
和ELSE
分支都不会进入! - 多次绑定时,因为第一次绑定连接已经生成,所以 received 和 requested 都会为 true,这里会进入第一个
IF
分支,尝试执行 ServiceConnection.onServiceConnected 方法,因为之前绑定已经存在,就不会执行!!!
- 第一次绑定时,进入该分支前, received 为 false 而 requested 为 true(requested 是在 bringUpServiceLocked -> requestServiceBindingLocked 被置为 true 的),所以下面
对于非 BIND_AUTO_CREATE 的这种 bindService 方式:
- 如果服务之前没有启动,那么不管绑定几次,都只是将绑定所数据绑定到相应的集合中,但 received 和 requested 都为 false!,所以会进入第二个
ELSE
分支,尝试拉起 onbind 方法,但是由于服务没有被创建和运行,r.app 和 r.app.thread 都为 null,所以不会继续执行! - 如果服务之前已经被启动了,我们知道对于这种情况,如果之前进行了 bindService 的操作, 因为系统已经保存了绑定信息,所以会立刻拉起服务的 onbind 方法,并执行 ServiceConnection.onServiceConnected 方法!
- 如果服务之前已经被启动了,这是我们再执行 bindService 操作:
- 第一次绑定,进入该分支前, received 和 requested 均为 false(这个第一种情况不同),这样会进入第二个
ELSE
分支,拉起服务的 onBind 方法,并执行 ServiceConnection.onServiceConnected 方法! - 多次绑定,进入该分支前, received 和 requested 均为 true,所以会进入第一个
IF
分支,尝试执行 ServiceConnection.onServiceConnected 方法,因为之前绑定已经存在,就不会执行!!!
- 第一次绑定,进入该分支前, received 和 requested 均为 false(这个第一种情况不同),这样会进入第二个
- 如果服务之前没有启动,那么不管绑定几次,都只是将绑定所数据绑定到相应的集合中,但 received 和 requested 都为 false!,所以会进入第二个
整个流程看起来复杂,但是体现在生命周期上很简单,这里就不说了!!
然后,我们来看下这个方法中的重点!!
2.2.1 ActiveServices.retrieveServiceLocked
根据 intent 来查询被启动服务的 ServiceRecord 对象,参数传递:
- boolean createIfNeeded:传入的是 true;
- boolean callingFromFg:表示是从前台调用,还是后台调用;
- boolean isBindExternal:表示 bind 的是否是 isolated, external 类型的服务,我们这里默认为 false;
1 | private ServiceLookupResult retrieveServiceLocked(Intent service, |
这个方法的最终目的是返回要启动的服务的信息封装对象 ServiceLookupResult!
2.2.2 ActiveServices.unscheduleServiceRestartLocked
如果服务此时已经在重启列表中了,就要取消这个任务!
参数传入:
- boolean force:传入 false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25private final boolean unscheduleServiceRestartLocked(ServiceRecord r, int callingUid,
boolean force) {
if (!force && r.restartDelay == 0) {
return false;
}
// Remove from the restarting list; if the service is currently on the
// restarting list, or the call is coming from another app, then this
// service has become of much more interest so we reset the restart interval.
boolean removed = mRestartingServices.remove(r);
if (removed || callingUid != r.appInfo.uid) {
// 重置重启计数!
r.resetRestartCounter();
}
if (removed) {
clearRestartingIfNeededLocked(r);
}
// 从 mAm.mHandler 中移除对一个的 ServiceStarter 对象!
c.removeCallbacks(r.restarter);
return true;
}
因为当前服务要重新启动,所以之前的重启就要重置!
2.2.3 ServiceRecord.retrieveAppBindingLocked
这里是很关键的一段逻辑,创建了很多的对象,并相互引用: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// 3、创建 AppBindRecord 对象,用来记录绑定到这个服务的应用的信息!
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
// 创建 ConnectionRecord 对象,用来记录一个连接!
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
// connection 是一个绑定者进程的 IServiceConnection.proxy 对象,和 InnerConnection 对应!!
IBinder binder = connection.asBinder();
// s.connections 记录了这个服务的 IServiceConnection 和 ConnectionRecord 的对应关系!
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
// 将 ConnectionRecord 保存到 s.connections 中!
clist.add(c);
// 将 ConnectionRecord 对象添加到对应的 AppBindRecord 的 connections 中!
b.connections.add(c);
// 如果 activity 不为 null,说明是 Activity 执行的 bind,所以要把
// 添加到其 connections 中;
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
activity.connections.add(c);
}
// 将 ConnectionRecord 保存到调用者进程的 connections 列表中!
b.client.connections.add(c);
if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
b.client.hasAboveClient = true;
}
if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
s.whitelistManager = true;
}
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
// mServiceConnections 是 AS 的成员变量,记录着 IServiceConnection 和其 ConnectionRecord 的对应关系!
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
这里调用了 ServiceRecord 的 retrieveAppBindingLocked 方法,参数 ProcessRecord app 表示绑定者所在的进程!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// in ServiceRecord
public AppBindRecord retrieveAppBindingLocked(Intent intent,
ProcessRecord app) {
// 首先,创建 FilterComparison 来封装启动 Intent!
// 并获得其对应的 IntentBindRecord 对象,这里可以看到,多次 bindService,只会保存第一次的信息!
Intent.FilterComparison filter = new Intent.FilterComparison(intent);
IntentBindRecord i = bindings.get(filter);
// 创建对应的 IntentBindRecord 对象,将 FilterComparison 和 IntentBindRecord 的映射保存到 SR.bindings 中!
if (i == null) {
i = new IntentBindRecord(this, filter);
bindings.put(filter, i);
}
// 创建 AppBindRecord 对象!
AppBindRecord a = i.apps.get(app);
if (a != null) {
return a;
}
a = new AppBindRecord(this, i, app);
i.apps.put(app, a);
return a;
}
这里会创建了一下如下对象 AppBindRecord,用来表示被绑定的 Service 和 bind 它的应用进程 ProcessRecord 的关系!1
2
3
4
5
6final class AppBindRecord {
final ServiceRecord service; // 被 bind 的服务!
final IntentBindRecord intent; // IntentBindRecord 对象
final ProcessRecord client; // bind 发起端的进程!
final ArraySet<ConnectionRecord> connections = new ArraySet<>(); // 连接到这个服务的所有 ConnectionRecord!
}
以及 IntentBindRecord 对象,用来表示绑定 Service 的 intent 的信息!1
2
3
4
5
6
7
8
9
10
11
12final class IntentBindRecord {
final ServiceRecord service; // 被 bind 的服务!
final Intent.FilterComparison intent; // intent 封装类,等价于 intent!
// 用来托管所有使用这个 intent 来绑定服务的进程 ProcessRecord 和其 AppBindRecord 的映射关系!
final ArrayMap<ProcessRecord, AppBindRecord> apps = new ArrayMap<ProcessRecord, AppBindRecord>();
IBinder binder; // 当绑定 Service 成功后,onBind 会返回 Service 的“桩”,而这个 binder 是“桩”的客户端代理!
boolean requested;
boolean received;
boolean hasBound;
boolean doRebind;
}
以及 ConnectionRecord 对象,用来表示绑定 Service 的 intent 的信息!!1
2
3
4
5
6
7
8final class ConnectionRecord {
final AppBindRecord binding; // AppBindRecord 对象!
final ActivityRecord activity; // bind 服务的 activity
final IServiceConnection conn; // 来自 bind 端的 IServiceConnection.proxy 对象!
final int flags; // bindService 的第三个参数!
final PendingIntent clientIntent; // 发送的 intent!
boolean serviceDead; // 表示服务是否死亡!
}
除此之外,在 ServiceRecord 中:1
2
3
4
5
6
7
8// 所有活跃的 intent 和其对应的 IntentBindRecord 对象!
final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings
= new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
// 所有 IServiceConnection 对象和其对应的 ArrayList<ConnectionRecord>> 列表!
final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections
= new ArrayMap<IBinder, ArrayList<ConnectionRecord>>();
// IBinder -> ConnectionRecord of all bound clients
以及在 ActiveServices 中:1
final ArrayMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections = new ArrayMap<>();
这里我们用一张图来看下这几个数据结构间的关系;
![系统进程中的数据结构关系.png-467.2kB][2]
可以看到,引用关系很复杂,这也是方便 AMS 在调度时,更快的查询到数据!!
2.3 AServices.bringUpServiceLocked
上面的代码中, 如果 flags 有设置 hasAutoCreateConnections 的话,会进入 bringUpServiceLocked 这个方法,这里和前面的 startService 很类似了,启动服务!
参数分析:
- ServiceRecord r:服务的 ServiceRecord 对象;
- int intentFlags:启动服务的 intent 的 flag,通过 getFlags 获得;
- boolean execInFg:传入 callFg,表示本次启动是前台调用还是后台调用;
- boolean whileRestarting:表示是否是正在重启,传入 false;
- boolean permissionsReviewRequired:是否需要校验权限;
我们这里假设 Service 所在的进程没有启动!
bringUpServiceLocked 的方法
1 | private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, |
注意
bindService 时候,如果设置了 Context.BIND_AUTO_CREATE 标志,就会调用 bringUpServiceLocked 方法!
然而对应 bind 来说,是不会执行 sendServiceArgsLocked 方法中的逻辑,不会拉起服务的 onStartCommand 方法的!
因为只有 start 的方式,才会将启动项目 StartItem 添加到 ServiceRecord 的 pendingStarts 集合中,而对于 bind,pendingStarts 集合的大小始终为 0,所以不会继续执行的!!
同时,对于 bindService,如果服务所在的进程已经被拉起,那么 bringUpServiceLocked 方法会在 sendServiceArgsLocked 只会返回,不会执行下面的逻辑,而是返回 bindServiceLocked ,继续往下执行!!
方法流程总结
1、如果已经启动,就会进入 realStartServiceLocked 方法,启动服务!
2、如果没有启动,就会 startProcessLocked 先启动服务所在进程,,最后进入 attachApplicationLocked 方法。然后还是会进入 realStartServiceLocked !
所以最终调用的是 realStartServiceLocked 方法,它会拉起 Service 的 onCreate、onBind 方法!
这里我们先假设,服务所在的进程,还没有被启动!!!!
2.4 ActivityManagerS.attachApplicationLocked
当应用进程启动后,会通过 Binder 通信,调用 AMS.attachApplicationLocked,我们去看看: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
64private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
... ... ... ...
// 这里会回到应用进程中,创建 Applicaiton 对象,并调用其 onCreate 方法,这里我们不看!
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
// 更新进程 LRU 队列!
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
// 每当 bindApplication 操作失败,则重新启动进程, 此处有可能会导致进程无限重启。
startProcessLocked(app, "bind fail", processName);
return false;
}
// 将当前已经被启动的新进程的 ProcessRecord 从正在启动的进程集合 mPersistentStartingProcesses
// 和等待启动的进程集合 mProcessesOnHold 中移除!
mPersistentStartingProcesses.remove(app);
mProcessesOnHold.remove(app);
boolean badApp = false;
boolean didSomething = false;
... ... ... ...
if (!badApp) {
try {
// 检查是否有 service 组件要在这个新进程中运行!
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
... ... ... ...
if (badApp) { // badApp 为 true,就杀掉这个进程
app.kill("error during init", true);
handleAppDiedLocked(app, false, true);
return false;
}
if (!didSomething) { // 检查后发现,没有任何组件要运行在新进程,更新 OomAdj 的值!
updateOomAdjLocked();
}
return true;
}
bindApplication 方法会回到应用进程中,创建 Applicaiton 对象,并调用其 onCreate 方法,这里我们不关注!!
这里会调用 ActiveServices 的 attachApplicationLocked 方法!
2.5 ActiveServices.attachApplicationLocked
当应用进程启动成功,并且 Application 对象已经创建,其 onCreate 方法已经调用后,就要启动指定的服务了!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
60boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
boolean didSomething = false;
// 还记得 mPendingServices 吗?这里面保存着所有正在等待其所在的进程启动的服务!
if (mPendingServices.size() > 0) {
ServiceRecord sr = null;
try {
// 遍历 mPendingServices 集合中的所有服务,启动属于这个进程的所有服务!
for (int i=0; i<mPendingServices.size(); i++) {
sr = mPendingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
mPendingServices.remove(i);
i--;
// 将服务的包名,版本号以及 AMS 的进程状态对象保存到进程对象中!
proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
mAm.mProcessStats);
//【1】启动服务,这里又回到了之前的方法中!
realStartServiceLocked(sr, proc, sr.createdFromFg);
didSomething = true;
if (!isServiceNeeded(sr, false, false)) {
bringDownServiceLocked(sr);
}
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting service "
+ sr.shortName, e);
throw e;
}
}
// 接着启动那些需要重启的服务,重启的服务都会保存到 mRestartingServices 服务中!
// 因为重启的时间可能还没有到,所以这里并不是立刻启动它们,而是启动了一个任务,交给了 AMS 的 MainHandler 去做!
if (mRestartingServices.size() > 0) {
ServiceRecord sr;
for (int i=0; i<mRestartingServices.size(); i++) {
sr = mRestartingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
mAm.mHandler.removeCallbacks(sr.restarter);
mAm.mHandler.post(sr.restarter);
}
}
return didSomething;
}
这里最终又回到了 realStartServiceLocked 方法!
2.6 AS.realStartServiceLocked
对于非隔离的进程,最后都会通过调用 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
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
113private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
if (DEBUG_MU)
Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
+ ", ProcessRecord.uid = " + app.uid);
// 跟新活跃时间!
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
// 将被启动服务的 ServiceRecord 对象添加到所属进程的 app.services 中!
// 如果本次启动的是一个新的服务,newService 值为 true!
final boolean newService = app.services.add(r);
// 针对 onCreate 方法,设置超时处理!
bumpServiceExecutingLocked(r, execInFg, "create");
// 更新 LruProcess 和 OomAdj!
mAm.updateLruProcessLocked(app, false, null);
mAm.updateOomAdjLocked();
boolean created = false;
try {
if (LOG_SERVICE_START_STOP) { // log 相关!
String nameTerm;
int lastPeriod = r.shortName.lastIndexOf('.');
nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
EventLogTags.writeAmCreateService(
r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
}
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
//【1】通过 binder 通信,拉起服务的 onCreate 方法!
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
// 启动成功的话,置 created 为 true 方法;
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app); // 如果在服务启动时,应用进程死了,调用 appDiedLocked 通知死亡仆告对象!
throw e;
} finally {
if (!created) { // 如果启动失败,并且不是一个被销毁的服务,那就尝试重启他!
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
if (newService) {
app.services.remove(r);
r.app = null;
}
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
if (r.whitelistManager) {
app.whitelistManager = true;
}
//【2】执行 bind 操作,这里会拉起服务的 onBind 方法!!
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
// 注意 startRequested 只有在 startService 的情况下被置为 true,所以这里是不会添加启动项的!
// 即:r.pendingStarts 的大小为 0!!
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
null, null));
}
// 这里也不会拉起 Service 的 onSrartCommand 方法,原因是 :r.pendingStarts 的大小为 0,找不到启动项!!
sendServiceArgsLocked(r, execInFg, true);
if (r.delayed) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
getServiceMap(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
if (r.delayedStop) {
r.delayedStop = false;
if (r.startRequested) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"Applying delayed stop (from start): " + r);
stopServiceLocked(r);
}
}
}
注意:
startRequested 只有在 startService 的情况下被置为 true,所以这里是不会添加启动项的!所以 sendServiceArgsLocked 也不会拉起 Service 的 onSrartCommand 方法,原因是 :r.pendingStarts 的大小为 0,找不到启动项!!
这就要进入 requestServiceBindingsLocked 方法了!!!
2.6.1 ApplicationThreadP.scheduleCreateService
这里首先会拉起 Serivce 的 onCreate 方法!1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23class ApplicationThreadProxy implements IApplicationThread {
public final void scheduleCreateService(IBinder token, ServiceInfo info,
CompatibilityInfo compatInfo, int processState) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
info.writeToParcel(data, 0);
compatInfo.writeToParcel(data, 0);
data.writeInt(processState);
try {
// 通过 Binder 通信!
mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
} catch (TransactionTooLargeException e) {
Log.e("CREATE_SERVICE", "Binder failure starting service; service=" + info);
throw e;
}
data.recycle();
}
}
进入应用进程,下面再看!!
2.6.2 ActiveServices.requestServiceBindingsLocked
1 | private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg) |
这里会遍历 r.bindings 集合,还记得这个集合吗?这个集合保存这个 bind 的 intent 和 IntentBindRecord 之间的映射关系,只有 bindService 的情况下,该集合才会有元素,startService 的情况下,该集合的 size 为 0,这就解释了 startService 为什么不会执行该方法了!!
继续来看!!
2.6.2.1 ActiveServices.requestServiceBindingLocked
参数传入:
- boolean rebind:表示是否重新 bind,这里传入的是 false!
1 | private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, |
thread 是 ApplicationThreadProxy 代理对象!!
2.6.2.2 ApplicationThreadP.scheduleBindService
这里的 IBinder token 是 ServiceRecord 对象!!1
2
3
4
5
6
7
8
9
10
11
12
13
14public final void scheduleBindService(IBinder token, Intent intent, boolean rebind,
int processState) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
intent.writeToParcel(data, 0);
data.writeInt(rebind ? 1 : 0);
data.writeInt(processState);
// binder 通信!
mRemote.transact(SCHEDULE_BIND_SERVICE_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
可以看到,拉起服务的 onCreate 方法和 onBind 方法的 binder 通信都是 IBinder.FLAG_ONEWAY 的!也就是说 Binder 服务端无需等待 BInder 客户端的操作返回结果,只要 Binder 客户端一收到 Binder服务端传送的命令和数据后,Binder 服务端会立即向下执行!
下面,进入被绑定者进程!
3 被绑定者进程
3.1 ApplicationThread.scheduleCreateService
1 | public final void scheduleCreateService(IBinder token, |
这里和 startService 一样,不多说了!
3.2 ApplicationThread.scheduleBindService
1 | public final void scheduleBindService(IBinder token, Intent intent, |
这里创建了一个 BindServiceData 对象!1
2
3
4
5
6
7
8
9static final class BindServiceData {
IBinder token;
Intent intent;
boolean rebind;
public String toString() {
return "BindServiceData{token=" + token + " intent=" + intent + "}";
}
}
很简单,不多说了!
接着,发送 H.BIND_SERVICE 方法,进入主线程的 Handler!
3.3 ActivityThread.H
1 | private class H extends Handler { |
不多说了!!
3.3.1 ActivityThread.handleCreateService
1 | private void handleCreateService(CreateServiceData data) { |
成功地拉起了 Service 的 onCreate 方法!最后有调用了 ActivityManagerNative.getDefault().serviceDoneExecuting,这个和 startService 的流程一样,这里就不多数了!
3.3.2 ActivityThread.handleBindService
1 | private void handleBindService(BindServiceData data) { |
这里,我们先默认是第一次绑定,rebind 为 false,我们在重写 Service 的 onBind 方法后,会返回一个 Stub 类型的对象,这个是 Service 这边定义的 “桩”,我们继续看!!!!
3.4 ActivityManagerProxy
这里不多说了!
1 | public void serviceDoneExecuting(IBinder token, int type, int startId, |
4 系统进程
进入 AMS,首先会进入 ActivityManagerN 的 onTransact 方法!
4.1 ActivityManagerN.onTransact
1 | case SERVICE_DONE_EXECUTING_TRANSACTION: { |
4.1.1 ActivityManagerS.serviceDoneExecuting
1 | public void serviceDoneExecuting(IBinder token, int type, int startId, int res) { |
最后进入 AS.serviceDoneExecutingLocked 方法!
4.1.1.1 ActiveServices.serviceDoneExecutingLocked
参数传递:
- int type:这里的 type 是
SERVICE_DONE_EXECUTING_ANON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
boolean inDestroying = mDestroyingServices.contains(r);
if (r != null) {
if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
... ... ... // 不进入,不看
} else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) {
... ... ... // 不进入,不看
}
final long origId = Binder.clearCallingIdentity();
// 进入 serviceDoneExecutingLocked 方法,看
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
Binder.restoreCallingIdentity(origId);
} else {
Slog.w(TAG, "Done executing unknown service from pid "
+ Binder.getCallingPid());
}
}
4.1.2 ActivityManagerS.publishService
1 | public void publishService(IBinder token, Intent intent, IBinder service) { |
继续看:
4.1.2.1 ActiveServices.publishService
1 | void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { |
这里会继续通过 Bind 回调绑定者进程的 ServcieConnection 的 onServiceDisconnected 方法!这个方法是非阻塞的,是异步的,因为有 oneway 的标志!!
c.conn 是 IServiceConnection.proxy ,即服务连接代理对象!!!这里,就要回到绑定者进程,我们后面再看!!
4.1.3 ActivityManagerS.serviceDoneExecutingLocked
1 | private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying, |
这里很简单了,就不详细说了!!
5 绑定者进程
下面来看看绑定者进程的 connected 方法的回调问题!!
IServiceConnection.aild 文件中只定义了一个接口:
1 | import android.content.ComponentName; |
可以看到,这个方法是 oneway 类型的,就是说,binder 通信是非阻塞的!
5.1 InnerConnection.connected
进入 LoadedApk 的 InnerConnection 类!1
2
3
4
5
6
7
8
9
10
11
12
13
14
15private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
// 接着,调用 ServiceDispatcher 的 connected 方法!
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service);
}
}
}
5.2 ServiceDispatcher.connected
1 | public void connected(ComponentName name, IBinder service) { |
5.3 ServiceDispatcher.RunConnection
参数传递:
- int command:0;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22private 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;
}
继续看:
5.4 ServiceDispatcher.doConnected
1 | public void doConnected(ComponentName name, IBinder service) { |
最后,我们看到,调用了 mConnection.onServiceConnected,这个方法大家很熟悉了,不多说了!
6 总结
6.1 数据结构总结
绑定者进程的数据结构关系图
一个应用进程,只会有一个 InnerConnection 对象!
系统进程的数据结构关系图
6.2 binder 通信总结
6.3 生命周期总结
对于只设置了 BIND_AUTO_CREATE 标志位的情况,只调用 bindService,Service 的周期如下:
服务没有被创建:
1
Service.onCreate() -> Service.onBind() -> ServiceConnection.onServiceConnected()
服务已经被创建:
1
Service.onBind() -> ServiceConnection.onServiceConnected()
对于没有设置 BIND_AUTO_CREATE 标志,但设置了其他标志的情况,只调用 bindService,Service 的周期如下:
服务没有被创建:
1
// 无法实现 bind 操作, 但是会将本次 bind 操作的信息保存到系统进程中!
服务之前已经被创建(之前通过 startService 启动服务,或者其他组件通过 BIND_AUTO_CREATE 方式绑定拉起):
1
Service.onBind() -> ServiceConnection.onServiceConnected()
服务之后才被创建(之后通过 startService 启动服务,或者其他组件通过 BIND_AUTO_CREATE 方式绑定拉起):
1
Service.onCreate() -> Service.onBind() (-> Service.onStartCommand) -> ServiceConnection.onServiceConnected()
对于第三中情况,是不是很奇怪?原因很简单,如果服务之前没有被创建,调用 bindService(只设置了其他标志),是不会拉起 Service.onBind 方法的,但是会把本次 bind 的信息保存相应的集合中,当服务被 startService 或者通过 BIND_AUTO_CREATE 方式绑定拉起后,会对之前的 bind 信息处理,返回之前 bind 对应的代理对象!!详情请参考 startService 篇!
对于多次调用 bindService
设置了 BIND_AUTO_CREATE 标志!
1
Service.onCreate()(once) -> Service.onBind()(once) -> ServiceConnection.onServiceConnected()(once)
如果服务已经被创建的话,那 onCreate 方法是不会调用的,直接调用 onBind 方法!
未设置 BIND_AUTO_CREATE 标志!
服务没有被启动!
1
2// 无法实现 bind 操作, 但是会将本次 bind 操作的信息保存到系统进程中,等到服务被 startService 或者其他自动创建类型的 bindService 拉起后才会执行如下周期:
Service.onBind(once) -> ServiceConnection.onServiceConnected()(once)服务已经被启动!
1
Service.onBind()(once) -> ServiceConnection.onServiceConnected()(once)
以上就是 bindService 相关的生命周期,有不对的地方,欢迎指正,谢谢!
6.4 相关 Log 参考
1 | 07-04 17:24:21.523 1761 4194 V ActiveServices: bindService: Intent { cmp=com.cooqi.servicedemo/.service.AService } type=null conn=android.os.BinderProxy@abcfcca flags=0x1 |