《Android中级工程师》Service启动流程
来源:互联网 发布:android c语言开发 编辑:程序博客网 时间:2024/05/05 22:33
前言
前几天深入研究了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进程的代理, 可以畅通无阻地进行交互。
- 《Android中级工程师》Service启动流程
- 《Android中级工程师》Activity启动流程
- 《Android中级工程师》BroadcastReceive工作流程
- Android启动Service流程
- Android service启动流程分析.
- 【Android中级工程师】性能优化
- android四大组件启动流程 - Service启动流程
- Android中Service的启动流程
- 【Android中级工程师】跨进程通信IPC
- Service启动流程
- Service启动流程-startService
- Android启动流程分析(九) 解析init.rc的service
- Android Service的启动流程源码分析(8.0)
- Service 启动和绑定流程
- 系统Service的启动流程
- Service 启动流程源码解析
- Service的启动流程分析
- Android中级之手机启动过程
- [乐意黎原创]云南省红河州泸西县各乡镇及村委会区划代码和城乡划分代码
- 在jsp页面定义CSS样式怎么写
- 2017.11.20笔记
- 深入理解linux内核之文件系统分析一
- 凭智慧嫁入娱乐豪门的金巧巧,却也曾熟人骗700万
- 《Android中级工程师》Service启动流程
- MySQL5.7.17主从复制搭建(一主一从)教程详解
- Python练习题(1)
- react 1
- OpenCV检测篇(二) ——笑脸检测
- C++ cout输出格式化(1)
- ESP8266擦除flash
- hadoop 2.x yarn 的工作机制
- Gensim Word2vec 使用教程