聊聊startService()方法(上)

簡介

我們做app經(jīng)常會(huì)接觸到service這個(gè)組件,書上也經(jīng)常說,我們應(yīng)該把一些耗時(shí)的操作放到service中,那么問題來了,為什么我們要把耗時(shí)的操作放到service中,service有什么特殊的意義?放到service中就安然無恙了嗎?我們帶著這些問題,來看看我們今天的主角service,故事就這樣展開了。

掃個(gè)盲

  • AMP:ActivityManagerProxy
  • AMN:ActivityManagerNative
  • AMS:ActivityManagerService
  • AT:ApplicationThread
  • ATP:ApplicationThreadProxy
  • ATN:ApplicationThreadNative

我們看看這些寶貝類或者接口的關(guān)系圖:

binder.jpg

使用

<service android:enabled=["true" | "false"]
    android:exported[="true" | "false"]
    android:icon="drawable resource"
    android:label="string resource"
    android:name="string"
    android:permission="string"
    android:process="string">
    <intent-filter >
        <action android:name="com.android.server.TestService.TestAction" />
    </intent-filter>
</service>

在代碼中:

..............
Intent serviceIntent = new Intent(mContext, TestService.class);
serviceIntent.putExtra("Args", mArgs);
mContext.startService(serviceIntent);
..............
public class TestService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        ...........
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        ..............
        return START_STICKY;
    }

     @Override
     public void onDestroy() {
         super.onDestroy();
        ..........
    }
}

使用結(jié)果說明:

  • onBind() :bind service的時(shí)候使用
  • onCreate()
  • onStartCommand()
    1. START_STICKY
      當(dāng)Service因?yàn)閮?nèi)存不足而被系統(tǒng)kill后,在接下來的某個(gè)時(shí)間內(nèi),當(dāng)系統(tǒng)內(nèi)存足夠可用的情況下,系統(tǒng)將會(huì)嘗試重新創(chuàng)建此Service; 
      一旦創(chuàng)建成功后,將回調(diào)onStartCommand方法,但一般情況下,參數(shù)中的Intent將是null。
      
    2. START_NOT_STICKY
      當(dāng)Service因?yàn)閮?nèi)存不足而被系統(tǒng)kill后,在接下來的某個(gè)時(shí)間內(nèi),即使系統(tǒng)內(nèi)存足夠可用,系統(tǒng)也不會(huì)嘗試重新創(chuàng)建此Service。
      
    3. START_REDELIVER_INTENT
      與START_STICKY相同,當(dāng)Service因?yàn)閮?nèi)存不足而被系統(tǒng)kill后,在接下來的某個(gè)時(shí)間內(nèi),當(dāng)系統(tǒng)內(nèi)存足夠可用的情況下,系統(tǒng)將會(huì)嘗試重新創(chuàng)建此Service;
      唯一不同的是,Service創(chuàng)建成功后,回調(diào)onStartCommand方法時(shí),傳入的參數(shù)將是最后一次調(diào)用startService時(shí)使用的intent。
      

需要注意的是,只有系統(tǒng)kill掉Service時(shí)上述返回值才有意義,如果是人為地kill掉Service進(jìn)程,系統(tǒng)不會(huì)按照onStartCommand的返回值重啟Service。

最后,客戶端無論調(diào)用多少次startService,只需要一次stopService即可將此Service終止(畢竟onCreate函數(shù)也之調(diào)用過一次),此時(shí)AMS將回調(diào)Service的onDestroy函數(shù)。

service啟動(dòng)的兩種方式

  1. 顯示啟動(dòng)

    ...........
    Intent startIntent = new Intent();
    ComponentName componentName = new ComponentName("service的packagename", "service的classname");
    startIntent.setComponent(componentName);
    mContext.startService(startIntent);
    ............
    
    ...........
    Intent startIntent = new Intent(mContext, TestService.class);
    mContext.startService(startIntent);
    ............
    
  2. 隱式啟動(dòng)

    ............
    Intent startIntent = new Intent();
    startIntent.setAction("com.android.server.TestService.TestAction");
    mContext.startService(startIntent);
    ............
    

隱式啟動(dòng)在5.0以后廢棄

分析

先從Acvitiy說起,比如我們現(xiàn)在最常見的就是從Activity進(jìn)行startService(),我們先看一下繼承關(guān)系

Context
    ContextWrapper
        ContextThemeWrapper
            Activity

當(dāng)我們調(diào)用startService的時(shí)候,其實(shí)是調(diào)用了ContextWrapper中的方法。當(dāng)我們分析Activity如何創(chuàng)建的時(shí)候我們在來說ContextWrapper是在那里創(chuàng)建的。

startSerive1.png
startService.jpg
  • 黃色表示當(dāng)前要啟動(dòng)service的進(jìn)程
  • 綠色表示systemserver進(jìn)程
  • service所在進(jìn)程(有可能在同一個(gè)進(jìn)程,也有可能不再同一個(gè)進(jìn)程)

核心方法

AS.startServiceLocked()

part1

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
        int callingPid, int callingUid, String callingPackage, final int userId)
        throws TransactionTooLargeException {
    ................
    final boolean callerFg;
    if (caller != null) {
        //通過AMS得到調(diào)用方的進(jìn)程信息
        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
        ................
        //判斷調(diào)用方是否屬于前臺(tái)進(jìn)程
        callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
    } else {
        callerFg = true;
    }

    //檢索待啟動(dòng)的Service
    ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false);//[part1-1]
    ..................
    //從ServiceLookupResult中取出ServiceRecord
    ServiceRecord r = res.record;
    .................

如果調(diào)用者為null,則callerFg = true,否則callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;通過這個(gè)來判斷是不是處于后臺(tái)

