之前分析了app端bindService的流程,详细juejin.cn/post/710007… 下面来分析一下AMS端的流程
AMS端bindservice的数据类可以参考juejin.cn/post/710045…
ActivityManagerService
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String callingPackage,
int userId) throws TransactionTooLargeException {
enforceNotIsolatedCaller("bindService");
synchronized(this) {
// mServices是ActiveServices类型,是ams的属性
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}
ActiveServices
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
// 获取caller对应的ProcessRecord进程对象
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
......
// step0 获取ServiceLookupResult
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant);
ServiceRecord s = res.record;
......
final ServiceRecord serviceRecord = s;
final Intent serviceIntent = service;
try {
......
// step1 retrieveAppBindingLocked
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
// step2 将connection与activity关联 并保存到AppBindRecord
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
// 存在多个activity关联使用同一个serviceconnetion对象的情况,
// 所以ServiceRecord中的connections是ArrayMap<IBinder, ArrayList<ConnectionRecord>>
// 一个connctionbinder对应的是一个ConnectionRecord列表
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
// 创建ConnectionRecord集合
clist = new ArrayList<ConnectionRecord>();
// 保存ArrayList<ConnectionRecord>到ServiceRecord中
s.connections.put(binder, clist);
}
// ConnectionRecord保存到ConnectionRecord集合中
clist.add(c);
// 保存到AppBindRecord的connections集合
b.connections.add(c);
// 将ConnectionRecord也保存到activityrecord中,这里面是HashSet
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
// 保存到ActivityRecord的connections集合中
activity.connections.add(c);
}
// 添加到ProcessRecord进程对象中
b.client.connections.add(c);
// 属性 ArrayMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
// mServiceConnections也保存一份
clist = mServiceConnections.get(binder);
if (clist == null) {
// 创建ArrayList<ConnectionRecord>
clist = new ArrayList<ConnectionRecord>();
// 添加到mServiceConnections
mServiceConnections.put(binder, clist);
}
// 添加ConnectionRecord
clist.add(c);
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
// step3 bringUpServiceLocked
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 {
// step4 与activity建立连接
c.conn.connected(s.name, b.intent.binder, false);
} 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) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
step5 请求bindService
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
下面分析每一步
step0 获取ServiceLookupResult
private ServiceLookupResult retrieveServiceLocked(Intent service,
String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
boolean allowInstant) {
ServiceRecord r = null;
userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);
// 获取ServiceMap, 是继承handler的类,里面包装了两个ArrayMap,<ComponentName, ServiceRecord> 和
// <Intent.FilterComparison, ServiceRecord>
ServiceMap smap = getServiceMapLocked(userId);
final ComponentName comp = service.getComponent();
if (comp != null) {
// 先通过ComponentName 查找ServiceRecord
r = smap.mServicesByName.get(comp);
}
// 没有找到查找ServiceRecord 入参isBindExternal为false,再通过FilterComparison查找ServiceRecord
if (r == null && !isBindExternal) {
Intent.FilterComparison filter = new Intent.FilterComparison(service);
r = smap.mServicesByIntent.get(filter);
}
if (r == null) {
try {
// 查找pms
ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
resolvedType, flags, userId, callingUid);
ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
// 创建ComponentName
ComponentName name = new ComponentName(
sInfo.applicationInfo.packageName, sInfo.name);
r = smap.mServicesByName.get(name);
if (r == null && createIfNeeded) {
// 创建FilterComparison
final Intent.FilterComparison filter = new Intent.FilterComparison(service.cloneFilter());
final ServiceRestarter res = new ServiceRestarter();
final BatteryStatsImpl.Uid.Pkg.Serv ss;
final BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
ss = stats.getServiceStatsLocked(
sInfo.applicationInfo.uid, sInfo.packageName,
sInfo.name);
}
// 创建ServiceRecord
r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
res.setService(r);
// 缓存到ServiceMap的两个集合
smap.mServicesByName.put(name, r);
smap.mServicesByIntent.put(filter, r);
}
} catch (RemoteException ex) {
}
}
if (r != null) {
// 返回ServiceLookupResult
return new ServiceLookupResult(r, null);
}
return null;
}
大致流程是先在ServiceMap的两个集合中查找缓存,如果没有就通过pms查找注册的service信息,构造对应的ServiceRecord对象。然后加到ServiceMap的两个集合中。最后创建返回ServiceLookupResult
step1 ServiceRecord#retrieveAppBindingLocked
public AppBindRecord retrieveAppBindingLocked(Intent intent,
ProcessRecord app) {
// 包装了FilterComparison
Intent.FilterComparison filter = new Intent.FilterComparison(intent);
// 查询成员属性bindings,是一个map<Intent.FilterComparison, IntentBindRecord> 保存了FilterComparison和IntentBindRecord的映射
IntentBindRecord i = bindings.get(filter);
if (i == null) {
// 本地缓存没有, new一个加入本地
i = new IntentBindRecord(this, filter);
bindings.put(filter, i);
}
// 根据ProcessRecord获取对应的AppBindRecord,这里面可以拿到所有的conn
AppBindRecord a = i.apps.get(app);
if (a != null) {
return a;
}
// 本地没有找到 new一个AppBindRecord,保存到intent的apps集合中
a = new AppBindRecord(this, i, app);
i.apps.put(app, a);
返回AppBindRecord
return a;
}
在ServiceRecord中查找AppBindRecord, 先在本地缓存bindings中找IntentBindRecord,在根据IntentBindRecord找AppBindRecord,并返回
step2 将connection与activity关联 并保存到AppBindRecord
根据activityrecord 和 IServiceConnection 创建ConnectionRecord,并将ConnectionRecord保存到AppBindRecord、ProcessRecord、mServiceConnections各数据结构中。
step3 ActiveServices#bringUpServiceLocked
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;
final String procName = r.processName;
String hostingType = "service";
ProcessRecord app;
// 没有设置ServiceInfo.FLAG_ISOLATED_PROCESS
if (!isolated) {
// step3.1 查找对应的进程
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
// 进程存在
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
// step3.2 启动service
realStartServiceLocked(r, app, execInFg);
return null;
}
}
}
// 进程未启动
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
if (app == null && !permissionsReviewRequired) {
// step3.3 启动进程
if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, r.name, false, isolated, false)) == null) {
bringDownServiceLocked(r);
return msg;
}
}
// 添加到mPendingServices中
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
return null;
}
这边就是真正的启动service的地方了。这里分成两种情况,service运行在同app进程,那么直接 realStartServiceLocked,如果是在新进程中运行的,那么先启动进程,再启动sercie