前言
前几天深入研究了Activity的启动流程之后,尝到了研究源码的甜头,趁热打铁,准备把四大组件都研究一遍,今天来研究研究Service的启动流程,由于Service可以通过start和bind方式来启动,所以两部分分开研究。
一、Start方式时序图
二、Start方式追踪
1. ContextWrapper.startService()
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
这里的mBase是ContextImpl类型,在上一篇分析Activity的时候我们看到过,ContextImpl完成了Context的大部分逻辑,主要是Activity通过attach方法来建立关联,这里是使用了桥接模式,让ContextWrapper的操作交给ContextImpl去完成。
2. ContextImpl.startService()
@Override
public ComponentName startService(Intent service) {
//当system进程调用此方法时,打印warn信息
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}
3. ContextImpl.startServiceCommon()
private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
//检查Intent是否符合要求
validateServiceIntent(service);
//Intent可能跨进程传输,检验安全性
service.prepareToLeaveProcess(this);
//通过AMS的接口拉起服务
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), getOpPackageName(), user.getIdentifier());
//权限检查,省略部分代码
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
这里我们先看一下validateServiceIntent()方法:
private void validateServiceIntent(Intent service) {
//Intent中既没有指定Component,也没有指定Package,即以隐式启动的方式拉起服务
if (service.getComponent() == null && service.getPackage() == null) {
//当版本大于Android L,即Android 5.0时,会抛出异常
if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
IllegalArgumentException ex = new IllegalArgumentException(
"Service Intent must be explicit: " + service);
throw ex;
} else {
Log.w(TAG, "Implicit intents with startService are not safe: " + service
+ " " + Debug.getCallers(2, 3));
}
}
}
需要注意的是,在Android5.0之后,已经不建议隐式启动service了,在Android5.0以下采用隐式启动时会提示warning,而在Android5.0以上,则直接报异常。
回到上面的startServiceCommon()方法往下看,我们看到了熟悉的ActivityManagerNative.getDefault(),我们已经知道这个就是ActivityManagerService(AMS)了,那么这里显然又通过了跨进程的方式把启动service的任务交给了AMS。
4. ActivityManagerService.startService()
public ComponentName startService(//省略参数)
throws TransactionTooLargeException {
//当调用者是孤立进程,则抛出异常。
enforceNotIsolatedCaller("startService");
//省略部分代码
synchronized(this) {
final int callingPid = Binder.getCallingPid();//调用者pid
final int callingUid = Binder.getCallingUid();//调用者uid
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
这里的mServices类型为ActiveServices,在AMS初始化时得到。在早期的安卓版本中并没有这个类,后来重构时抽出这个类专门用来管理Service。
5. ActiveServices.startServiceLocked()
ComponentName startServiceLocked(//省略参数) throws TransactionTooLargeException {
final boolean callerFg;
if (caller != null) {
//通过AMS得到调用方的进程信息
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
//省略部分代码
//判断调用方是否属于前台进程
callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
} else {
callerFg = true;
}
//检索待启动的Service
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
//省略部分代码
//如果这个服务在重启列表中,清空对应的信息
if (unscheduleServiceRestartLocked(r, callingUid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r);
}
//如果启动的是非前台进程,且同时服务对应的ServiceRecord中没有记录对应进程的信息(即初次使用),
if (!callerFg && r.app == null
//且user已经启动过其它进程
&& mAm.mUserController.hasStartedUserState(r.userId)) {
//通过AMS查询Service对应的进程信息
ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
//若Service对应的进程未启动,或优先级过低,则有可能需要延迟启动服务
if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
//当超出 同一时间允许后续启动的最大服务数,则将该服务加入延迟启动的队列
Slog.i(TAG_SERVICE, "Delaying start of: " + r);
smap.mDelayedStartList.add(r);
r.delayed = true;
return r.name;
}
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying: " + r);
addToStarting = true;
} else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
//将新的服务加入到后台启动队列,该队列也包含当前正在运行其他services或者receivers的进程
addToStarting = true;
//省略部分代码
return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}
这个方法主要是判断当前Service是否需要延迟启动,如果需要延迟启动,则将ServiceRecord保存到smap中的mDelayedStartList中,并结束本启动流程;否则,调用startServiceInnerLocked函数,进入启动Service的下一个阶段。
6. ActiveServices.startServiceInnerLocked()
ComponentName startServiceInnerLocked(//省略参数) throws TransactionTooLargeException {
ServiceState stracker = r.getTracker();
if (stracker != null) {
//更新ServiceRecord的ServiceState
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
}
r.callStart = false;
synchronized (r.stats.getBatteryStats()) {
//用于耗电统计,开启运行的状态
r.stats.startRunningLocked();
}
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
//上文提到的,后台进程启动的service才有可能将addToStarting置为true
if (r.startRequested && addToStarting) {
boolean first = smap.mStartingBackground.size() == 0;
//将ServiceRecord加入到smap中的mStartingBackground中
smap.mStartingBackground.add(r);
//设置启动Service的超时时间
r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;
if (first) {
//first为true,说明之前mStartingBackground中的Service处理完毕
//调用smap的rescheduleDelayedStarts函数
smap.rescheduleDelayedStarts();
}
} else if (callerFg) {
//若当前Service被后台进程启动过,现在重新被前台进程启动
//则将其从mStartingBackground中移除,并调用rescheduleDelayedStarts函数(后台服务少了一个,故可能可以继续处理等待的延迟服务)
//若mDelayedStartList存在该服务的记录,移除对应的信息
smap.ensureNotStartingBackground(r);
}
return r.name;
}
7. ActiveServices.bringUpServiceLocked()
private String bringUpServiceLocked(//省略参数) throws TransactionTooLargeException {
//Service已经启动
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
//等待延迟重启的过程,则直接返回
if (!whileRestarting && r.restartDelay > 0) {
return null;
}
//启动service前,把service从重启服务队列中移除
if (mRestartingServices.remove(r)) {
r.resetRestartCounter();
clearRestartingIfNeededLocked(r);
}
//service正在启动,将delayed设置为false
if (r.delayed) {
getServiceMap(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
//确保拥有该服务的user已经启动,否则停止;
if (!mAm.mUserController.hasStartedUserState(r.userId)) {
String msg = "";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
return msg;
}
//Service正在启动,package不能被停止.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
r.packageName, false, r.userId);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
}
if (!isolated) {
//取出ServiceRecord对应的进程信息
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
//如果对应进程已经启动
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
//真正启动服务
realStartServiceLocked(r, app, execInFg);
return null;
}
} else {
//对于“孤立”的Service而言,其ServiceRecord中记录着它将运行的进程
//此处,若isolatedProc为null,则表明需要启动新的进程; 不为null,说明正在等待进程的启动
app = r.isolatedProc;
}
//对于进程没有启动的情况
if (app == null && !permissionsReviewRequired) {
//启动服务对应的进程
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated, false)) == null) {
String msg = "";
Slog.w(TAG, msg);
//进程启动失败,将停止服务
bringDownServiceLocked(r);
return msg;
}
}
//mPendingServices保存待启动服务,当进程启动后,会重新启动该服务
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
//服务还未完成启动,就收到结束请求时,会直接停止该服务
if (r.delayedStop) {
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"Applying delayed stop (in bring up): " + r);
stopServiceLocked(r);
}
}
return null;
}
整个方法看似比较复杂,但是逻辑还是比较清晰的,主要是处理三种情况:
1、service已经启动过,则调用sendServiceArgsLocked函数,将新的待处理信息发送给service;
2、service未启动过,但对应的进程已启动,那么调用realStartServiceLocked函数,启动服务即可;
3、service对应的进程并没有启动,那么先启动进程
对于第1种,当第2种场景中的服务启动后,仍将利用sendServiceArgsLocked函数中的流程,将Intent消息发往Service处理;
对于第2种,需要我们跟进;
对于第3种,当进程启动后,经过层层调用,最终会调用AMS的attachApplicationLocked(),将启动等待的service。
8. ActiveServices.realStartServiceLocked()
private final void realStartServiceLocked(//省略参数) throws RemoteException {
//省略部分代码
//对服务的状态进行记录
bumpServiceExecutingLocked(r, execInFg, "create");
//更新进程对应的优先级信息
mAm.updateLruProcessLocked(app, false, null);
mAm.updateOomAdjLocked();
boolean created = false;
try {
//省略部分代码
//更改进程状态为PROCESS_STATE_SERVICE
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
//失败则kill进程
mAm.appDiedLocked(app);
throw e;
} finally {
//服务创建失败
if (!created) {
//更新相关的统计信息
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
// Cleanup.
if (newService) {
app.services.remove(r);
r.app = null;
}
//将根据服务的重启次数,决定是否继续重启,以及重启的时间间隔
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
//Service被绑定过,才会调用onBind函数
requestServiceBindingsLocked(r, execInFg);
//如果客户端Bind Service成功,按需更新服务端进程优先级
updateServiceClientActivitiesLocked(app, null, true);
//调用到sendServiceArgsLocked发送参数
sendServiceArgsLocked(r, execInFg, true);
//如果Service是延迟启动的,那么此时可以将其从mDelayedStartList移除
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;
}
//若Service被要求停止,那么结束服务
if (r.delayedStop) {
//省略部分代码
}
}
realStartServiceLocked函数最主要的工作是:
1、利用bumpServiceExecutingLocked函数,记录ServiceRecord的执行状态,主要用于将进程的ProcessRecord信息,与ServiceRecord关联起来。同时,更新ServiceRecord中的一些信息,并设置命令超时的时间。;
2、利用scheduleCreateService函数,进程间调用,通过ApplicationThread创建出Service对象;
3、利用sendServiceArgsLocked函数,将Intent中的信息递交给Service处理。
9. ApplicationThread.scheduleCreateService()
public final void scheduleCreateService(//省略参数) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
sendMessage(H.CREATE_SERVICE, s);
}
果然也是通过发送消息给H,来让handleCreateService()来完成。
10. ActivityThread.handleCreateService()
private void handleCreateService(CreateServiceData data) {
//当应用处于后台即将进行GC,而此时被调回到活动状态,则跳过本次gc
unscheduleGcIdler();
//得到Service对应的LoadedApk信息
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
//通过反射创建出实例
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
//省略部分代码
}
try {
//创建ContextImpl对象
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
//创建Application对象
Application app = packageInfo.makeApplication(false, mInstrumentation);
//建立ContextImpl和Service的联系
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
//调用Service的onCreate函数
service.onCreate();
//将service对象存储到ActivityThread的一个列表中
mServices.put(data.token, service);
try {
//通知AMS service启动成功,进行取消超时消息等操作
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
//省略部分代码
}
走到这里service算是终于创建出来了,我们再回到8中的第3步看看,onCreate之后执行的方法。
11. ActiveServices.sendServiceArgsLocked()
private final void sendServiceArgsLocked(//省略参数) throws TransactionTooLargeException {
//省略部分代码
r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
//省略部分代码
}
12. ActiveServices.scheduleServiceArgs()
public final void scheduleServiceArgs(//省略参数) {
ServiceArgsData s = new ServiceArgsData();
s.token = token;
s.taskRemoved = taskRemoved;
s.startId = startId;
s.flags = flags;
s.args = args;
sendMessage(H.SERVICE_ARGS, s);
}
13. ActiveServices.handleServiceArgs()
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
int res;
if (!data.taskRemoved) {
//调用Service的onStartCommand函数,处理Intent携带的内容
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
QueuedWork.waitToFinish();
try {
//再次调用AMS的serviceDoneExecuting函数,通知AMS消息处理完毕
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
}
//省略部分代码
}
}
走到这里我们看到,service的onStartCommand方法也被调用了,service就已经start了。而我们知道onStartCommand()是有返回值的,它的返回值就在AMS的serviceDoneExecuting()方法中被处理。
14. ActivityManagerService.serviceDoneExecuting()
void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
boolean inDestroying = mDestroyingServices.contains(r);
if (r != null) {
if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
r.callStart = true;
switch (res) {
case Service.START_STICKY_COMPATIBILITY:
case Service.START_STICKY: {
r.findDeliveredStart(startId, true);
r.stopIfKilled = false;
break;
}
case Service.START_NOT_STICKY: {
r.findDeliveredStart(startId, true);
if (r.getLastStartId() == startId) {
r.stopIfKilled = true;
}
break;
}
case Service.START_REDELIVER_INTENT: {
ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
if (si != null) {
si.deliveryCount = 0;
si.doneExecutingCount++;
r.stopIfKilled = true;
}
break;
}
case Service.START_TASK_REMOVED_COMPLETE: {
r.findDeliveredStart(startId, true);
break;
}
default:
throw new IllegalArgumentException(
"Unknown service start result: " + res);
}
if (res == Service.START_STICKY_COMPATIBILITY) {
r.callStart = false;
}
} else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) {
if (!inDestroying) {
if (r.app != null) {
}
} else if (r.executeNesting != 1) {
r.executeNesting = 1;
}
}
final long origId = Binder.clearCallingIdentity();
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
Binder.restoreCallingIdentity(origId);
} else {
}
}
基本上,startService的流程到此我们就走完了。
三、Start方式总结
还是借用一下http://gityuan.com/2016/03/06/start-service/这位仁兄的。
启动流程:
- Process A进程采用Binder IPC向system_server进程发起startService请求;
- system_server进程接收到请求后,向zygote进程发送创建进程的请求;
- zygote进程fork出新的子进程Remote Service进程;
- Remote Service进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
- system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向remote Service进程发送scheduleCreateService请求;
- Remote Service进程的binder线程在收到请求后,通过handler向主线程发送CREATE_SERVICE消息;
- 主线程在收到Message后,通过发射机制创建目标Service,并回调Service.onCreate()方法。
四、Bind方式时序图
五、Bind方式追踪
1. ContextWrapper.bindService()
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
Bind方式仍然是从ContextWrapper开始的,这里面很多和Start方式相似的就不多提了。
2. ContextImpl.bindService()
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}
3. ContextImpl.bindServiceCommon()
private boolean bindServiceCommon(//省略参数) {
IServiceConnection sd;
if (mPackageInfo != null) {
//得到ServiceConnetion的Binder通信端,内部静态类InnerConnection
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
//检查Intent是否符合要求
validateServiceIntent(service);
try {
//省略部分代码
service.prepareToLeaveProcess(this);
//ServiceConnection对应的Binder通信服务端将注册到AMS
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
}
}
这里需要注意这个getServiceDispatcher()方法,它会将客户端的ServiceConnection对象转化为ServiceDispatcher.InnerConnection对象,原因是InnerConnection对象在跨进程调用中充当Binder,供AMS回调。我们来看看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) {
//初始时,需要创建ServiceConnection对应的ServiceDispatcher
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mServices.put(context, map);
}
//然后将ServiceDispatcher加入到mServices中
map.put(c, sd);
} else {
sd.validate(context, handler);
}
//返回的内部类的对象InnerConnection
return sd.getIServiceConnection();
}
}
4. ActivityManagerService.bindService()
public int bindService(//省略参数) throws TransactionTooLargeException {
enforceNotIsolatedCaller("bindService");
//参数有效性检查
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}
5. ActiveServices.bindServiceLocked()
int bindServiceLocked(//参数检查) throws TransactionTooLargeException {
//得到客户端进程信息
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
//如果是一个Activity绑定Service, 那么该Activity必须是有效的
ActivityRecord activity = null;
if (token != null) {
//判断Activity是否存在于Task中
activity = ActivityRecord.isInStackLocked(token);
if (activity == null) {
return 0;
}
}
//一些特殊标志位的处理
//判断调用方是否来自前台
final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
//检索待启动的服务
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
//权限检查
try {
//从待重启服务中,移除当前的Service
if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: "
+ s);
}
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
//Service初次被绑定时,更改其状态信息
if (!s.hasAutoCreateConnections()) {
//省略部分代码
}
}
//将绑定的发起方和接收方关联起来,同时保存在AMS定义的数据结构中
mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState,
s.appInfo.uid, s.name, s.processName);
//根据Intent信息,检索出对应的IntentBindRecord(记录Intent,能启动哪个Service)
//进一步从IntentBindRecord中检索出AppBindRecord (记录进程,与哪个Service绑定)
//初次绑定时,将分别创建出IntentBindRecord和AppBindRecord
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
//构造注册connection对应的ConnectionRecord
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
//以下都是更新ServiceRecord中的数据结构
IBinder binder = connection.asBinder();
//省略部分代码
//如果Service所在进程之前已经启动过
if (s.app != null) {
//更新Service对应进程的优先级
updateServiceClientActivitiesLocked(s.app, c, true);
}
//ActiveServices也将按照ServiceConnection的Binder保存ConnectionRecord
clist = mServiceConnections.get(binder);
//注意到同一个Binder可以对应多个ConnectionRecord
//这是因为,客户端可以用同一个ServiceConnection绑定多个Service
//每次绑定时,都会生成对应的ConnectionRecord,但这些ConnectionRecord共用相同的Binder
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
//如同Unbounded Service,仍然调用bringUpServiceLocked函数启动Service
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
//省略部分代码
}
这个方法主要完成的工作是:
- 通过retrieveServiceLocked(),根据用户传递进来Intent来检索相对应的服务;
- 通过retrieveAppBindingLocked().创建AppBindRecord对象记录着当前ServiceRecord, intent以及发起方的进程信息;
- 通过bringUpServiceLocked()拉起目标服务。
6. ActiveServices.bringUpServiceLocked()
private String bringUpServiceLocked(//省略参数) throws TransactionTooLargeException {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
//这个流程就和Start方式一样,就不分析了
realStartServiceLocked(r, app, execInFg);
}
7. ActiveServices.realStartServiceLocked()
private final void realStartServiceLocked(//省略参数) throws RemoteException {
//省略部分代码
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
//服务进入onCreate(),这里下去的流程和Start方式一样,就不分析了
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
//和Start方式不同之处
requestServiceBindingsLocked(r, execInFg);
//省略部分代码
}
8. ActiveServices.requestServiceBindingsLocked()
private final boolean requestServiceBindingLocked(//省略参数) throws TransactionTooLargeException {
//IntentBindRecord被处理过后,requested将被置为true
//因此只有第一次处理的请求,和重新绑定时,才会处理
//这就是,客户端第一次绑定Service时,onBind函数才会被回调的原因
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
//服务进入onBind()
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
}
return true;
}
9. ActivityThread.scheduleBindService()
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
sendMessage(H.BIND_SERVICE, s);
}
10. ActivityThread.handleBindService()
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (DEBUG_SERVICE)
Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
//调用Service的onBind函数
IBinder binder = s.onBind(data.intent);
//调用AMS的publishService函数,发布服务
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) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
}
}
}
onBind()方法调用之后,会返回一个Binder对象给客户端使用,此时Service就处于绑定状态了,但是onBind方法是Service的方法,这个时候客户端并不知道已经成功连接了Service了,所以还必须调用客户端的ServiceConnection中的onServiceConnected(),这个过程由ActivityManagerNative.getDefault().publishService()来完成。
11. ActivityManagerService.publishService()
public void publishService(IBinder token, Intent intent, IBinder service) {
synchronized(this) {
if (!(token instanceof ServiceRecord)) {
throw new IllegalArgumentException("Invalid service token");
}
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
12. ActiveServices.publishServiceLocked()
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
try {
c.conn.connected(r.name, service);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.name +
" to connection " + c.conn.asBinder() +
" (in " + c.binding.client.processName + ")", e);
}
}
这里c的类型是ConnectionRecord,c.conn的类型是ServiceDispatcher.InnerConnection,接下来就看看InnerConnection的connected()方法。
13. InnerConnection.connected()
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service);
}
}
14. ServiceDispatcher.connected()
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0));
} else {
doConnected(name, service);
}
}
15 RunConnection
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;
}
16. ServiceDispatcher.doConnected()
public void doConnected(ComponentName name, IBinder service) {
//省略部分代码
//如果存在旧的连接,回调ServiceConnection的onServiceDisconnected方法
if (old != null) {
mConnection.onServiceDisconnected(name);
}
//如果是新的连接,就回调ServiceConnection的onServiceConnected方法
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
六、Bind方式总结
- 首先Client进程通过getServiceDispatcher获取匿名Binder服务端,即LoadedApk.ServiceDispatcher.InnerConnection;
- 通过bindService方法跨进程调用进入system_server进程;
- 通过scheduleCreateService和scheduleBindService方法, 远程调用到target进程;
- target进程:依次执行onCreate()和onBind()方法,将onBind()方法的返回值IBinder(作为target进程的binder服务端)通过publishService传递回system_server进程;
- system_server进程利用IServiceConnection代理对象向Client进程发起connected()调用, 并把target进程的onBind返回Binder对象的代理端传递到Client进程;
- Client进程回调到onServiceConnection()方法, 该方法的第二个参数便是target进程的binder代理端. 到此便成功地拿到了target进程的代理, 可以畅通无阻地进行交互。