補(bǔ)充知識(shí):

  1. 內(nèi)核負(fù)責(zé)了進(jìn)程的CPU調(diào)度,所有運(yùn)行中的進(jìn)程并非能平等的能獲取相等的時(shí)間片。在ProcessRecord中,通過Schedule Group來記錄進(jìn)程的調(diào)度組:
  2. 它們可能的取值定義在ProcessList.java中:
// Activity manager's version of Process.THREAD_GROUP_BG_NONINTERACTIVE
static final int SCHED_GROUP_BACKGROUND = 0;
// Activity manager's version of Process.THREAD_GROUP_DEFAULT
static final int SCHED_GROUP_DEFAULT = 1;
// Activity manager's version of Process.THREAD_GROUP_TOP_APP
static final int SCHED_GROUP_TOP_APP = 2;
// Activity manager's version of Process.THREAD_GROUP_TOP_APP
// Disambiguate between actual top app and processes bound to the top app
static final int SCHED_GROUP_TOP_APP_BOUND = 3;

其中獲取CPU資源的能力來看,SCHED_GROUP_TOP_APP_BOUND最高,其次SCHED_GROUP_TOP_APP應(yīng)該強(qiáng)于SCHED_GROUP_DEFAULT, 最后才輪到SCHED_GROUP_BACKGROUND

part1-1 retrieveServiceLocked()

private ServiceLookupResult retrieveServiceLocked(.......) {
    ServiceRecord r = null;
    ..........
    //得到當(dāng)前用戶的UserId
    userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
            ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);

    //每個(gè)UserId有對應(yīng)的ServiceMap,統(tǒng)一保存在ActiveServices中
    ServiceMap smap = getServiceMap(userId);

    //對于顯示啟動(dòng)
    final ComponentName comp = service.getComponent();
    if (comp != null) {
        //根據(jù)ComponentName從ServiceMap中取出對應(yīng)的ServiceRecord
        r = smap.mServicesByName.get(comp);
    }

    //對于隱式啟動(dòng)
    if (r == null && !isBindExternal) {
        Intent.FilterComparison filter = new Intent.FilterComparison(service);
        //根據(jù)Intent對應(yīng)的Filter,從ServiceMap中取出匹配的ServiceRecord
        r = smap.mServicesByIntent.get(filter);
    }

    //特殊情況的處理
    //對于包含F(xiàn)LAG_EXTERNAL_SERVICE的service,將運(yùn)行于調(diào)用方進(jìn)程中
    //對于這種特殊服務(wù),
    //如果根據(jù)Component或Filter找到了一個(gè)正在運(yùn)行的Service,但其運(yùn)行進(jìn)程與當(dāng)前調(diào)用進(jìn)程不一致
    //那么必須重新在調(diào)用進(jìn)程中創(chuàng)建該ServiceRecord,于是將r置為null
    if (r != null && (r.serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0
            && !callingPackage.equals(r.packageName)) {
        // If an external service is running within its own package, other packages
        // should not bind to that instance.
        r = null;
    }

    //以上均是在緩存信息中,查找ServiceRecord
    //如果查詢不到,則必須通過PKMS進(jìn)行查找
    if (r == null) {
        try {
            //PKMS根據(jù)參數(shù)得到對應(yīng)Pkg中Serivce的ResolveInfo
            ResolveInfo rInfo = AppGlobals.getPackageManager().resolveService(service,
                    resolvedType, ActivityManagerService.STOCK_PM_FLAGS
                            | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                    userId);

            //從ResolveInfo中取出ServiceInfo
            ServiceInfo sInfo =
                    rInfo != null ? rInfo.serviceInfo : null;

            //構(gòu)造出Service對應(yīng)的ComponentName
            ComponentName name = new ComponentName(
                    sInfo.applicationInfo.packageName, sInfo.name);

            //特殊情況處理
            if ((sInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0) {
                if (isBindExternal) {
                    ..............
                    // Run the service under the calling package's application.
                    //FLAG_EXTERNAL_SERVICE將運(yùn)行在調(diào)用方進(jìn)程中,此處就是修改PKMS檢索出的ServiceInfo
                    //先得到調(diào)用方的應(yīng)用信息
                    ApplicationInfo aInfo = AppGlobals.getPackageManager().getApplicationInfo(
                            callingPackage, ActivityManagerService.STOCK_PM_FLAGS, userId);
                    ............
                    //將ServiceInfo中的信息,改為調(diào)用方應(yīng)用的信息
                    sInfo = new ServiceInfo(sInfo);
                    sInfo.applicationInfo = new ApplicationInfo(sInfo.applicationInfo);
                    sInfo.applicationInfo.packageName = aInfo.packageName;
                    sInfo.applicationInfo.uid = aInfo.uid;
                    name = new ComponentName(aInfo.packageName, name.getClassName());
                    service.setComponent(name);
                } else {
                    //拋出異常
                    .....
                }
            } else if(isBindExternal) {
                //拋出異常
                ............
            }

            //多用戶的處理
            if (userId > 0) {
                //檢查服務(wù)是否為單例且可被調(diào)用的
                if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
                        sInfo.name, sInfo.flags)
                        && mAm.isValidSingletonCall(callingUid, sInfo.applicationInfo.uid)) {
                    //對于多用戶而言,每個(gè)用戶啟動(dòng)的服務(wù),運(yùn)行于對應(yīng)用戶所在進(jìn)程組中
                    //但如果待啟動(dòng)服務(wù)為單例的,那么該服務(wù)還是得運(yùn)行在系統(tǒng)用戶的進(jìn)程組中
                    //于是此次將userId置為0
                    userId = 0;

                    //ServiceMap都被調(diào)整為系統(tǒng)用戶對應(yīng)的
                    smap = getServiceMap(0);
                }
                sInfo = new ServiceInfo(sInfo);
                //此處使用了userId
                sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
            }

            r = smap.mServicesByName.get(name);
            if (r == null && createIfNeeded) {
                ..............
                //創(chuàng)建出對應(yīng)的ServiceRecord
                r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
                ..............
                //保存到ServiceMap中
                smap.mServicesByName.put(name, r);
                smap.mServicesByIntent.put(filter, r);
            }
        } catch(RemoteException ex) {
            ...........
        }
    }

    if (r != null) {
        //進(jìn)行一些權(quán)限檢查和有效性檢查
        .................

        //沒有問題時(shí),返回正常結(jié)果
        return new ServiceLookupResult(r, null);
    }
    return null;
}
  1. 得到當(dāng)前用戶的userId
  2. 根據(jù)userId得到ServiceMap,這個(gè)ServiceMap保存在ActiveServices中
  3. 根據(jù)顯示啟動(dòng)和隱式啟動(dòng)從ServiceMap中拿出來ServiceRecord
  4. 上面信息都是從當(dāng)前ActiveServices中的ServiceMap(緩存)中查找,如果沒有找到則通過PKMS進(jìn)行查找
  5. 最后確保沒有問題返回一個(gè)包裝ServiceRecord對象的ServiceLookupResult對象

