Android之Service自启动流程
16lz
2021-01-26
当Service被异常销毁后,默认都会自动重启,但Service的自动重启是如何实现的尼?下面就来梳理一下Service的自动重启流程。
无论Service是启动还是绑定成功,都会调用ActiveServices
的serviceDoneExecutingLocked
方法,来看一下这个方法的实现。
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) { // This is a call from a service start... take care of // book-keeping. //默认调用Service的startCommand这个方法 r.callStart = true; switch (res) { case Service.START_STICKY_COMPATIBILITY: case Service.START_STICKY: { // We are done with the associated start arguments. r.findDeliveredStart(startId, true); // Don't stop if killed. //被异常kill掉,允许重启该Service r.stopIfKilled = false; break; } case Service.START_NOT_STICKY: { // We are done with the associated start arguments. r.findDeliveredStart(startId, true); if (r.getLastStartId() == startId) { // There is no more work, and this service // doesn't want to hang around if killed. //被异常kill掉,不允许重启该Service r.stopIfKilled = true; } break; } case Service.START_REDELIVER_INTENT: { // We'll keep this item until they explicitly // call stop for it, but keep track of the fact // that it was delivered. ServiceRecord.StartItem si = r.findDeliveredStart(startId, false); if (si != null) { si.deliveryCount = 0; si.doneExecutingCount++; // Don't stop if killed. //被异常kill掉,不允许重启。但后面会依靠deliveredStarts触发重启 r.C= true; } break; } case Service.START_TASK_REMOVED_COMPLETE: { // Special processing for onTaskRemoved(). Don't // impact normal onStartCommand() processing. r.findDeliveredStart(startId, true); break; } default: throw new IllegalArgumentException( "Unknown service start result: " + res); } if (res == Service.START_STICKY_COMPATIBILITY) { //当startCommand返回START_STICKY_COMPATIBILITY时则不允许调用startCommand方法 r.callStart = false; } } else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) { ... } ... } else { ... } }
当Service启动或绑定成功后就会给当前Service给stopIfKilled
这个标志位赋值,该标志位决定当Service被异常kill掉后是否需要重启。
Service被意外kill后会调用ActiveServices
的killServicesLocked
方法,来看看这个方法的实现。
final void killServicesLocked(ProcessRecord app, boolean allowRestart) { ... ServiceMap smap = getServiceMapLocked(app.userId); // Now do remaining service cleanup. for (int i=app.services.size()-1; i>=0; i--) { //拿到Service的信息 ServiceRecord sr = app.services.valueAt(i); ... // Any services running in the application may need to be placed // back in the pending list. //如果连续两次重启失败就不再重启Service if (allowRestart && sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags &ApplicationInfo.FLAG_PERSISTENT) == 0) { ... //不允许重启 bringDownServiceLocked(sr); } else if (!allowRestart//不允许重启 || !mAm.mUserController.isUserRunningLocked(sr.userId, 0)) { //不允许重启 bringDownServiceLocked(sr); } else { //尝试重启 boolean canceled = scheduleServiceRestartLocked(sr, true); //在多次尝试发送失败的命令的极端情况下,也会在这里停止它。 if (sr.startRequested && (sr.stopIfKilled || canceled)) { if (sr.pendingStarts.size() == 0) { sr.startRequested = false; if (sr.tracker != null) { sr.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis()); } if (!sr.hasAutoCreateConnections()) { // Whoops, no reason to restart! //哎呀,没理由重启! bringDownServiceLocked(sr); } } } } } //做一些清理操作 ... }
从上面代码可以看出,尝试重启的具体实现是在scheduleServiceRestartLocked
这个方法里,来看看它的实现。
private final boolean scheduleServiceRestartLocked(ServiceRecord r, boolean allowCancel) { boolean canceled = false; ... final long now = SystemClock.uptimeMillis(); if ((r.serviceInfo.applicationInfo.flags &ApplicationInfo.FLAG_PERSISTENT) == 0) { long minDuration = mAm.mConstants.SERVICE_RESTART_DURATION; long resetTime = mAm.mConstants.SERVICE_RESET_RUN_DURATION; // Any delivered but not yet finished starts should be put back // on the pending list. final int N = r.deliveredStarts.size(); if (N > 0) { for (int i=N-1; i>=0; i--) { ServiceRecord.StartItem si = r.deliveredStarts.get(i); si.removeUriPermissionsLocked(); if (si.intent == null) { // We'll generate this again if needed. } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) { //重启的时候,deliveredStarts被pendingStarts替换掉了,这样就能拿到Intent的值 // 也就说,这个时候START_REDELIVER_INTENT由死转生 r.pendingStarts.add(0, si); long dur = SystemClock.uptimeMillis() - si.deliveredTime; //将重启间隔时间拉大,被kill掉次数越多,重启所需要时间越长 dur *= 2; if (minDuration < dur) minDuration = dur; if (resetTime < dur) resetTime = dur; } else { Slog.w(TAG, "Canceling start item " + si.intent + " in service " + r.name); canceled = true; } } r.deliveredStarts.clear(); } //重启次数加1 r.totalRestartCount++; if (r.restartDelay == 0) { r.restartCount++; r.restartDelay = minDuration; } else { // If it has been a "reasonably long time" since the service // was started, then reset our restart duration back to // the beginning, so we don't infinitely increase the duration // on a service that just occasionally gets killed (which is // a normal case, due to process being killed to reclaim memory). if (now > (r.restartTime+resetTime)) { r.restartCount = 1; r.restartDelay = minDuration; } else { r.restartDelay *= mAm.mConstants.SERVICE_RESTART_DURATION_FACTOR; if (r.restartDelay < minDuration) { r.restartDelay = minDuration; } } } r.nextRestartTime = now + r.restartDelay; //两个Service启动至少间隔10秒,这里的意义其实不是很大,主要是为了Service启动失败的情况,如果启动成功,其他要启动的Service会被一并直接重新唤起 boolean repeat; do { repeat = false; final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN; for (int i=mRestartingServices.size()-1; i>=0; i--) { ServiceRecord r2 = mRestartingServices.get(i); if (r2 != r && r.nextRestartTime >= (r2.nextRestartTime-restartTimeBetween) && r.nextRestartTime < (r2.nextRestartTime+restartTimeBetween)) { r.nextRestartTime = r2.nextRestartTime + restartTimeBetween; r.restartDelay = r.nextRestartTime - now; repeat = true; break; } } } while (repeat); } else { // Persistent processes are immediately restarted, so there is no // reason to hold of on restarting their services. r.totalRestartCount++; r.restartCount = 0; r.restartDelay = 0; r.nextRestartTime = now; } if (!mRestartingServices.contains(r)) { r.createdFromFg = false; mRestartingServices.add(r); r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now); } cancelForegroundNotificationLocked(r); mAm.mHandler.removeCallbacks(r.restarter); //执行Service重启操作,这里的restarter就是一个ServiceRestarter对象,在ServiceRecord创建时添加进去的 mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime); r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay; ... return canceled; } private class ServiceRestarter implements Runnable { private ServiceRecord mService; void setService(ServiceRecord service) { mService = service; } public void run() { synchronized(mAm) { //开始重启 performServiceRestartLocked(mService); } } } final void performServiceRestartLocked(ServiceRecord r) { ... try { bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false); } catch (TransactionTooLargeException e) { ... } }
最后就在ServiceRestarter
执行重新创建Service操作,在run
方法里调用了performServiceRestartLocked
来进行重启,而performServiceRestartLocked
里直接调用了bringUpServiceLocked
这个方法,这个就是重新创建Service的方法,关于这个方法的详细实现可以去阅读Android源码之Service启动流程这篇文章。
Android的服务(Service)(二)Service的自动重启问题
Android Service重启恢复(Service进程重启)原理解析
更多相关文章
- Android入门(7):活动的启动模式
- Android(安卓)RecycleView(二)——添加分割线
- Android中WebView与Javascript的交互
- Android的JS调用Java代码或使用了Javascript相关技术,如何混淆
- Android疑问1——Handler的removeCallbacks方法无效?(已经明白了)
- Android(安卓)Fatal signal 6 (SIGABRT) at 0x0000271d (code=-6
- 直播平台软件开发Android(安卓)Activity横竖屏切换生命周期详解
- Android(安卓)ADB命令大全(通过ADB命令查看wifi密码、MAC地址、
- 运行时动态注销在AndroidManifest.xml声明的BroadcastReceiver,En