StartService流程

startService.png

概述:

Ams在整個(gè)流程中充當(dāng)server端的作用, ActivityManagerNative兩次調(diào)用AMS,第一次調(diào)用創(chuàng)建service運(yùn)行的process,第二次調(diào)用創(chuàng)建具體的service

    一.從主進(jìn)程調(diào)用到ActivityManagerService進(jìn)程中,完成新進(jìn)程的創(chuàng)建;

    二. 從新進(jìn)程調(diào)用到ActivityManagerService進(jìn)程中,獲取要在新進(jìn)程啟動(dòng)的服務(wù)的相關(guān)信息;

    三. 從ActivityManagerService進(jìn)程又回到新進(jìn)程中,最終將服務(wù)啟動(dòng)起來(lái)。

一.從contextimpl的startServiceCommon方法進(jìn)入到ActivityManangerService的startService方法.

 ComponentName res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid, callingPackage, userId);

二.從AMS進(jìn)入到ActivityServices中的startServiceLocked方法

在該方法中首先確定該服務(wù)是前臺(tái)服務(wù)還是后臺(tái)服務(wù),

 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;
        }

取出一個(gè)ServiceLookupResult對(duì)象

ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType,
                    callingPid, callingUid, userId, true, callerFg);

ServiceLookupResult對(duì)象包括一個(gè)ServiceRecord對(duì)象和一個(gè)permission字符串

 private final class ServiceLookupResult {
        final ServiceRecord record;
        final String permission;

        ServiceLookupResult(ServiceRecord _record, String _permission) {
            record = _record;
            permission = _permission;
        }
    }
三.如果ActiveServices中沒有存儲(chǔ)service的引用,會(huì)生成一個(gè)新的ServiceRecord進(jìn)行存儲(chǔ),并將service從PendingServices隊(duì)列中去除,并且重新開始這個(gè)service.
if (r == null && createIfNeeded) {
                    Intent.FilterComparison filter
                            = new Intent.FilterComparison(service.cloneFilter());
                    ServiceRestarter res = new ServiceRestarter();
                    BatteryStatsImpl.Uid.Pkg.Serv ss = null;
                    BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
                    synchronized (stats) {
                        ss = stats.getServiceStatsLocked(
                                sInfo.applicationInfo.uid, sInfo.packageName,
                                sInfo.name);
                    }
                    r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
                    res.setService(r);
                    smap.mServicesByName.put(name, r);
                    smap.mServicesByIntent.put(filter, r);

                    // Make sure this component isn't in the pending list.
                    for (int i=mPendingServices.size()-1; i>=0; i--) {
                        ServiceRecord pr = mPendingServices.get(i);
                        if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
                                && pr.name.equals(name)) {
                            mPendingServices.remove(i);
                        }
                    }

如果callerApp運(yùn)行在后臺(tái),service有可能因?yàn)楹笈_(tái)啟動(dòng)隊(duì)列已滿而暫緩啟動(dòng),但如果callerApp運(yùn)行在前臺(tái)則沒有這種情況

   if (r.delayed) {
                    // This service is already scheduled for a delayed start; just leave
                    // it still waiting.
                    if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Continuing to delay: " + r);
                    return r.name;
                }
                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;
                }

四,進(jìn)入startServiceInnerLocked函數(shù)

如果此時(shí)

if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }

ServiceRecord對(duì)象中的app和app對(duì)象中的thread均不為null,則調(diào)用bringUpServiceLocked()函數(shù),并返回null值,也就是service已經(jīng)啟動(dòng)的情況

String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false);

在bringUpServiceLocked()函數(shù)中:

1>

首先會(huì)調(diào)用
sendServiceArgsLocked函數(shù)

在這里出現(xiàn)一個(gè)StartItem的數(shù)據(jù)結(jié)構(gòu),這個(gè)類記錄了一次service的啟動(dòng)過程的相關(guān)參數(shù)
 final ArrayList<StartItem> pendingStarts = new ArrayList<StartItem>();
                            // start() arguments that haven't yet been delivered.

接著調(diào)用

                bumpServiceExecutingLocked(r, execInFg, "start");

在這個(gè)函數(shù)中主要對(duì)處于executing狀態(tài)的service進(jìn)行判斷,看是否已經(jīng)超時(shí),前臺(tái)service是20秒,后臺(tái)servie是200s

之后會(huì)執(zhí)行scheduleServiceArgs()函數(shù),在該函數(shù)中跳轉(zhuǎn)到handleServiceArgs函數(shù)中

handleServiceArgs((ServiceArgsData)msg.obj);

在handleServiceArgs中主要執(zhí)行了onStartCommand和onTaskRemoved兩個(gè)回調(diào)函數(shù)