part2

//進(jìn)行一些檢查工作
    .............
    if (res.record == null) {
        return new ComponentName("!", res.permission != null
                ? res.permission : "private to package");
    }
    ServiceRecord r = res.record;
    if (!mAm.getUserManagerLocked().exists(r.userId)) { //檢查是否存在啟動(dòng)服務(wù)的user
        return null;
    }
    //如果這個(gè)服務(wù)在重啟列表中,清空對應(yīng)的信息
    if (unscheduleServiceRestartLocked(r, callingUid, false)) {
        .................
    }

    r.lastActivity = SystemClock.uptimeMillis();
    r.startRequested = true;
    r.delayedStop = false;

    //startService可以多次向Service傳遞信息,每次的信息都是一個(gè)StartItem,對應(yīng)著一個(gè)StartId
    r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
            service, neededGrants));
    ............
    //addToStarting決定是否將待啟動(dòng)的Service
    //加入到ActiveServices維護(hù)的mStartingBackground隊(duì)列
    boolean addToStarting = false;

    //如果啟動(dòng)服務(wù)的不是前臺(tái)進(jìn)程
    //同時(shí)服務(wù)對應(yīng)的ServiceRecord中沒有記錄對應(yīng)進(jìn)程的信息(即初次使用)
    if (!callerFg && r.app == null
            //并且user已經(jīng)啟動(dòng)過其它進(jìn)程
            && mAm.mUserController.hasStartedUserState(r.userId)) {

        //通過AMS查詢Service對應(yīng)的進(jìn)程信息
        ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);

        //若Service對應(yīng)的進(jìn)程未啟動(dòng),或優(yōu)先級過低,則有可能需要延遲啟動(dòng)服務(wù)
        if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
            .....................
            if (r.delayed) {
                // This service is already scheduled for a delayed start; just leave
                // it still waiting.
                return r.name;
            }

            //若當(dāng)前用戶啟動(dòng)的后臺(tái)服務(wù)數(shù)量過多,則延遲啟動(dòng)服務(wù)
            if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
                ................
                smap.mDelayedStartList.add(r);
                r.delayed = true;
                return r.name;
            }
            ..............
            addToStarting = true;
        } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
            addToStarting = true;
            ................
        } ..........
        ............
    } ............
    ...............
    return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}
  • 做一些檢查工作
  • 如果這個(gè)服務(wù)在重啟列表中將晴空對應(yīng)信息
  • startService可以多次向Service傳遞信息,每次的信息都是一個(gè)StartItem,對應(yīng)著一個(gè)StartId
  • boolean addToStarting決定是否將待啟動(dòng)的Service加入到ActiveServices維護(hù)的mStartingBackground隊(duì)列
  • 如果啟動(dòng)服務(wù)的不是前臺(tái)進(jìn)程,同時(shí)服務(wù)對應(yīng)的ServiceRecord中沒有記錄對應(yīng)進(jìn)程的信息(即初次使用)并且user已經(jīng)啟動(dòng)過其它進(jìn)程則
    • 通過AMS查詢Service對應(yīng)的進(jìn)程信息
    • 如果Service對應(yīng)進(jìn)程沒有啟動(dòng),或者優(yōu)先級低,則有可能需要延遲啟動(dòng)服務(wù)
    • 如果當(dāng)前用戶啟動(dòng)的后臺(tái)服務(wù)數(shù)量大于后臺(tái)啟動(dòng)最大服務(wù)數(shù)量,則延遲啟動(dòng)
        //若當(dāng)前用戶啟動(dòng)的后臺(tái)服務(wù)數(shù)量過多,則延遲啟動(dòng)服務(wù)
          if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
              ................
              smap.mDelayedStartList.add(r);
              r.delayed = true;
              return r.name;
          }
      
    • addToStarting = true;(當(dāng)服務(wù)對應(yīng)的ServiceRecord沒有記錄對應(yīng)的進(jìn)程信息,如果不是延遲啟動(dòng))||(包含service的進(jìn)程已經(jīng)存在并且proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE//Process is in the background running a service.)

概述:
判斷當(dāng)前Service是否需要延遲啟動(dòng)。
若需要延遲啟動(dòng),則將ServiceRecord保存到smap中的mDelayedStartList中,并結(jié)束本啟動(dòng)流程;
否則,調(diào)用startServiceInnerLocked函數(shù),進(jìn)入啟動(dòng)Service的下一個(gè)階段。

AS.startServiceInnerLocked()

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
        boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
    ProcessStats.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(); //用于耗電統(tǒng)計(jì),開啟運(yùn)行的狀態(tài)
    }
    //核心啟動(dòng)service的方法
    String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false);
    if (error != null) {
        return new ComponentName("!!", error);
    }
    //
    if (r.startRequested && addToStarting) {
        boolean first = smap.mStartingBackground.size() == 0;
        smap.mStartingBackground.add(r);
        r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;
        if (first) {
            smap.rescheduleDelayedStarts();
        }
    } else if (callerFg) {
        smap.ensureNotStartingBackground(r);
    }
    return r.name;
}
  • 通過bringUpServiceLocked真正啟動(dòng)service
  • 當(dāng)啟動(dòng)完成的時(shí)候設(shè)置啟動(dòng)超時(shí)時(shí)間
  • 啟動(dòng)成功之后將ServiceRecord加入到smap中的mStartingBackground中
  • 如果是第一次啟動(dòng)則需要從smap.rescheduleDelayedStarts();中移除MSG_BG_START_TIMEOUT(service未啟動(dòng)ANR)并且從mStartingBackground(后臺(tái)啟動(dòng)service列表中)移除,仔細(xì)研究見下文

