Service对于Android开发来说再熟悉不过了,不过大部分人对Service的了解也仅限于api,这篇文章,我们通过分析AMS的源码,从一个更高的高度来了解一下Service的整个生命周期。

Service的生命周期接口:

1. startService

2. bindService

3. stopService

4. unbindService

这几个接口在apk进程里调用,通过ActivityManagerNative这个Binder最后调用到ActivityManagerService里,而AMS管理Service的类是ActiveService,这个类接管了所有Service生命周期的函数,包括startServiceLocked、stopServiceLocked、bindServiceLocked、unbindServiceLocked等。

startServiceLocked:

该函数实现Service的启动,首先调用retrieveServiceLocked根据Intent查询ServiceLookupResult(主要字段ServiceRecord),查询是先在ServiceMap里找,没有就重新由PackageManager的resolveService来获得ResolveInfo,创建新的ServiceRecord。针对Service的case,startService分为下面三种case,1,caller app是前台应用或者Service所在的app的进程优先级较高(高于PROCESS_STATE_SERVICE), 那么无限制的start。2,其他情况的Service作为background service,会加入到mStartingBackground list里,如果starting  list的size没有达到上限,那么直接启动。3,此时starting list已到上限,那么此Service的start会推迟,Service会加到mDelayedStartList里。

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,            int callingPid, int callingUid, String callingPackage, int userId)            throws TransactionTooLargeException {        ......        ......        // 检查caller app是否是前台进程        final boolean callerFg;        if (caller != null) {            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);            if (callerApp == null) {                throw new SecurityException(                        "Unable to find app for caller " + caller                        + " (pid=" + Binder.getCallingPid()                        + ") when starting service " + service);            }            callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;        } else {            callerFg = true;        }        // 查找ServiceRecord        ServiceLookupResult res =            retrieveServiceLocked(service, resolvedType, callingPackage,                    callingPid, callingUid, userId, true, callerFg);               ......        ......         ServiceRecord r = res.record;        ......        ......        r.lastActivity = SystemClock.uptimeMillis();        r.startRequested = true;        r.delayedStop = false;        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),                service, neededGrants));        final ServiceMap smap = getServiceMap(r.userId);        boolean addToStarting = false;        if (!callerFg && r.app == null && mAm.mStartedUsers.get(r.userId) != null) {            ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);            if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {                // 这个分支表示Service所在的进程不存在,或者进程优先级小于PROCESS_STATE_RECEIVER,说明这个Service是background service                ......                // 如果Service在delayed start list,则直接返回                if (r.delayed) {                     if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Continuing to delay: " + r);                    return r.name;                }                // 如果后starting background list超上限,则加到mDelayedStartList,暂时不startService,直接返回                if (smap.mStartingBackground.size() >= mMaxStartingBackground) {                    // Something else is starting, delay!                    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) {                // 这个分支表示Service所在的进程优先级小于PROCESS_STATE_SERVICE,但又比PROCESS_STATE_RECEIVER大,加到starting list里,并startService                addToStarting = true;                if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,                        "Not delaying, but counting as bg: " + r);            } else if (DEBUG_DELAYED_STARTS) {                StringBuilder sb = new StringBuilder(128);                sb.append("Not potential delay (state=").append(proc.curProcState)                        .append(' ').append(proc.adjType);                String reason = proc.makeAdjReason();                if (reason != null) {                    sb.append(' ');                    sb.append(reason);                }                sb.append("): ");                sb.append(r.toString());                Slog.v(TAG_SERVICE, sb.toString());            }        }         ......        ......        // 分支走到这里等于startService会成功,addToStarting表示是否加到StartingBackground List        return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);    }

Service的start是由函数startServiceInnerLocked完成,而startServiceInnerLocked则是调用bringUpServiceLocked完成Service的start,每次startService都会往ServiceRecord的pendingStarts里填加一项StartItem,即使是被放入Delayed List的Service启动。bringUpServiceLocked做的事就是拉起Service。

一,如果进程r.app和r.app.thread已经初始化(代表着Service之前已经Create过),那么bringUpServiceLocked只需要执行onStartCommand,这是通过调用sendServiceArgsLocked来实现,sendServiceArgsLocked就遍历之前pendingStarts的所有StartItem(每个startService都会对应一个StartItem),逐个调用app.thread.scheduleServiceArgs。app.thread是Service所在进程的IApplicationThread Binder对象,用于AMS的SystemServer进程到Client App端的跨进程调用,IApplicationThread的实现是在ActivityThread的内部类ApplicationThread,AMS ->  ActivityThread的调用通过IApplicationThread,ActivityThread -> AMS的调用就是ActivityManagerNative,这样就打通了一条从AMS到ActivityThread的跨进程调用之路。scheduleServiceArgs在ActivityThread里的对应就是ActivityThread.handleServiceArgs,这就执行到了我们所熟悉的onStartCommand。至此可以解释两个我们对于Service的认知:1,每次startService,都会对应一次onStartCommand,就算Service已经onCreate成功。2,Service的回调函数都是在主线程,这个和ApplicationThread这个Binder Client的执行线程一致。sendServiceArgsLocked之后,pendingStarts里的StartItem就被加入到了deliveredStarts里,等待后续stopService或者Service restart的时候用。

二,如果Service所在的进程已经创建(ProcessRecord不空),那么会调用realStartServiceLocked来启动Service,这时的Service是还没有调用过onCreate。realStartServiceLocked会调用app.thread.scheduleCreateService来完成Service的启动,scheduleCreateService同scheduleServiceArgs一样,会调用到ActivityThread里,最终会执行Service的onCreate。之后同样执行sendServiceArgsLocked回调到onStartCommand。

三,如果Service所在的进程还未创建,那么bringUpServiceLocked做的事就是调用AMS的startProcessLocked创建进程,并将Service放进mPendingServices,等待进程创建成功,调用attachApplicationLocked的时候,会遍历所有的mPendingServices,继续调用realStartServiceLocked来完成Service的启动。

最后再看看bringUpServiceLocked的代码来加深一下印象

    private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,            boolean whileRestarting) throws TransactionTooLargeException {        // Service已经启动过了,直接调用sendServiceArgsLocked来执行onStartCommand        if (r.app != null && r.app.thread != null) {            sendServiceArgsLocked(r, execInFg, false);            return null;        }        // Service正在restart,啥都不做,等restart定时器触发以后再start        if (!whileRestarting && r.restartDelay > 0) {            // If waiting for a restart, then do nothing.            return null;        }        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent);        // 从正在重启的Service列表里删除        if (mRestartingServices.remove(r)) {            r.resetRestartCounter();            clearRestartingIfNeededLocked(r);        }        // 已经start了,从mDelayedStartList里删除        if (r.delayed) {            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (bring up): " + r);            getServiceMap(r.userId).mDelayedStartList.remove(r);            r.delayed = false;        }        ......        ......        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;        final String procName = r.processName;        ProcessRecord app;        if (!isolated) {            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid                        + " app=" + app);           // 如果进程已经创建,那么可以执行startService了,先执行Service的onCreate,再执行onStartCommand            if (app != null && app.thread != null) {                try {                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);                    realStartServiceLocked(r, app, execInFg);                    return null;                } catch (TransactionTooLargeException e) {                    throw e;                } catch (RemoteException e) {                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);                }                // If a dead object exception was thrown -- fall through to                // restart the application.            }        } else {            // If this service runs in an isolated process, then each time            // we call startProcessLocked() we will get a new isolated            // process, starting another process if we are currently waiting            // for a previous process to come up.  To deal with this, we store            // in the service any current isolated process it is running in or            // waiting to have come up.            app = r.isolatedProc;        }        // 如果进程还没创建,调用startProcessLocked来创建进程,并加入到mPendingServices,等待attachApplicationLocked后再startService        if (app == null) {            if (app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,                    "service", r.name, false, isolated, false)) == null) {                String msg = "Unable to launch app "                        + r.appInfo.packageName + "/"                        + r.appInfo.uid + " for service "                        + r.intent.getIntent() + ": process is bad";                Slog.w(TAG, msg);                bringDownServiceLocked(r);                return msg;            }            if (isolated) {                r.isolatedProc = app;            }        }        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;    }
bindServiceLocked :

bindServiceLocked比startService要复杂很多,主要是其多了Service和App之间的绑定关系:

1,AppBindRecord

retrieveServiceLocked查找到ServiceRecord之后,生成Service和Client(callerApp)之间的绑定关系AppBindRecord,AppBindRecord的字段包括service,client,intent,确定了他们之间的绑定关系。

final class AppBindRecord {    final ServiceRecord service;    // The running service.    final IntentBindRecord intent;  // The intent we are bound to.    final ProcessRecord client;     // Who has started/bound the service.}
2,ConnectionRecord

Service和Client之间一个绑定关系就会对应一个ConnectionRecord,ConnectionRecord字段里除了绑定关系等对象之外,还有一个比较重要的对象就是IServiceConnection,这是一个binder对象,用做Client端和Server端的桥接,IServiceConnection的定义在LoadedApk里,处理ServiceConnection的connected状态,并由ServiceDispatcher统一做Service连接分发,如果connected函数的第二个参数IBinder是空,那么就是调用回调函数onServiceDisconnected,不空则表示连接建立成功,调用onServiceConnected。在ServiceConnection创建成功时,ServiceDispatcher会注册这个Service的死亡通知,如果Service crash,也会马上调用onServiceDisconnected。

        private static class InnerConnection extends IServiceConnect.Stub {            final WeakReference mDispatcher;            InnerConnection(LoadedApk.ServiceDispatcher sd) {                this.mDispatcher = new WeakReference(sd);            }            public void connected(ComponentName name, IBinder service) throws RemoteException {                LoadedApk.ServiceDispatcher sd = (LoadedApk.ServiceDispatcher)this.mDispatcher.get();                if(sd != null) {                    sd.connected(name, service);                }            }        }             static final class ServiceDispatcher {         public void connected(ComponentName name, IBinder service) {            if(this.mActivityThread != null) {                this.mActivityThread.post(new LoadedApk.ServiceDispatcher.RunConnection(name, service, 0));            } else {                this.doConnected(name, service);            }        }        public void death(ComponentName name, IBinder service) {            synchronized(this) {                this.mDied = true;                LoadedApk.ServiceDispatcher.ConnectionInfo old = (LoadedApk.ServiceDispatcher.ConnectionInfo)this.mActiveConnections.remove(name);                if(old == null || old.binder != service) {                    return;                }                old.binder.unlinkToDeath(old.deathMonitor, 0);            }            if(this.mActivityThread != null) {                this.mActivityThread.post(new LoadedApk.ServiceDispatcher.RunConnection(name, service, 1));            } else {                this.doDeath(name, service);            }        }        public void doConnected(ComponentName name, IBinder service) {            LoadedApk.ServiceDispatcher.ConnectionInfo old;            synchronized(this) {                if(this.mForgotten) {                    return;                }                old = (LoadedApk.ServiceDispatcher.ConnectionInfo)this.mActiveConnections.get(name);                if(old != null && old.binder == service) {                    return;                }                if(service != null) {                    this.mDied = false;                    LoadedApk.ServiceDispatcher.ConnectionInfo info = new LoadedApk.ServiceDispatcher.ConnectionInfo();                    info.binder = service;                    info.deathMonitor = new LoadedApk.ServiceDispatcher.DeathMonitor(name, service);                    try {                        service.linkToDeath(info.deathMonitor, 0);                        this.mActiveConnections.put(name, info);                    } catch (RemoteException var8) {                        this.mActiveConnections.remove(name);                        return;                    }                } else {                    this.mActiveConnections.remove(name);                }                if(old != null) {                    old.binder.unlinkToDeath(old.deathMonitor, 0);                }            }            if(old != null) {                this.mConnection.onServiceDisconnected(name);            }            if(service != null) {                this.mConnection.onServiceConnected(name, service);            }        }        public void doDeath(ComponentName name, IBinder service) {            this.mConnection.onServiceDisconnected(name);        }        private final class DeathMonitor implements DeathRecipient {            final ComponentName mName;            final IBinder mService;            DeathMonitor(ComponentName name, IBinder service) {                this.mName = name;                this.mService = service;            }            public void binderDied() {                ServiceDispatcher.this.death(this.mName, this.mService);            }        }

3,connections

AppBindRecord的connections字段则保存了这个client的所有ServiceConnection连接ConnectionRecord,ConnectionRecord和IServiceConnection对象是对应的。ServiceRecord也有个connections列表,但ServiceRecord的connections列表存储的是这个Service相关的所有ConnectionRecord,Service和Client之间是多对多的关系,所以其各自维护了一个connections。

ConnectionRecord和AppBindRecord初始化完之后,就进入Service的主题,如果bindService的flag加上了BIND_AUTO_CREATE,那么将马上调用bringUpServiceLocked来启动Service,否则不会主动startService,这种情况如果之前Service并没有启动过,那么bind操作就会失败。之后检查Service是否绑定过,没有绑定过或者需要重新绑定的时候,由requestServiceBindingLocked来实际bindService,最后通过app.thread.scheduleBindService完成Service的绑定。并通过c.conn.connected调用,通知Client的IServiceConnection.onServiceConnected。从而完成Service和Client之间的Bind。


stopServiceLocked:

    private void stopServiceLocked(ServiceRecord service) {        // 如果Service还未start,那么置delayedStop为true,等startService结束以后调用stopServiceLocked        if (service.delayed) {            // If service isn't actually running, but is is being held in the            // delayed list, then we need to keep it started but note that it            // should be stopped once no longer delayed.            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Delaying stop of pending: " + service);            service.delayedStop = true;            return;        }        synchronized (service.stats.getBatteryStats()) {            service.stats.stopRunningLocked();        }        service.startRequested = false;        if (service.tracker != null) {            service.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),                    SystemClock.uptimeMillis());        }        service.callStart = false;        bringDownServiceIfNeededLocked(service, false, false);    }
stopServiceLocked是调用bringDownServiceLocked来停止Service。首先对这个Service的所有bind连接,都通知回调onServiceDisconnected,之后通过调用r.app.thread.scheduleStopService,通知Service进程stopService,Service的onDestroy会被调用。

    private final void bringDownServiceLocked(ServiceRecord r) {       // 对这个Service的每个绑定连接都通知client端回调onServiceDisconnected        for (int conni=r.connections.size()-1; conni>=0; conni--) {            ArrayList c = r.connections.valueAt(conni);            for (int i=0; i=0; i--) {                IntentBindRecord ibr = r.bindings.valueAt(i);                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down binding " + ibr                        + ": hasBound=" + ibr.hasBound);                if (ibr.hasBound) {                    try {                        bumpServiceExecutingLocked(r, false, "bring down unbind");                        mAm.updateOomAdjLocked(r.app);                        ibr.hasBound = false;                        r.app.thread.scheduleUnbindService(r,                                ibr.intent.getIntent());                    } catch (Exception e) {                        Slog.w(TAG, "Exception when unbinding service "                                + r.shortName, e);                        serviceProcessGoneLocked(r);                    }                }            }        }        // 已经unbind了,mPendingServices的列表可以清空了        for (int i=mPendingServices.size()-1; i>=0; i--) {            if (mPendingServices.get(i) == r) {                mPendingServices.remove(i);                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending: " + r);            }        }        r.cancelNotification();        r.isForeground = false;        r.foregroundId = 0;        r.foregroundNoti = null;        // Clear start entries.        r.clearDeliveredStartsLocked();        r.pendingStarts.clear();        if (r.app != null) {           // 调用r.app.thread.scheduleStopService,通知Service进程stopService,Service的onDestroy会被调用            r.app.services.remove(r);            if (r.app.thread != null) {                updateServiceForegroundLocked(r.app, false);                try {                    bumpServiceExecutingLocked(r, false, "destroy");                    mDestroyingServices.add(r);                    r.destroying = true;                    mAm.updateOomAdjLocked(r.app);                    r.app.thread.scheduleStopService(r);                } catch (Exception e) {                    Slog.w(TAG, "Exception when destroying service "                            + r.shortName, e);                    serviceProcessGoneLocked(r);                }            } else {                if (DEBUG_SERVICE) Slog.v(                    TAG_SERVICE, "Removed service that has no process: " + r);            }        } else {            if (DEBUG_SERVICE) Slog.v(                TAG_SERVICE, "Removed service that is not running: " + r);        }        ......        ......    }

unbindService:

unbindService就比较简单了,把参数IServiceConnection对应的ConnectionRecord列表,逐个调用removeConnectionLocked移除连接,而removeConnectionLocked其实就是之前bindService时初始化AppBindRecord相关对象的逆过程,把和这个需要unbind的IServiceConnection连接从各个数据结构里删掉。移除完之后,如果发现这个Service已经没有任何Client绑定在其上面,就会调用s.app.thread.scheduleUnbindService,通知Service的进程执行onUnbind。

    boolean unbindServiceLocked(IServiceConnection connection) {        IBinder binder = connection.asBinder();        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "unbindService: conn=" + binder);        ArrayList clist = mServiceConnections.get(binder);        if (clist == null) {            Slog.w(TAG, "Unbind failed: could not find connection for "                  + connection.asBinder());            return false;        }        final long origId = Binder.clearCallingIdentity();        try {            while (clist.size() > 0) {                ConnectionRecord r = clist.get(0);               // 移除ConnectionRecord                removeConnectionLocked(r, null, null);                if (clist.size() > 0 && clist.get(0) == r) {                    // In case it didn't get removed above, do it now.                    Slog.wtf(TAG, "Connection " + r + " not removed for binder " + binder);                    clist.remove(0);                }                if (r.binding.service.app != null) {                    // This could have made the service less important.                    if ((r.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {                        r.binding.service.app.treatLikeActivity = true;                        mAm.updateLruProcessLocked(r.binding.service.app,                                r.binding.service.app.hasClientActivities                                || r.binding.service.app.treatLikeActivity, null);                    }                   // 重新更新各进程的oom_adj                    mAm.updateOomAdjLocked(r.binding.service.app);                }            }        } finally {            Binder.restoreCallingIdentity(origId);        }        return true;    }

至此,我们介绍了AMS是怎么管理Service的整个生命周期,之前文章 Android的LowMemoryKiller杀进程策略 介绍LMK杀进程的时候,有个foreground的oom_adj级别对应的case就是executingServices的size大于0的情况,在Service的startService、stopService、bindService、unBindService的时候都会将Service加入到executingServices里,通过ServiceRecord.app.thread回调到Service的Client进程之后,都会调用ActivityManagerNative.getDefault().serviceDoneExecuting,执行到AMS进程里,再将这个Service从executingServices里删除。加到executingServices里之后,会有个超时时间(callerApp是前台的话是20秒,后台是200秒),超时则触发ANR。executingServices不空就表示,Service的生命周期还未走完,Service的Client进程还未收到回调,此时把其oom_adj下调到前台App的级别,以保证Service生命周期的完整性也是很合理的策略。


Service还有个特点是杀掉后是可以重启的,最后我们简单介绍一下这个重启策略。Service的死分为两种,一种是自己crash,一种是被LMK kill。Android进程刚创建的时候,ActivityManagerService在attachApplication方法里会注册该进程的死亡通知,所以不论那种死法,AMS都会通过死亡通知获得回调,从而根据一定的策略来重启进程。

private final boolean attachApplicationLocked(IApplicationThread thread,            int pid) {        ......        ......        try {            AppDeathRecipient adr = new AppDeathRecipient(                    app, pid, thread);            thread.asBinder().linkToDeath(adr, 0);            app.deathRecipient = adr;        } catch (RemoteException e) {            app.resetPackageList(mProcessStats);            startProcessLocked(app, "link fail", processName);            return false;        }        ......        ......}

AMS的死亡通知类定义如下:

    private final class AppDeathRecipient implements IBinder.DeathRecipient {        final ProcessRecord mApp;        final int mPid;        final IApplicationThread mAppThread;        AppDeathRecipient(ProcessRecord app, int pid,                IApplicationThread thread) {            if (DEBUG_ALL) Slog.v(                TAG, "New death recipient " + this                + " for thread " + thread.asBinder());            mApp = app;            mPid = pid;            mAppThread = thread;        }        @Override        public void binderDied() {            if (DEBUG_ALL) Slog.v(                TAG, "Death received in " + this                + " for thread " + mAppThread.asBinder());            synchronized(ActivityManagerService.this) {                appDiedLocked(mApp, mPid, mAppThread, true);            }        }    }
一旦进程死掉,就会调用appDiedLocked来处理,如果是Home App挂了的话,进程就会马上重启。

    final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,            boolean fromBinderDied) {        // First check if this ProcessRecord is actually active for the pid.        synchronized (mPidsSelfLocked) {            ProcessRecord curProc = mPidsSelfLocked.get(pid);            if (curProc != app) {                Slog.w(TAG, "Spurious death for " + app + ", curProc for " + pid + ": " + curProc);                return;            }        }        BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();        synchronized (stats) {            stats.noteProcessDiedLocked(app.info.uid, pid);        }        if (!app.killed) {            // 如果不是死亡通知调用的,那么就执行Process.killProcessQuiet杀死进程            if (!fromBinderDied) {                Process.killProcessQuiet(pid);            }            killProcessGroup(app.info.uid, pid);            app.killed = true;        }        // Clean up already done if the process has been re-started.        if (app.pid == pid && app.thread != null &&                app.thread.asBinder() == thread.asBinder()) {            boolean doLowMem = app.instrumentationClass == null;            boolean doOomAdj = doLowMem;            boolean homeRestart = false;            if (!app.killedByAm) {                // 桌面App死了,需马上重启                if (mHomeProcessName != null && app.processName.equals(mHomeProcessName)) {                    mHomeKilled = true;                    homeRestart = true;                }                Slog.i(TAG, "Process " + app.processName + " (pid " + pid                        + ") has died");                mAllowLowerMemLevel = true;            } else {                // Note that we always want to do oom adj to update our state with the                // new number of procs.                mAllowLowerMemLevel = false;                doLowMem = false;            }            EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName);            if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,                "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());            handleAppDiedLocked(app, false, true);            if (doOomAdj) {                updateOomAdjLocked();            }            if (doLowMem) {                doLowMemReportIfNeededLocked(app);            }            if (mHomeKilled && homeRestart) {                // 立即重启Home App                Intent intent = getHomeIntent();                ActivityInfo aInfo = mStackSupervisor.resolveActivity(intent, null, 0, null, 0);                startProcessLocked(aInfo.processName, aInfo.applicationInfo, true, 0,                        "activity", null, false, false, true);                homeRestart = false;            }        } else if (app.pid != pid) {            // A new process has already been started.            Slog.i(TAG, "Process " + app.processName + " (pid " + pid                    + ") has died and restarted (pid " + app.pid + ").");            EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName);        } else if (DEBUG_PROCESSES) {            Slog.d(TAG_PROCESSES, "Received spurious death notification for thread "                    + thread.asBinder());        }    }
handleAppDiedLocked会调用mServices.killServicesLocked,在killServicesLocked里会根据具体情况来实施重启策略,

    final void killServicesLocked(ProcessRecord app, boolean allowRestart) {        // 清除进程的所有Service connection        for (int i = app.connections.size() - 1; i >= 0; i--) {            ConnectionRecord r = app.connections.valueAt(i);            removeConnectionLocked(r, app, null);        }        ......        ......        // Now do remaining service cleanup.        for (int i=app.services.size()-1; i>=0; i--) {            ServiceRecord sr = app.services.valueAt(i);            // 除了persistent进程,其他的Service都清除,persitent是个高优先级的进程,不管oom_adj很小,LMK不会杀,           //  而且PackageManagerService在installApk的时候也不会杀掉,这样就会导致persistent的进程升级不了,必须要重启系统            if (!app.persistent) {                app.services.removeAt(i);            }            // Sanity check: if the service listed for the app is not one            // we actually are maintaining, just let it drop.            final ServiceRecord curRec = smap.mServicesByName.get(sr.name);            if (curRec != sr) {                if (curRec != null) {                    Slog.wtf(TAG, "Service " + sr + " in process " + app                            + " not same as in map: " + curRec);                }                continue;            }            // Service crash超过两次之后,Service被stop,不会再restart            if (allowRestart && sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags                    &ApplicationInfo.FLAG_PERSISTENT) == 0) {                Slog.w(TAG, "Service crashed " + sr.crashCount                        + " times, stopping: " + sr);                EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,                        sr.userId, sr.crashCount, sr.shortName, app.pid);                bringDownServiceLocked(sr);            } else if (!allowRestart || !mAm.isUserRunningLocked(sr.userId, false)) {                bringDownServiceLocked(sr);            } else {                // 准备重启Service,重启的时间在scheduleServiceRestartLocked里设置                boolean canceled = scheduleServiceRestartLocked(sr, true);                // 如果stopIfKilled设为true,后续没有再调用startService的情况下,也不会再重启Service,调用bringDownServiceLocked停止Service                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);                        }                    }                }            }        }        ......        ......        // Make sure we have no more records on the stopping list.        int i = mDestroyingServices.size();        while (i > 0) {            i--;            ServiceRecord sr = mDestroyingServices.get(i);            if (sr.app == app) {                sr.forceClearTracker();                mDestroyingServices.remove(i);                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "killServices remove destroying " + sr);            }        }        app.executingServices.clear();    }

如果crash次数超过2次,那么进程死掉的时候,Service就不会进入restart状态。scheduleServiceRestartLocked是处理service restart的函数,确定每个要重启的service准备restart的时间点。可以看到persitent的进程的优先级非常高,除了没有crash超过2次的限制外,restartDelay的值也会被设为0,也就是说马上restart,所以一旦persistent进入循环重启状态的时候,就出现无限重启,根本听不下来。


Service的生命周期管理就介绍到这儿,代码主要分布在ActivityManagerService、ActiveService、ActivityThread、LoadedApk等类中,看完之后,对Service的原理的了解就更加深刻了。


作者简介:

田力,网易彩票Android端创始人,小米视频创始人,现任roobo技术经理、视频云技术总监

欢迎关注微信公众号 磨剑石,定期推送技术心得以及源码分析等文章,谢谢



更多相关文章

  1. android中的dialog
  2. Android获得所有存储设备位置的最佳方法
  3. 基于Android(安卓)AIDL进程间通信接口使用介绍
  4. Android(安卓)Serivce 高级篇AIDL讲解
  5. Android之旅[1] - Architecture
  6. Webview 和js之间安全交互
  7. Android之Activity相关
  8. Android(安卓)Jni调用so库,加载库失败分析
  9. 跨进程调用Service(AIDL Service)

随机推荐

  1. Android的view重绘
  2. cocos2dx android mk 2.0.2编译文件目录
  3. Android(安卓)开发技术选型(博客,新闻,阅读
  4. Android总结之链式调用(方法链)
  5. Android模拟器学framework和driver之batt
  6. Android(安卓)AVD创建及设置中各参数详解
  7. PC客户端与Android服务端的Socket同步通
  8. Android变形(Transform)之Matrix用法
  9. 编译不同android系统镜像,需要的环境要求,
  10. Android(安卓)Binder机制浅