res = s.onStartCommand(data.args, data.flags, data.startId);
s.onTaskRemoved(data.args);

通過binder通信回到AMS中執(zhí)行serviceDoneExecuting()函數(shù)

2>

再回到bringUpServieLocked()函數(shù)中,判斷該service是否處于正在準(zhǔn)備restart的狀態(tài),或者service處在restart隊(duì)列就強(qiáng)制把它移除該隊(duì)列.再判斷service是否處于延遲開始狀態(tài),


        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);

        // We are now bringing the service up, so no longer in the
        // restarting state.
        if (mRestartingServices.remove(r)) {
            r.resetRestartCounter();
            clearRestartingIfNeededLocked(r);
        }

// Make sure this service is no longer considered delayed, we are starting it now.
        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;
        }

        // Make sure that the user who owns this service is started.  If not,
        // we don't want to allow it to run.
        if (mAm.mStartedUsers.get(r.userId) == null) {
            String msg = "Unable to launch app "
                    + r.appInfo.packageName + "/"
                    + r.appInfo.uid + " for service "
                    + r.intent.getIntent() + ": user " + r.userId + " is stopped";
            Slog.w(TAG, msg);
            bringDownServiceLocked(r);
            return msg;
        }

3>之后判斷該service是否要運(yùn)行在一個(gè)單獨(dú)的進(jìn)程中,如果運(yùn)行在當(dāng)前進(jìn)程并且進(jìn)程已經(jīng)啟動(dòng),就直接調(diào)用realStartServiceLocked()方法:

realStartServiceLocked(r, app, execInFg);
如果要運(yùn)行在單獨(dú)的進(jìn)程中,會(huì)調(diào)用startProcessLocked()方法開啟一個(gè)新的進(jìn)程.

觀察startProcessLocked()方法:

如果service會(huì)運(yùn)行在當(dāng)前進(jìn)程中,就會(huì)調(diào)用getProcessLocked()方法得到一個(gè)ProcessRecord對(duì)象。

下面代碼中有一段邏輯,如果啟動(dòng)service的intent由后臺(tái)發(fā)出,那么一旦判斷目前的進(jìn)程時(shí)bad進(jìn)程就會(huì)直接返回一個(gè)null值.

badProcess是指在一段時(shí)間內(nèi)發(fā)生兩次以上crash的進(jìn)程,AMS中有一個(gè)隊(duì)列來(lái)存儲(chǔ)這些bad進(jìn)程,而一旦該進(jìn)程被restart了,那么它就會(huì)從bad隊(duì)列中去除掉.

if (!isolated) {
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
            checkTime(startTime, "startProcess: after getProcessRecord");

            if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
                // If we are in the background, then check to see if this process
                // is bad.  If so, we will just silently fail.
                if (mBadProcesses.get(info.processName, info.uid) != null) {
                    if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
                            + "/" + info.processName);
                    return null;
                }
            } else {
                // When the user is explicitly starting a process, then clear its
                // crash count so that we won't make it bad until they see at
                // least one crash dialog again, and make the process good again
                // if it had been bad.
                if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
                        + "/" + info.processName);
                mProcessCrashTimes.remove(info.processName, info.uid);
                if (mBadProcesses.get(info.processName, info.uid) != null) {
                    EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                            UserHandle.getUserId(info.uid), info.uid,
                            info.processName);
                    mBadProcesses.remove(info.processName, info.uid);
                    if (app != null) {
                        app.bad = false;
                    }
                }
            }
        } else {
            // If this is an isolated process, it can't re-use an existing process.
            app = null;
        }

最終進(jìn)入到startProcessLocked()方法調(diào)用Process.start()方法開啟一個(gè)新的進(jìn)程.

 checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
/ We don't have to do anything more if:
        // (1) There is an existing application record; and
        // (2) The caller doesn't think it is dead, OR there is no thread
        //     object attached to it so we know it couldn't have crashed; and
        // (3) There is a pid assigned to it, so it is either starting or
        //     already running.

創(chuàng)建新新進(jìn)程后,會(huì)把service加入到等待啟動(dòng)的隊(duì)列中

if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }

當(dāng)新進(jìn)程啟動(dòng)后,會(huì)調(diào)用attachApplicationLocked方法調(diào)用ActiveService中的realStartService()方法啟動(dòng)該service,在方法內(nèi)部繼續(xù)調(diào)用ActivityThread的scheduleCreateService方法.

 app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);

最終會(huì)調(diào)用到ActivityThread中的handleCreateService方法,在該方法中執(zhí)行service的onCreate()回調(diào).

回到scheduleCreateService函數(shù)中,繼續(xù)調(diào)用handleServiceArgs()方法,并在該方法中執(zhí)行service的回調(diào)onstartCommand()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容