AS.rescheduleDelayedStarts()

void rescheduleDelayedStarts() {
    //前面的注釋已經(jīng)提到過,后臺(tái)進(jìn)程啟動(dòng)Service超時(shí)會(huì)發(fā)送MSG_BG_START_TIMEOUT消息
    //該消息被處理時(shí),也會(huì)調(diào)用rescheduleDelayedStarts函數(shù)
    //因此,進(jìn)入該函數(shù)時(shí),先移除掉該信息
    removeMessages(MSG_BG_START_TIMEOUT);

    final long now = SystemClock.uptimeMillis();
    for (int i=0, N=mStartingBackground.size(); i<N; i++) {
        ServiceRecord r = mStartingBackground.get(i);

        //將超時(shí)的Service從mStartingBackground中移除
        if (r.startingBgTimeout <= now) {
            Slog.i(TAG, "Waited long enough for: " + r);
            mStartingBackground.remove(i);
            N--;
            i--;
        }
    }

    //存在延遲Service,同時(shí)后臺(tái)Service較少時(shí)
    while (mDelayedStartList.size() > 0
            && mStartingBackground.size() < mMaxStartingBackground) {
        ServiceRecord r = mDelayedStartList.remove(0);
        .................
        r.delayed = false;
        try {
            //啟動(dòng)延遲Service,啟動(dòng)后會(huì)修改mStartingBackground.size
            startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false, true);
        } catch (TransactionTooLargeException e) {
            ..........
        }

        if (mStartingBackground.size() > 0) {
            ServiceRecord next = mStartingBackground.get(0);
            //決定延遲發(fā)送消息的時(shí)間
            long when = next.startingBgTimeout > now ? next.startingBgTimeout : now;
            ................
            Message msg = obtainMessage(MSG_BG_START_TIMEOUT);
            //一旦超時(shí),就會(huì)發(fā)送MSG_BG_START_TIMEOUT
            sendMessageAtTime(msg, when);
        }
        .....................
    }
}
  • 移除MSG_BG_START_TIMEOUT消息
  • 將超時(shí)的Service從mStartingBackground中移除
  • 存在延時(shí)service并且沒有達(dá)到后臺(tái)啟動(dòng)service最大數(shù)量的時(shí)候啟動(dòng)延時(shí)的service
  • 在mStartingBackground.size()>0后,發(fā)送延時(shí)啟動(dòng)消息一旦時(shí)間到達(dá)或者時(shí)間時(shí)間超出,則發(fā)送信號(hào)重新調(diào)用rescheduleDelayedStarts()

概述:

  • 判斷mStartingBackground中啟動(dòng)的Service是否超時(shí)
  • 判斷能否啟動(dòng)mDelayedStartList中,被延遲啟動(dòng)的服務(wù)。

AS.bringUpServiceLocked()

