Android之Service自启动流程

版权声明:未经本人允许,严禁转载 https://blog.csdn.net/lmh_19941113/article/details/85676881

 当Service被异常销毁后,默认都会自动重启,但Service的自动重启是如何实现的尼?下面就来梳理一下Service的自动重启流程。
 无论Service是启动还是绑定成功,都会调用ActiveServicesserviceDoneExecutingLocked方法,来看一下这个方法的实现。

    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后会调用ActiveServiceskillServicesLocked方法,来看看这个方法的实现。

    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进程重启)原理解析

猜你喜欢

转载自blog.csdn.net/lmh_19941113/article/details/85676881