Android系统的Service有两种启动方式,第一种是startService启动,第二种是bindService绑定。服务绑定状态时,多用于和其他组件通信。
Intent intentNormal = new Intent(ServiceActivity.this, NormalService.class);
startService(intentNormal);
Intent intentNormalBind = new Intent(ServiceActivity.this, NormalService.class);
bindService(intentNormalBind, conn, Service.BIND_AUTO_CREATE);
本文分析在Activity组件中调用bindService方法,实现Service绑定的流程,解释一下Service的onBind方法,App自定义实现类ServiceConnection的#onServiceConnected方法调用时机。
参考源码
我们在Activity组件中调用bindService方法,看一下打印日志。
AppServiceLifeCycle: LifeCycleService LifeCycleService 构造方法
LifeCycleService onCreate 方法
LifeCycleService onBind 方法
触发三个方法,构造方法,创建方法和绑定方法。Activity组件继承Context的装饰类ContextWrapper,在它的bindService方法中,调用的是ContextImpl实现类的bindService方法。
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, Process.myUserHandle());
}
进入bindServiceCommon方法代码。
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
IServiceConnection sd;
//抛出conn空的异常
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
} else {
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
//Ams请求
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
if (res < 0) {
//异常
}
return res != 0;
} catch (RemoteException e) {
}
}
在该方法中,访问Ams服务,调用服务的bindService方法,传递参数包括ApplicationThread回调App进程,IBinder token代表该Activity在Ams中唯一标志,还有一个IServiceConnection对象。
系统没有将我们自定义ServiceConnection传给Ams服务,根据它由LoadedApk获取IServiceConnection。从系统源码中可以看出,IServiceConnection是一个aidl文件,InnerConnection是Binder类型,继承IServiceConnection.stub类,进程通信的服务端,和ApplicationThread是原理一样,Ams服务回调App进程。看一下LoadedApk的getServiceDispatcher方法。
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) {
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);
}
return sd.getIServiceConnection();
}
}
系统将ServiceConnection和ServiceDispatcher的关系保存在一个ArrayMap,根据Context和ServiceConnection定位ServiceDispatcher,未查到则创建一个新ServiceDispatcher。它的内部封装InnerConnection(Binder),ServiceConnection(服务回调),Context和ActivityThread。
Service绑定Ams服务流程
下面看一下ActivityManagerService的bindService方法处理过程。
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);
}
}
委托Ams内部ActiveServices类。下面的都是该类的方法。
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags,
String callingPackage, int userId) throws TransactionTooLargeException {
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
//ProcessRecord是空抛异常
ActivityRecord activity = null;
//根据token查找Ams中的ActivityRecord记录
if (token != null) {
activity = ActivityRecord.isInStackLocked(token);
//记录是空返回0
}
ServiceRecord s = res.record;
try {
...
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
return 0;
}
}
if (s.app != null && b.intent.received) {
try {
c.conn.connected(s.name, b.intent.binder);
} catch (Exception e) {
}
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);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
调用bringUpServiceLocked方法。
private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting) throws TransactionTooLargeException {
//如果app和thread存在,直接回调app进程onStartCommand方法,
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
//不存在,继续走流程
realStartServiceLocked方法。
}
然后,调用realStartServiceLocked方法,通过scheduleCreateService方法回调App进程,创建Service,生命周期方法onCreate。
最后,bindServiceLocked方法会调用到requestServiceBindingLocked方法,回调App进程的scheduleBindService方法。回传参数IBinder(Ams的ServiceRecord记录),Intent。在App进程,发送BIND_SERVICE消息到ActivityThread的H中处理。
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
//服务返回Binder
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
}
} catch (Exception e) {
}
}
}
根据token,查找绑定的Service类,调用Service的onBind方法。返回Binder对象,这时,服务已经被绑定。
publishService方法,回访Ams服务,将Binder发布到Ams,由Ams负责通知客户端。三个参数,都是scheduleBindService方法传过来的。
Ams的publishService方法,调用ActiveServices#publishServiceLocked方法。
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
...
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
if (!filter.equals(c.binding.intent.intent)) {
continue;
}
try {
c.conn.connected(r.name, service);
} catch (Exception e) {
}
}
ConnectionRecord内部conn是InnerConnection,Ams服务利用它进程通信,通知App进程。调用InnerConnection的connected方法,并将Binder返回绑定触发者,即Activity组件中自定义的ServiceConnection类。ServiceDispatcher的connected方法。
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0));
} else {
doConnected(name, service);
}
}
ServiceDispatcher构造方法传入Handler,它就是从ActivityThread获取的H类。看一下RunConnection任务。执行doConnected方法。
public void doConnected(ComponentName name, IBinder service) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
...
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
调用ServiceDispatcher内部ServiceConnection的方法。到这里,我们在开发中遇到的Service绑定最常见的两个方法都执行过了,注意,只有onBind方法返回Binder对象不空时,才会调用onServiceConnected方法。
总结
Service绑定流程与其他组件启动类似,向Ams注册要绑定的服务类,通过ApplicationThread类实现App回调通知。在Ams服务中,如果发现服务未创建时,首先通知App生成服务实例,生命周期方法onCreate。
App进程Service绑定成功,将服务Binder通知到Ams服务,最后,Ams服务再利用IServiceConnection进程间业务接口将服务已经连接的事情通知在Activity中自定义的服务连接对象ServiceConnection,并告知它服务Binder。
任重而道远
网友评论