private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
        boolean whileRestarting) throws TransactionTooLargeException {
        //處理Service已經(jīng)啟動(dòng)的情況,此時(shí)只是發(fā)送新的StartItem
    if (r.app != null && r.app.thread != null) {
        //調(diào)用service.onStartCommand()過程
        sendServiceArgsLocked(r, execInFg, false);
        return null;
    }
    if (!whileRestarting && r.restartDelay > 0) {
        return null; //等待延遲重啟的過程,則直接返回
    }

    // 啟動(dòng)service前,把service從重啟服務(wù)隊(duì)列中移除
    if (mRestartingServices.remove(r)) {
        r.resetRestartCounter();
        clearRestartingIfNeededLocked(r);
    }
    //service正在啟動(dòng),將delayed設(shè)置為false
    if (r.delayed) {
        getServiceMap(r.userId).mDelayedStartList.remove(r);
        r.delayed = false;
    }

    //確保擁有該服務(wù)的user已經(jīng)啟動(dòng),否則停止;
    if (mAm.mStartedUsers.get(r.userId) == null) {
        String msg = "";
        bringDownServiceLocked(r);
        return msg;
    }
    //服務(wù)正在啟動(dòng),設(shè)置package停止?fàn)顟B(tài)為false
    AppGlobals.getPackageManager().setPackageStoppedState(
            r.packageName, false, r.userId);

    final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
    final String procName = r.processName;
    ProcessRecord app;
    if (!isolated) {
        //根據(jù)進(jìn)程名和uid,查詢ProcessRecord
        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
        //能進(jìn)入此循環(huán)說明對應(yīng)進(jìn)程已經(jīng)啟動(dòng)
        if (app != null && app.thread != null) {
            try {
                app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                // 啟動(dòng)服務(wù)
                realStartServiceLocked(r, app, execInFg);
                return null;
            } catch (TransactionTooLargeException e) {
                throw e;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting service " + r.shortName, e);
            }
        }
    } else {
        app = r.isolatedProc;
    }

    //對于進(jìn)程沒有啟動(dòng)的情況
    if (app == null) {
        //啟動(dòng)service所要運(yùn)行的進(jìn)程
        if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                "service", r.name, false, isolated, false)) == null) {
            String msg = ""
            bringDownServiceLocked(r); // 進(jìn)程啟動(dòng)失敗
            return msg;
        }
        if (isolated) {
            r.isolatedProc = app;
        }
    }
    //mPendingServices保存待啟動(dòng)服務(wù),當(dāng)進(jìn)程啟動(dòng)后,會(huì)重新啟動(dòng)該服務(wù)
    if (!mPendingServices.contains(r)) {
        mPendingServices.add(r);
    }
    //服務(wù)還未完成啟動(dòng),就收到結(jié)束請求時(shí),會(huì)直接停止該服務(wù)
    if (r.delayedStop) {
        r.delayedStop = false;
        if (r.startRequested) {
            stopServiceLocked(r); //停止服務(wù)
        }
    }
    return null;
}
  • service已經(jīng)啟動(dòng)過了,則調(diào)用sendServiceArgsLocked函數(shù),將新的待處理信息發(fā)送給Service
  • service未啟動(dòng)過,但對應(yīng)的進(jìn)程已啟動(dòng),那么調(diào)用realStartServiceLocked函數(shù),啟動(dòng)服務(wù)即可;
  • service對應(yīng)的進(jìn)程并沒有啟動(dòng),那么先啟動(dòng)進(jìn)程。在啟動(dòng)進(jìn)程過程中會(huì)調(diào)用realStartServiceLocked啟動(dòng)service

所以這里,如果service啟動(dòng)過了,現(xiàn)在重新調(diào)用啟動(dòng)函數(shù)的話,則只是將intent的信息發(fā)送給service進(jìn)行處理,如果service沒有啟動(dòng)但是進(jìn)程啟動(dòng)了,那么就會(huì)啟動(dòng)service,如果連進(jìn)程都沒有啟動(dòng)則會(huì)啟動(dòng)進(jìn)程,然后在啟動(dòng)進(jìn)程的過程中會(huì)啟動(dòng)service

AS.realStartServiceLocked()

private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
    ...

    r.app = app;
    r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
    final boolean newService = app.services.add(r);

    //發(fā)送delay消息
    bumpServiceExecutingLocked(r, execInFg, "create");
    //更新進(jìn)程對應(yīng)的優(yōu)先級信息
    mAm.updateLruProcessLocked(app, false, null);
    mAm.updateOomAdjLocked();
    boolean created = false;
    try {
        synchronized (r.stats.getBatteryStats()) {
            r.stats.startLaunchedLocked();
        }
        mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
        //更改進(jìn)程狀態(tài)為PROCESS_STATE_SERVICE
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
        //服務(wù)進(jìn)入 onCreate()
        //此時(shí)又是Binder通信,發(fā)送消息給目標(biāo)進(jìn)程的ApplicationThread,通知去創(chuàng)建服務(wù)
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
        r.postNotification();
        created = true;
    } catch (DeadObjectException e) {
        mAm.appDiedLocked(app); //當(dāng)是被時(shí)候會(huì)讓這個(gè)進(jìn)程也掛掉
        throw e;
    } finally {
        if (!created) {
            //如果服務(wù)創(chuàng)建失敗,則看是不是mDestroyingServices列表中有記錄,如果有則執(zhí)行一些銷毀動(dòng)作
            final boolean inDestroying = mDestroyingServices.contains(r);
            serviceDoneExecutingLocked(r, inDestroying, inDestroying);
            if (newService) {
                app.services.remove(r);
                r.app = null;
            }
            //嘗試重新啟動(dòng)服務(wù)
            if (!inDestroying) {
                scheduleServiceRestartLocked(r, false);
            }
        }
    }
    //Service被綁定過,才會(huì)調(diào)用onBind函數(shù)
    requestServiceBindingsLocked(r, execInFg);
    //如果客戶端Bind Service成功,按需更新服務(wù)端進(jìn)程優(yōu)先級
    updateServiceClientActivitiesLocked(app, null, true);

    if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                null, null));
    }
    //會(huì)調(diào)用sendServiceArgsLocked()方法發(fā)送參數(shù)
    sendServiceArgsLocked(r, execInFg, true);
    //如果Service是延遲啟動(dòng)的,那么此時(shí)可以將其從mDelayedStartList移除
    if (r.delayed) {
        getServiceMap(r.userId).mDelayedStartList.remove(r);
        r.delayed = false;
    }
    //若Service被要求停止,那么結(jié)束服務(wù)
    if (r.delayedStop) {
        r.delayedStop = false;
        if (r.startRequested) {
            stopServiceLocked(r); //停止服務(wù)
        }
    }
}
  • 對service的狀態(tài)進(jìn)行記錄(bumpServiceExecutingLocked)
  • 更新進(jìn)程對應(yīng)的優(yōu)先級信息(mAm.updateOomAdjLocked();)
  • 強(qiáng)制更改進(jìn)程的狀態(tài)(為PROCESS_STATE_SERVICE)
  • 通過Binder通信發(fā)送消息給進(jìn)程的ApplicationThread,創(chuàng)建服務(wù)(app.thread.scheduleCreateService())
  • 如果創(chuàng)建失敗則會(huì)kill進(jìn)程
  • 如果符合重啟條件則會(huì)重啟service
  • 如果調(diào)用過Bind service,則會(huì)調(diào)用(requestServiceBindingsLocked()---> OnBind函數(shù))
  • 如果Bind成功則會(huì)按照需求更新service進(jìn)程的優(yōu)先級
  • 構(gòu)造一個(gè)StartItem然后通過sendServiceArgsLocked發(fā)送參數(shù)(sendServiceArgsLocked())
  • 如果service是延時(shí)啟動(dòng)的則將其從mDelayedStartList中移除(getServiceMap(r.userId).mDelayedStartList.remove(r);)
  • 如果service被主動(dòng)要求停止那么調(diào)用(stopServiceLocked(r))

