这篇主要讲BindService的主要逻辑 Api-27
Service的一些特性:
1.多个客户端可以绑定同一个服务
bindservice的入口为ContextImpl.bindService(Intent service, ServiceConnection conn, int flags);
然后ContextImpl.bindServiceCommon().
bindService和startService使用区别在于启动着是有渠道持有Service的渠道的,这个渠道就是IServiceConnection
ContextImpl:
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) {
//
IServiceConnection sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
//2拒绝隐式Intent
validateServiceIntent(service);
try {
...
//3.调用服务端bindService
int res = ActivityManager.getService().bindService(..., sd, ...);
...
}
}
在bindServiceCommon这个方法里先是根据conn去获得IServiceConnection,然后校验隐式Intent,最后调用服务端AMS去bindService()
服务端:
ActivityManagerService:
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);
}
...
}
这里的mServices就是AMS中用于管理Service启动的ActiveServices
ActiveServices:
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
...
//1.获得要启动的Service信息
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
...
ServiceRecord s = res.record;
...
//2.得到AppBindRecord,AppBindRecord描述的作用是连接Service和他的绑定者(IntentBindRecord)
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity, connection, flags, clientLabel, clientIntent);
//3.启动Service
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) {
return 0;
}
}
...
if (s.app != null && b.intent.received) {
//Service已经运行, 我们可以立即发布connection.
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
...
}
//4.如果是第一次连接并且被要求rebind
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
//5.
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
}
在这个方法里,首先通过retrieveServiceLocked(正常启动后返回null,只有异常返回非null)获得将要启动的Service信息,然后去找AppBindRecord,接着如果有Context.BIND_AUTO_CREATE,那么就调用bringUpServiceLocked(),启动完Service后(异步)就调用c.conn.connected()去绑定
我们回到ActiveServices.bindServiceLocked()方法里.如果已经绑定过Service就调用c.conn.connected(),否则就requestServiceBindingLocked().
ActiveServices:
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) {
...
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState);
...
return true;
}
这里开始回到客户端了,直接看ApplicationThread.scheduleBindService();
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
...
sendMessage(H.BIND_SERVICE, s);
}
case BIND_SERVICE:
handleBindService((BindServiceData)msg.obj);
break;
这里进入ActivityThread.handleBindService()方法
private void handleBindService(BindServiceData data) {
//1.首先获得之前bringUpServiceLocked通过启动的Service
Service s = mServices.get(data.token);
if (s != null) {
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
ActivityManager.getService().publishService(data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
}
}
...
}
第一次bindService的话data.rebind是false,首先通过Service.onBind()返回一个IBinder,然后把这个IBinder交给服务端AMS的publishService方法()
ActivityManagerService:
public void publishService(IBinder token, Intent intent, IBinder service) {
...
synchronized(this) {
...
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
交给ActiveServices的publishServiceLocked()方法
ActiveServices:
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
...
Intent.FilterComparison filter = new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
if (b != null && !b.received) {
b.binder = service;
b.requested = true;
b.received = true;
for (int conni = r.connections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
for (int i = 0; i < clist.size(); i++) {
...
try {
...//过滤不需要的ConnectionRecord
c.conn.connected(r.name, service, false);
}
}
}
}
}
这个方法里又看见c.conn.connected(r.name, service, false)了.
这里c是ConnectionRecord, c.conn是IServiceConnection,那么c.conn.connected()就是去调用IServiceConnection的connected(),这里的IServiceConnection实现类是InnerConnection,之前ContextImpl.bindServiceCommon的时候会通过mPackageInfo.getServiceDispatcher()去获得IServiceConnection
LoadedApk:
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);
if (map != null) {
if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
最终return sd.getIServiceConnection()返回的是mIServiceConnection
LoadedApk.ServiceDispatcher:
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
mLocation = new ServiceConnectionLeaked(null);
mLocation.fillInStackTrace();
mFlags = flags;
}
在ServiceDispatcher的构造函数里mIServiceConnection就是InnerConnection.
回到c.conn.connected()这个方法,可以看出其实就是去调InnerConnection的connected()方法
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);
}
}
}
原来InnerConnection的connected方法又去调ServiceDispatcher的connected方法,最终调doConnected方法
ServiceDispatcher:
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
...
//1.绑定过,返回
old = mActiveConnections.get(name);
if (old != null && old.binder == service) {
// Huh, already have this one. Oh well!
return;
}
if (service != null) {
// A new service is being connected... set it all up.
info = new ConnectionInfo();
info.binder = service;
info.deathMonitor = new DeathMonitor(name, service);
try {
//死亡监听
service.linkToDeath(info.deathMonitor, 0);
mActiveConnections.put(name, info);
} catch (RemoteException e) {
// This service was dead before we got it... just
// don't do anything with it.
mActiveConnections.remove(name);
return;
}
} else {
// The named service is being disconnected... clean up.
mActiveConnections.remove(name);
}
if (old != null) {
old.binder.unlinkToDeath(old.deathMonitor, 0);
}
}
// If there was an old service, it is now disconnected.
if (old != null) {
mConnection.onServiceDisconnected(name);
}
if (dead) {
mConnection.onBindingDied(name);
}
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
c.conn.connected(s.name, b.intent.binder, false);
doConnected的3个入参(ComponentName name, IBinder service, boolean dead)
- ComponentName name : ServiceRecord.name也就是启动Service的Intent的ComponentName
- IBinder service : b.intent.binder也就是AppBindRecord.IntentBindRecord.IBinder,IntentBindRecord的binder.这个值其实就是Service.onBind()返回的IBinder.
- boolean dead:传的是false
这里先判断该Service是否已经被绑定过,没有就增加一个死亡监听,然后调用ServiceConnection.onServiceConnected()
至此,Service的bind过程就分析完毕了.
网友评论