文章目录
- ContextWrapper#bindService(除特殊说明外,以下代码都基于API25)
- ContextImpl#bindService
- ContextImpl#bindServiceCommon
- ContextImpl#bindServiceCommon(API26)
- ActivityManagerService#bindService
- ActiveServices#requestServiceBindingsLocked
- ActivityThread.ApplicationThread#scheduleBindService
- ActivityManagerService#publishService
- 参考
ContextWrapper#bindService(除特殊说明外,以下代码都基于API25)
和Service的启动过程一样,Service的绑定过程也是从ContextWrapper开始的,mBase同样是ContextImpl类型的对象,所以真正调用的是ContextImpl的bindService方法。
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
ContextImpl#bindService
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}
继续调用自己的bindServiceCommon方法。
ContextImpl#bindServiceCommon
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd; //IServiceConnection是一个aidl文件
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
//mPackageInfo是一个LoadedApk类型的对象
//最终sd的类型是LoadedApk.ServiceDispatcher.InnerConnection
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
//验证Service的有效性,Android 5.0版本以后不允许使用隐式调用
validateServiceIntent(service);
try {
//...
// 准备离开应用程序进程,进人ActivityManagerService进程
service.prepareToLeaveProcess(this);
//调用AMS的bindService方法来完成具体的绑定过程
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
bindServiceCommon方法主要完成了如下两件事情:
- 首先将客户端的ServiceConnection对象转化为LoadedApk.ServiceDispatcher.InnerConnection对象。这是通过LoadedApk的getServiceDispatcher方法来实现。
为什么不能直接使用ServiceConnection对象?
因为服务的绑定可能是跨进程的,因此ServiceConnection必须借助Binder才能让远程服务端回调自己的方法。InnerConnection就充当了Binder这个角色。而ServiceDispatcher起着连接ServiceConnection和InnerConnection的作用。
- 调用AMS的bindService方法来完成具体的绑定过程。
LoadedApk#getServiceDispatcher
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
/*
* mServices是一个ArrayMap对象,它的key是Context类型,value是ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>类型
* 所以存储的是当前活动的ServiceConnection和ServiceDispatcher的映射关系
*/
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
sd = map.get(c); //查找当前ServiceConnection对应的ServiceDispatcher
}
if (sd == null) { //若没有找到ServiceDispatcher
sd = new ServiceDispatcher(c, context, handler, flags); //初始化ServiceDispatcher
//若当前活动还没有ServiceConnection和ServiceDispatcher的映射关系,先创建该映射关系
if (map == null) {
map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mServices.put(context, map);
}
//在本活动新增映射关系
map.put(c, sd);
} else {
sd.validate(context, handler); //验证ServiceDispatcher
}
//返回IServiceConnection对象,该对象的真正类型是ServiceDispatcher.InnerConnection
return sd.getIServiceConnection();
}
}
该方法先是得到与当前ServiceConnection对应的LoadedApk.ServiceDispatcher对象,并最终返回ServiceDispatcher中保存的InnerConnection对象。
LoadedApk.ServiceDispatcher.InnerConnection
InnerConnection是ServiceDispatcher的静态内部类
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) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service);
}
}
}
系统会通过InnerConnection来调用ServiceConnection的onServiceConnected方法,这个过程有可能是跨进程的。
ContextImpl#bindServiceCommon(API26)
在API26中,bindServiceCommon方法有一处小改变
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
//...
try {
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
//...
return res != 0;
} //...
}
可以看出,主要是获取AMS的方法变了,但是最终都是获取到AMS,然后调用AMS的bindService方法。
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) {
//mServices是一个ActiveServices对象
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}
然后调用ActiveServices的bindServiceLocked方法
ActiveServices#bindServiceLocked
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
//...
//retrieveServiceLocked方法解析Service,解析结果保存在res.record中
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 s = res.record; //res.record是一个ServiceRecord对象
//...
try {
//...
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
//当标志位为BIND_AUTO_CREATE时,正常启动服务
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
//...
}
return 1;
}
继续调用bringUpServiceLocked,到这里开始和Service的启动过程类似,最终都是通过ApplicationThread来完成Service实例的创建并执行其onCreate方法。
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;
if (!isolated) {
if (app != null && app.thread != null) { //如果服务所在进程已经启动
try {
realStartServiceLocked(r, app, execInFg);
return null;
}
}
}
//...
return null;
}
继续调用realStartServiceLocked,同样和Service的启动过程类似
ActiveServices#realStartServiceLocked
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
//...
try {
//...
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
//...
}
requestServiceBindingsLocked(r, execInFg);
//...
sendServiceArgsLocked(r, execInFg, true);
//...
}
同样和Service的启动过程类似,这里说一下不同的,首先看requestServiceBindingsLocked方法
ActiveServices#requestServiceBindingsLocked
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
throws TransactionTooLargeException {
for (int i=r.bindings.size()-1; i>=0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
break;
}
}
}
其中调用了requestServiceBindingLocked方法
ActiveServices#requestServiceBindingLocked
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if (r.app == null || r.app.thread == null) {
// If service is not currently running, can't yet bind.
return false;
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
//...
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
//...
} //...
}
return true;
}
r.app.thread的实现类是ActivityThread.ApplicationThread,调用其scheduleBindService方法进行Service的绑定
ActivityThread.ApplicationThread#scheduleBindService
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
updateProcessState(processState, false);
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;
//发送消息给H
sendMessage(H.BIND_SERVICE, s);
}
H对这个消息的处理是
case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
接着调用handleBindService方法
ActivityThread.ApplicationThread#handleBindService
private void handleBindService(BindServiceData data) {
//mServices是一个ArrayMap<IBinder, Service>对象,这里根据token取出相应的service
//这里的service是在前面执行handleCreateService方法时存进去的
Service s = mServices.get(data.token);
//...
if (s != null) {
try {
//...
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent); //回调service的onBind方法
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder); //调用AMS的publishService方法
} else {
s.onRebind(data.intent); //如果多次绑定同一个service,回调onRebind方法
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
//...
} //...
} //...
}
}
可以看到在该方法中回调了Service的onBind方法。原则上来说,这时service已经处于绑定状态,但是客户端还不知道已经成功连接service,所以继续看AMS的publishService方法
ActivityManagerService#publishService
public void publishService(IBinder token, Intent intent, IBinder service) {
//...
synchronized(this) {
//...
//mServices是一个ActiveServices对象
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
调用ActiveServices的publishServiceLocked方法
ActiveServices#publishServiceLocked
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
try {
//...
if (r != null) {
Intent.FilterComparison filter
= new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
if (b != null && !b.received) {
//...
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++) {
ConnectionRecord c = clist.get(i);
//...
try {
//执行连接成功的回调,其中c.conn是IServiceConnection对象,
//其实现类是LoadedApk.ServiceDispatcher.InnerConnection
c.conn.connected(r.name, service);
}//...
}
}
}
//...
}
}//...
}
又跳转到了LoadedApk.ServiceDispatcher.InnerConnection的connected方法
LoadedApk.ServiceDispatcher.InnerConnection#connected
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service); //调用LoadedApk.ServiceDispatcher的connected方法
}
}
InnerConnection的connected方法又调用LoadedApk.ServiceDispatcher的connected方法
LoadedApk.ServiceDispatcher#connected
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
//mActivityThread是一个Handler对象,其实它就是ActivityThread中的H
//RunConnection就可以通过H的post方法运行在主线程
mActivityThread.post(new RunConnection(name, service, 0));
} else {
doConnected(name, service);
}
}
接着看下RunConnection的定义
LoadedApk.ServiceDispatcher.RunConnection
RunConnection是ServiceDispatcher的内部类
private 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;
}
其run方法在传入的command为0时调用了doConnected方法
LoadedApk.ServiceDispatcher#doConnected
public void doConnected(ComponentName name, IBinder service) {
//...
// If there is a new service, it is now connected.
if (service != null) {
//mConnection是一个ServiceConnection对象,其保存了客户端的ServiceConnection
mConnection.onServiceConnected(name, service);
}
}
可以看到,最终是在ServiceDispatcher的doConnected方法中回调了ServiceConnection的onServiceConnected方法。至此,service的绑定过程分析完毕。
参考
- 《Android开发艺术探索》
- Android服务之bindService源码分析