小節(jié)重點(diǎn):

  • 對service的狀態(tài)進(jìn)行記錄(bumpServiceExecutingLocked)
  • 通過Binder通信發(fā)送消息給進(jìn)程的ApplicationThread,創(chuàng)建服務(wù)(app.thread.scheduleCreateService())
  • 構(gòu)造一個(gè)StartItem然后通過sendServiceArgsLocked發(fā)送參數(shù)(sendServiceArgsLocked())

AS.bumpServiceExecutingLocked()

private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
    ..............
    long now = SystemClock.uptimeMillis();

    //executeNesting用于記錄Service待處理的請求數(shù)量
    if (r.executeNesting == 0) {
        //處理第一個(gè)命令時(shí),即初次啟動(dòng)Service時(shí)

        r.executeFg = fg;
        ServiceState stracker = r.getTracker();
        if (stracker != null) {
            //記錄時(shí)間
            stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);
        }

        if (r.app != null) {
            //更新進(jìn)程ProcessRecord中關(guān)于Service的記錄
            r.app.executingServices.add(r);
            r.app.execServicesFg |= fg;

            if (r.app.executingServices.size() == 1) {
                //設(shè)置啟動(dòng)Service超時(shí)的時(shí)間
                //即Service初次啟動(dòng)時(shí),如果進(jìn)程中只有這一個(gè)Service
                //那么一旦啟動(dòng)超時(shí),將觸發(fā)AMS發(fā)送ANR
                scheduleServiceTimeoutLocked(r.app);
            }
        }
    } else if (r.app != null && fg && !r.app.execServicesFg) {
        //前臺(tái)進(jìn)程向后臺(tái)服務(wù)發(fā)送命令時(shí),也會(huì)設(shè)置超時(shí)時(shí)間,一旦超時(shí),也會(huì)ANR

        //發(fā)送一次后,該值變?yōu)閠rue,相當(dāng)與變成前臺(tái)服務(wù)了
        r.app.execServicesFg = true;

        scheduleServiceTimeoutLocked(r.app);
    }
    r.executeFg |= fg;
    //每處理一個(gè)命令,executeNesting均會(huì)+1
    r.executeNesting++;
    r.executingStart = now;
}

這個(gè)方法主要將service和進(jìn)程關(guān)聯(lián)起來(更新ServiceRecord中的信息),并且如果進(jìn)程中只有一個(gè)service那么一旦超時(shí)就會(huì)給AMS發(fā)送ANR信息

void scheduleServiceTimeoutLocked(ProcessRecord proc) {
    //進(jìn)程中需要執(zhí)行service和當(dāng)前進(jìn)程都得存活
    if (proc.executingServices.size() == 0 || proc.thread == null) {
        return;
    }

    long now = SystemClock.uptimeMillis();
    Message msg = mAm.mHandler.obtainMessage(
                ActivityManagerService.SERVICE_TIMEOUT_MSG);
    msg.obj = proc;
    mAm.mHandler.sendMessageAtTime(msg,
            //前臺(tái)超時(shí)的時(shí)間為20s,后臺(tái)為200s
            proc.execServicesFg ? (now+SERVICE_TIMEOUT) : (now+ SERVICE_BACKGROUND_TIMEOUT));
}

這里看到?jīng)],是通過proc.execServicesFg判斷service是否在前后臺(tái)

AS.scheduleCreateService()

AS.scheduleCreateService()-->ActivityThread發(fā)送H.CREATE_SERVICE-->ActivityThread.handleCreateService()

private void handleCreateService(CreateServiceData data) {
    ....................
    //得到這個(gè)進(jìn)程對應(yīng)的LoadedApk
    LoadedApk packageInfo = getPackageInfoNoCheck(
            data.info.applicationInfo, data.compatInfo);
    Service service = null;
    try {
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        //通過反射創(chuàng)建出實(shí)例
        service = (Service) cl.loadClass(data.info.name).newInstance();
    } catch (Exception e) {
        ..................
    } 

    try {
        ............
        //創(chuàng)建service的ContextImpl對象
        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        //實(shí)際工作類為ContextImpl,其代理設(shè)置為service
        context.setOuterContext(service);
        //得到app的Application對象
        Application app = packageInfo.makeApplication(false, mInstrumentation);

        //將一些重要的信息和對象綁定到service中
        //此處傳遞的this是ActivityThread,這就是大家常說的:service也是運(yùn)行在主線程中的原因
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManagerNative.getDefault());

        //調(diào)用Service的onCreate函數(shù)
        service.onCreate();

        //mServices中存儲(chǔ)了ActivityThread中運(yùn)行的服務(wù)
        //key值為Service對應(yīng)的IBinder,是從Service對應(yīng)的ServiceRecord中取出的
        mServices.put(data.token, service);
        try {
            //通知AMS service啟動(dòng)成功,進(jìn)行取消超時(shí)消息等操作
            //后文再分析該函數(shù)
            ActivityManagerNative.getDefault().serviceDoneExecuting(
                    data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    } catch (Exception e) {
        .............
    }
}
  • 得到Service對應(yīng)的LoadedApk信息
  • 通過反射創(chuàng)建出service實(shí)例
  • 創(chuàng)建service的ContextImpl
  • 將service類設(shè)置成代理,實(shí)際工作的是ContextImpl
  • 將service綁定一些常用的對象(service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault());)其中this是當(dāng)前進(jìn)程的ActiveThread對象
  • 調(diào)用service.onCreate()方法
  • 將當(dāng)前service添加到ActivityThread的mServices中利用鍵值對方式(mServices.put(data.token, service);)
  • 通知AMS service啟動(dòng)成功,進(jìn)行取消ANR那個(gè)消息(ActivityManagerNative.getDefault().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);)

小節(jié):

  • 得到LoadedApk反射得到service
  • 讓service持有當(dāng)前進(jìn)程的核心對象(service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault());)其中this是當(dāng)前進(jìn)程的ActiveThread對象
  • 調(diào)用service.onCreate()方法
  • 移除啟動(dòng)爆發(fā)那個(gè)ANR消息

AS.sendServiceArgsLocked()

private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
        boolean oomAdjusted) throws TransactionTooLargeException {
    ...............
    //本次需發(fā)送的信息,在調(diào)用sendServiceArgsLocked前,已經(jīng)加入到了pendingStarts中
    //通過循環(huán),將pending的信息發(fā)送完
    while (r.pendingStarts.size() > 0) {
        ...........
        try {
            //依次取出
            si = r.pendingStarts.remove(0);
            ............
            si.deliveredTime = SystemClock.uptimeMillis();
            //記錄發(fā)送時(shí)間和發(fā)送次數(shù)
            r.deliveredStarts.add(si);
            si.deliveryCount++;
            ...........
            int flags = 0;
            //發(fā)送次數(shù)大于1,添加對應(yīng)flag
            if (si.deliveryCount > 1) {
                flags |= Service.START_FLAG_RETRY;
            }

            //這個(gè)應(yīng)該是service被kill掉后,系統(tǒng)重啟服務(wù)發(fā)送的Intent,于是添加對應(yīng)的flag
            if (si.doneExecutingCount > 0) {
                flags |= Service.START_FLAG_REDELIVERY;
            }

            //Binder通信給ApplicationThread
            r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
        } ..........
        ...........
    }
}

r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),service, neededGrants));這個(gè)方法我們在許多地方調(diào)用比如在startServiceLocked()中,我們是將需要給service傳遞的信息封裝成一個(gè)startItem,在這個(gè)方法中我們將其發(fā)送給setvice,下面我們就看發(fā)送流程

  • 取出StartItem消息
  • 記錄發(fā)送時(shí)間和次數(shù)
  • 當(dāng)發(fā)送次數(shù)大于1,則添加對應(yīng)的flag
  • 通過binder方式給ApplicationThread發(fā)送這個(gè)startItem

r.app.thread.scheduleServiceArgs()-->H.SERVICE_ARGS-->ActivityThread.handleServiceArgs()

ActivityThread.handleServiceArgs()

private void handleServiceArgs(ServiceArgsData data) {
    //取出IBinder對應(yīng)的Service
    Service s = mServices.get(data.token);

    if (s != null) {
        try {
            .........
            int res;
            //通常情況,taskRemoved為false
            if (!data.taskRemoved) {
                //調(diào)用Service的onStartCommand函數(shù),處理Intent攜帶的內(nèi)容
                res = s.onStartCommand(data.args, data.flags, data.startId);
            } else {
                s.onTaskRemoved(data.args);
                res = Service.START_TASK_REMOVED_COMPLETE;
            }

            //在通知AMS消息處理完成前,現(xiàn)完成本地等待處理的任務(wù)
            //這里與啟動(dòng)BroadcastReceiver對應(yīng)進(jìn)程的情況相似
            //進(jìn)程可能是由于創(chuàng)建Service才被啟動(dòng)的,Service處理完畢后,AMS可能進(jìn)行進(jìn)程管理
            //殺死Service對應(yīng)進(jìn)程,因此先確保工作做完
            QueuedWork.waitToFinish();

            try {
                //再次調(diào)用AMS的serviceDoneExecuting函數(shù),通知AMS消息處理完畢
                //本次的flag為SERVICE_DONE_EXECUTING_START
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
            ensureJitEnabled();
        } catch(Exception e) {
            ........
        }
    }
}

很明確這里是會(huì)調(diào)用Service.onConmmand函數(shù),處理Intent攜帶的內(nèi)容
所以我們可以知道,Service.onConmmand函數(shù)可以調(diào)用多次,但是Service.onCreate()方法只能調(diào)用一次
然后再次調(diào)用AMS的serviceDoneExecuting函數(shù)通知執(zhí)行結(jié)果。

不過這里需要注意的是當(dāng)前調(diào)用onStartCommand之后會(huì)有一個(gè)結(jié)果返回,要根據(jù)這個(gè)結(jié)果AMS要做一些處理。我們先補(bǔ)充一點(diǎn)使用onStartCommand的知識(shí)。

  (1):onstart()方法和onStartCommand()方法的區(qū)別:
    onstart()方法是在android2.0一下的版本中使用。而在android2.0以上則使用onstartCommand()方法。它們兩個(gè)方法放在一起使用時(shí),不會(huì)產(chǎn)生沖突。
 
(2):onStartComand使用時(shí),返回的是一個(gè)(int)整形。
    這個(gè)整形可以有四個(gè)返回值:start_sticky、start_no_sticky、START_REDELIVER_INTENT、START_STICKY_COMPATIBILITY。
    它們的含義分別是:
       1):START_STICKY:如果service進(jìn)程被kill掉,保留service的狀態(tài)為開始狀態(tài),但不保留遞送的intent對象。隨后系統(tǒng)會(huì)嘗試重新創(chuàng)建service,由于服務(wù)狀態(tài)為開始狀態(tài),所以創(chuàng)建服務(wù)后一定會(huì)調(diào)用onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動(dòng)命令被傳遞到service,那么參數(shù)Intent將為null。
       2):START_NOT_STICKY:“非粘性的”。使用這個(gè)返回值時(shí),如果在執(zhí)行完onStartCommand后,服務(wù)被異常kill掉,系統(tǒng)不會(huì)自動(dòng)重啟該服務(wù)
       3):START_REDELIVER_INTENT:重傳Intent。使用這個(gè)返回值時(shí),如果在執(zhí)行完onStartCommand后,服務(wù)被異常kill掉,系統(tǒng)會(huì)自動(dòng)重啟該服務(wù),并將Intent的值傳入。
       4):START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保證服務(wù)被kill后一定能重啟。

然后我們看看通過 ActivityManagerNative.getDefault().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);調(diào)用之后的結(jié)果

public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
    synchronized(this) {
        ............
        mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
    }
}



void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
    //Service每執(zhí)行完一次命令都會(huì)通知AMS,serviceDoneExecutingLocked將被多次調(diào)用
    //因此,該函數(shù)中需要處理的場景比較多

    //先判斷該Service是否destroy
    boolean inDestroying = mDestroyingServices.contains(r);

    if (r != null) {
        //Service的onStartCommand函數(shù)被調(diào)用后,通知AMS的type為SERVICE_DONE_EXECUTING_START
        if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
            r.callStart = true;
            //處理onStartCommand的返回值
            switch (res) {
                case Service.START_STICKY_COMPATIBILITY:
                case Service.START_STICKY: {
                    //找到startId對應(yīng)的StartItem,并移除(true)
                    r.findDeliveredStart(startId, true);
                    //這個(gè)值置為false后,Service被殺掉還有機(jī)會(huì)重啟
                    r.stopIfKilled = false;
                    break;
                }
                case Service.START_NOT_STICKY: {
                    //找到startId對應(yīng)的StartItem,并移除(true)
                    r.findDeliveredStart(startId, true);

                    if (r.getLastStartId() == startId) {
                        //服務(wù)kill掉,不再重啟
                        r.stopIfKilled = true;
                    }
                    break;
                }
                case Service.START_REDELIVER_INTENT: {
                    //找到startId對應(yīng)的StartItem,不移除(false)
                    ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
                    if (si != null) {
                        si.deliveryCount = 0;
                        si.doneExecutingCount++;
                        r.stopIfKilled = true;
                    }
                    break;
                }
                .............
            }
        } else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) {
            //Service的onStop函數(shù)被調(diào)用時(shí),通知AMS的type為SERVICE_DONE_EXECUTING_STOP
            //打一些log而已,無實(shí)際操作
            ..................
        }
        ..........
        serviceDoneExecutingLocked(r, inDestroying, inDestroying);
        ..........
    } else {
        ........
    }
}

主要針對處理onStartCommand的返回值

  • Service.START_STICKY_COMPATIBILITY+Service.START_STICKY
    1.找到startId對應(yīng)的StartItem,并移除(true)
    2.這個(gè)值置為false后,Service被殺掉還有機(jī)會(huì)重啟
    
  • Service.START_NOT_STICKY
    1.找到startId對應(yīng)的StartItem,并移除(true)
    2.服務(wù)kill掉,不再重啟
    
  • Service.START_REDELIVER_INTENT
    1.找到startId對應(yīng)的StartItem,不移除(false)
    2.重傳Intent。使用這個(gè)返回值時(shí),如果在執(zhí)行完onStartCommand后,服務(wù)被異常kill掉,系統(tǒng)會(huì)自動(dòng)重啟該服務(wù),并將Intent的值傳入。
    

隨后調(diào)用serviceDoneExecutingLocked()方法

private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
        boolean finishing) {
    ...............
    //ServiceRecord的一個(gè)命令執(zhí)行完畢,executeNesting -1
    //這些操作與前面提過的bumpServiceExecutingLocked函數(shù),一一對應(yīng)
    r.executeNesting--;

    //所有命令執(zhí)行完畢
    if (r.executeNesting <= 0) {
        if (r.app != null) {
            ..............
            r.app.execServicesFg = false;
            //ServiceRecord被從executingServices移除,處理超時(shí)消息時(shí),不會(huì)處理該Service
            r.app.executingServices.remove(r);

            //整個(gè)進(jìn)程所有的Service命令均處理完畢
            if (r.app.executingServices.size() == 0) {
                ............
                //移除time out消息
                mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
            } else if (r.executeFg) {
                // Need to re-evaluate whether the app still needs to be in the foreground.
                for (int i=r.app.executingServices.size()-1; i>=0; i--) {
                    if (r.app.executingServices.valueAt(i).executeFg) {
                        //有一個(gè)Service是前臺(tái)服務(wù),則app仍是前臺(tái)的
                        r.app.execServicesFg = true;
                        break;
                    }
                }
            }

            if (inDestroying) {
                .......
                mDestroyingServices.remove(r);
                r.bindings.clear();
            }
            mAm.updateOomAdjLocked(r.app);
        }

        r.executeFg = false;
        if (r.tracker != null) {
            //更新ServiceRecord的ServiceState
            r.tracker.setExecuting(false, mAm.mProcessStats.getMemFactorLocked(),
                    SystemClock.uptimeMillis());
            if (finishing) {
                r.tracker.clearCurrentOwner(r, false);
                r.tracker = null;
            }
        }

        if (finishing) {
            //若Service結(jié)束,將其從進(jìn)程對應(yīng)的記錄信息中移除
            if (r.app != null && !r.app.persistent) {
                r.app.services.remove(r);
                .............
            }
            r.app = null;
        }
    }
}

主要進(jìn)行對ServiceRecord的收尾工作

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容