1. 程式人生 > >Android Service原理分析之startService(一)

Android Service原理分析之startService(一)

1. Service概述

Service作為Android四大元件之一,在開發過程中非常常用,它雖然沒有ui,但是同樣可以在後臺做很多重要的事情,我們平時使用啟動service主要通過startService以及bindService來啟動service以便已經相關操作。本文將介紹startService的原理,後續將分別介紹bindService的原理,以及在Android O上對service的新增限制管控。
注:本文基於Android 8.1
2. Service分類

    從啟動方式上,可以分別通過startService以及bindService啟動,兩者之間最重要的區別在於bindService可以建立binder連線,更加方便通訊。
    從執行方式上,可以分為前臺service(foregroundService,下面簡稱fg-service)與後臺service,兩者的區別在於有前臺service的程序對應的優先順序會更高,不容易被系統清理掉,但是前臺service需要在通知欄裡面顯示一個常駐的通知。

3. startService時序圖

startService的啟動大致分為三種情況:

    對應程序不存在(先啟動程序然後啟動service並執行onCreate和onStartCommand)
    程序存在但是service不存在(啟動service並執行onCreate和onStartCommand)
    程序和service都存在(只執行onStartCommand)

上面的時序圖主要針對程序存在,但是service不存在的情況,其他兩種在主要流程上沒有太大區別,關鍵在於其中有一些特殊判斷,在文章過程中也會提到。
4. 原始碼解析
4.1 ContextImpl.startService

    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }
    
        public ComponentName startForegroundService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, true, mUser);
    }
    // 最終的入口都在這個方法中
    // foreground service只是傳參requireForeground為true,普通service為false
    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            // binder call至ams
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
            if (cn != null) {
                if (cn.getPackageName().equals("!")) {
                    throw new SecurityException(
                            "Not allowed to start service " + service
                            + " without permission " + cn.getClassName());
                } else if (cn.getPackageName().equals("!!")) {
                    throw new SecurityException(
                            "Unable to start service " + service
                            + ": " + cn.getClassName());
                } else if (cn.getPackageName().equals("?")) {
                    throw new IllegalStateException(
                            "Not allowed to start service " + service + ": " + cn.getClassName());
                }
            }
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

   

最終通過startServiceCommon呼叫至ams,注意這裡返回值有進行特殊處理,然後丟擲了一些異常,主要返回值的component的packageName有"!","!!","?"三種,後面在介紹原始碼過程中可以看到具體是哪裡會返回這些異常。
"!":許可權校驗沒通過,不允許啟動
"!!":無法啟動
"?":不允許啟動
4.2 ActivityManagerService.startService

    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
        enforceNotIsolatedCaller("startService");
        // 進行一些簡單的校驗
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }
        // callingPackage不能為空
        if (callingPackage == null) {
            throw new IllegalArgumentException("callingPackage cannot be null");
        }
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
                // mService正是ActiveServices物件
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }


這塊只是簡單校驗之後,就呼叫到了ActiveServices.startServiceLocked。
引數解析:
caller:發起startService的程序對應的IApplicationThread物件
service:要啟動的service的intent
resolvedType:service型別,啟動的時候可以設定data已經schema等
requireForeground:是否發起啟動foregroundService
callingPackage:發起startService的程序的packageName
userId:當前使用者id
4.3 ActiveServices.startServiceLocked

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        final boolean callerFg;
        // 獲取發起binder call的caller程序,如果不存在則拋異常
        if (caller != null) {
            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
            if (callerApp == null) {
                throw new SecurityException(
                        "Unable to find app for caller " + caller
                        + " (pid=" + callingPid
                        + ") when starting service " + service);
            }
            // 根據當前這個程序所處的排程環境判斷是前臺還是後臺
            callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
        } else {
            callerFg = true;
        }
        // 拿到要啟動的service的資訊
        // 主要是從packageManagerService中查詢,然後快取起來
        // 其中還進行了一些許可權的校驗,4.4小節詳細介紹
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false);
        // 沒有查到要啟動的service,直接return了
        if (res == null) {
            return null;
        }
        // 這裡就能看到前面提到的返回component的package為“!”的情況了
        // 原因是沒有對應的servicerecord,沒有的原因會在下面4.4小節中進一步介紹
        if (res.record == null) {
            return new ComponentName("!", res.permission != null
                    ? res.permission : "private to package");
        }
        // 拿到要啟動的serviceRecord,這個就是我們在manifest中註冊的service元件對應在系統中封裝起來的物件
        ServiceRecord r = res.record;
        // 判斷user是否存在
        if (!mAm.mUserController.exists(r.userId)) {
            return null;
        }
        // 是否要啟動fg-service
        if (!r.startRequested && !fgRequired) {
            // 這塊是校驗如果要啟動的service是一個後臺service
            // 那麼需要看是否擁有後臺啟動的許可權,不允許就無法後臺啟動
            final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
                    r.appInfo.targetSdkVersion, callingPid, false, false);
            if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                // 新升級到O的應用可能會遇到這問題,因為不允許後臺情況下的app啟動後臺service
                Slog.w(TAG, "Background start not allowed: service "
                        + service + " to " + r.name.flattenToShortString()
                        + " from pid=" + callingPid + " uid=" + callingUid
                        + " pkg=" + callingPackage);
                if (allowed == ActivityManager.APP_START_MODE_DELAYED) {
                    return null;
                }
                // 不允許啟動,此處封裝component的packageName為“?”,對應前面提到的,會丟擲相關異常
                UidRecord uidRec = mAm.mActiveUids.get(r.appInfo.uid);
                return new ComponentName("?", "app is in background uid " + uidRec);
            }
        }
        ...
        // 如果這個service正在排程重啟,那麼取消重啟,因為馬上要啟動了
        if (unscheduleServiceRestartLocked(r, callingUid, false)) {
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r);
        }
        r.lastActivity = SystemClock.uptimeMillis();
        r.startRequested = true;
        r.delayedStop = false;
        r.fgRequired = fgRequired;
        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                service, neededGrants, callingUid));
        final ServiceMap smap = getServiceMapLocked(r.userId);
        boolean addToStarting = false;
        // 如果呼叫者在後臺,且不是啟動的前臺service,判斷是否需要delay
        if (!callerFg && !fgRequired && r.app == null
                && mAm.mUserController.hasStartedUserState(r.userId)) {
            ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
            if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
                if (r.delayed) {
                    return r.name;
                }
                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;
            }
        }
        ...
        // 準備啟動service了
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }

 
小結:

    校驗caller
    拿到serviceRecord,進一步校驗
    校驗是否有可以後臺啟動
    是否需要delay
    startServiceInnerLocked

4.4 ActiveServices.retrieveServiceLocked

    private ServiceLookupResult retrieveServiceLocked(Intent service,
            String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
            boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) {
        ServiceRecord r = null;
        // 獲取user
        userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
                ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);
        // 根據userId獲取ServiceMap
        // 有一個user為key,ServiceMap為v的map,儲存了所有的service資訊
        // 每個user對應一個
        // ServiceMap是一個handler物件,用的looper是ActivityManager執行緒
        // 其中主要儲存的都是存放service的各map,以不同的方式儲存的Servicerecord
        ServiceMap smap = getServiceMapLocked(userId);
        final ComponentName comp = service.getComponent();
        // 通過component從ServiceMap查詢
        if (comp != null) {
            r = smap.mServicesByName.get(comp);
        }
        ...
        if (r == null) {
            try {
                // 如果沒能查到,那需要從PackageManager去查詢了
                ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
                        resolvedType, ActivityManagerService.STOCK_PM_FLAGS
                                | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                        userId, callingUid);
                ServiceInfo sInfo =
                    rInfo != null ? rInfo.serviceInfo : null;
                if (sInfo == null) {
                    Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId +
                          ": not found");
                    return null;
                }
                // 封裝ComponentName
                ComponentName name = new ComponentName(
                        sInfo.applicationInfo.packageName, sInfo.name);
                // FLAG_EXTERNAL_SERVICE型別的service必須有人去bind
                // 這塊就不貼具體實現了,startService過程中這個邏輯不會走到
                ...

                if (userId > 0) {
                    if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
                            sInfo.name, sInfo.flags)
                            && mAm.isValidSingletonCall(callingUid, sInfo.applicationInfo.uid)) {
                        userId = 0;
                        smap = getServiceMapLocked(0);
                    }
                    sInfo = new ServiceInfo(sInfo);
                    sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
                }
                r = smap.mServicesByName.get(name);
                // 拿到ServiceRecord,如果沒有需要新建
                if (r == null && createIfNeeded) {
                    ...
                    // 這塊主要就是ServiceRecord物件建立以及放入ServiceMap中
                }
            }
        }
        if (r != null) {
            ...
            // 這塊主要是做一些許可權校驗,包括export(manifest中指定是否允許其他程序啟動)
            // 以及自己指定的service許可權
            if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid,
                    resolvedType, r.appInfo)) {
                return null;
            }
            // 查詢成功
            return new ServiceLookupResult(r, null);
        }
        // 沒有查詢成功返回null
        // 上面一節有提到,如果這裡返回null則會再進一步返回到ContextImpl中丟擲異常
        return null;
    }

   

這塊做了兩件事:

    查詢ServiceRecord,如果不存在則建立
    許可權檢查

4.5 ActiveServices.startServiceInnerLocked

    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
        ...
        r.callStart = false;
        synchronized (r.stats.getBatteryStats()) {
            r.stats.startRunningLocked();
        }
        // bringUpServiceLocked這個是啟動service的核心
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
        if (error != null) {
            return new ComponentName("!!", error);
        }
        // 下面主要是進行delay
        if (r.startRequested && addToStarting) {
            boolean first = smap.mStartingBackground.size() == 0;
            smap.mStartingBackground.add(r);
            r.startingBgTimeout = SystemClock.uptimeMillis() + mAm.mConstants.BG_START_TIMEOUT;
            if (first) {
                smap.rescheduleDelayedStartsLocked();
            }
        } else if (callerFg || r.fgRequired) {
            smap.ensureNotStartingBackgroundLocked(r);
        }
        return r.name;
    }

   
這裡沒做什麼事,主要實現都在bringUpServiceLocked
4.6 ActiveServices.bringUpServiceLocked

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        // 從上面的時序圖可以知道sendServiceArgsLocked中主要是要排程執行service的onStartCommand
        // 這裡怎麼直接就執行了呢?
        // 原因在於判斷條件,對於沒有執行onCreate的service,r.app是null,所以不會執行這個流程
        // 也就是沒有啟動過的service不會走這裡,只有啟動過的service才會
        // 所以對於已經啟動過的service,重複startService只會走onStartCommand,就是因為這裡,然後return
        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
        // 如果不是排程重啟,且已經在restart列表中,return
        // 只有排程重啟的地方呼叫過來whileRestarting為true
        if (!whileRestarting && mRestartingServices.contains(r)) {
            return null;
        }
        // 從restart中移除,因為馬上要執行啟動了
        if (mRestartingServices.remove(r)) {
            clearRestartingIfNeededLocked(r);
        }
        ...
        // 這中間是一些簡單的狀態判斷,有興趣可以自己檢視原始碼

        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;
        if (!isolated) {
            // 程序存在那就直接走真正啟動service的邏輯了
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            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);
                }
            }
        } else {
            // isolated程序處理,O上webview程序屬於這種型別,加以特殊處理,標記hostingType
            // hostingType主要用於啟動程序的時候
            app = r.isolatedProc;
            if (WebViewZygote.isMultiprocessEnabled()
                    && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
                hostingType = "webview_service";
            }
        }

        // 程序不存在,那還得先啟動程序
        if (app == null && !permissionsReviewRequired) {
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, 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;
            }
        }
        ...
        // 因為要啟動程序,所以需要記一下這次啟動程序的原因是因為需要啟動這個service
        // 等到程序啟動成功之後,在程序attachApplicationLocked的時候會再去啟動這個serivice
        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }
        return null;
    }

   

小結:

    如果service已經存在那麼直接排程sendServiceArgsLocked(將會執行service.onStartCommand)
    處理service重啟相關資料結構
    程序存在,則realStartServiceLocked
    程序不存在則先啟動程序並把service儲存在mPendingServices

4.7 ActiveServices.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);
        // 這裡主要是計算設定service的timeout
        // 因為service的執行是計算在ANR機制中的,這裡就是開始計時
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        // 如果是前臺service需要更新並記錄當前前臺serivice的狀態
        updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
        // 更新程序優先順序
        mAm.updateOomAdjLocked();

        boolean created = false;
        try {
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startLaunchedLocked();
            }
            mAm.notifyPackageUse(r.serviceInfo.packageName,
                                 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
            // 設定process的狀態為start service
            // 這樣在更新程序優先順序的時候會有對應的處理,其實就是會提升優先順序
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            // 到APP的程序中了,執行IApplicationThread.scheduleCreateService
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            // 發現執行過程中程序掛掉了,需要處理後事,主要是程序中一些狀態的清除
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
            if (!created) {
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                if (newService) {
                    app.services.remove(r);
                    r.app = null;
                }
                if (!inDestroying) {
                    scheduleServiceRestartLocked(r, false);
                }
            }
        }

        if (r.whitelistManager) {
            app.whitelistManager = true;
        }

        requestServiceBindingsLocked(r, execInFg);
        // 更新繫結的activity,這塊主要針對bindService
        updateServiceClientActivitiesLocked(app, null, true);
        // 如果需要執行service的start則加入到pendingStarts
        // r.startRequested在startServiceLocked就標記了
        // 且startServiceLocked時就已經加入到pendingStarts
        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    null, null, 0));
        }
        // 這裡將會執行service.onStartCommand
        sendServiceArgsLocked(r, execInFg, true);
        ...
        // delay相關
    }

   

小結:

    開始計算service “create”的ANR計時
    呼叫到app程序建立並執行service的onCreate
    sendServiceArgsLocked

4.8 ActiveServices.sendServiceArgsLocked

    private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
            boolean oomAdjusted) throws TransactionTooLargeException {
        // startServiceLocked時已經加入到pendingStarts
        final int N = r.pendingStarts.size();
        if (N == 0) {
            return;
        }
        ArrayList<ServiceStartArgs> args = new ArrayList<>();
        while (r.pendingStarts.size() > 0) {
            ServiceRecord.StartItem si = r.pendingStarts.remove(0);
            if (si.intent == null && N > 1) {
                continue;
            }
            si.deliveredTime = SystemClock.uptimeMillis();
            r.deliveredStarts.add(si);
            si.deliveryCount++;
            if (si.neededGrants != null) {
                mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
                        si.getUriPermissionsLocked());
            }
            mAm.grantEphemeralAccessLocked(r.userId, si.intent,
                    r.appInfo.uid, UserHandle.getAppId(si.callingId));
            // 再次開始ANR的計時,不過此處計時是“start”
            bumpServiceExecutingLocked(r, execInFg, "start");
            if (!oomAdjusted) {
                oomAdjusted = true;
                mAm.updateOomAdjLocked(r.app, true);
            }
            //  O上開始,呼叫startForegroundService需要5s內呼叫startForeground
            // 如果呼叫startForegroundService就處於r.fgRequired
            // 此處是如果發現需要呼叫startForeground但是沒調,則認為超時了
            if (r.fgRequired && !r.fgWaiting) {
                if (!r.isForeground) {
                    scheduleServiceForegroundTransitionTimeoutLocked(r);
                } else {
                    r.fgRequired = false;
                }
            }
            int flags = 0;
            if (si.deliveryCount > 1) {
                flags |= Service.START_FLAG_RETRY;
            }
            if (si.doneExecutingCount > 0) {
                flags |= Service.START_FLAG_REDELIVERY;
            }
            // 建立ServiceStartArgs
            args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));
        }

        ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
        slice.setInlineCountLimit(4);
        Exception caughtException = null;
        try {
            // 排程到APP程序執行scheduleServiceArgs(將會執行service.onStartCommand)
            r.app.thread.scheduleServiceArgs(r, slice);
        } catch (TransactionTooLargeException e) {
            scheduleServiceArgs
            ...
        }
        // 如果發生了異常需要停掉service
        if (caughtException != null) {
            final boolean inDestroying = mDestroyingServices.contains(r);
            for (int i = 0; i < args.size(); i++) {
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
            }
            if (caughtException instanceof TransactionTooLargeException) {
                throw (TransactionTooLargeException)caughtException;
            }
        }
    }

   

小結:

    開始service“start”的ANR計時
    建立ServiceStartArgs
    排程到app程序執行service的onStartCommand

4.9 ActivityThread.handleCreateService

    public final void scheduleCreateService(IBinder token,
           ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
       updateProcessState(processState, false);
       CreateServiceData s = new CreateServiceData();
       s.token = token;
       s.info = info;
       s.compatInfo = compatInfo;
       sendMessage(H.CREATE_SERVICE, s);
    }
    
public void handleMessage(Message msg) {
switch (msg.what) {
    ...
    case CREATE_SERVICE:
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
    handleCreateService((CreateServiceData)msg.obj);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;
    ...
}    

    private void handleCreateService(CreateServiceData data) {
        unscheduleGcIdler();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to instantiate service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }

        try {
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
            // 建立application
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            // 執行service attach
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            // 執行service的onCreate
            service.onCreate();
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }
    


app程序中binder執行緒排程過來之後,傳送訊息到主執行緒執行handleCreateService,在handleCreateService中終於看到了我們熟悉的onCreate了
處理完了service的生命週期,還要告訴ams,我處理完了,因為那邊還在進行service的ANR計時呢
4.10 ActivityThread.handleServiceArgs

    private void handleServiceArgs(ServiceArgsData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                if (data.args != null) {
                    data.args.setExtrasClassLoader(s.getClassLoader());
                    data.args.prepareToEnterProcess();
                }
                int res;
                if (!data.taskRemoved) {
                    // 執行service的onStartCommand方法
                    res = s.onStartCommand(data.args, data.flags, data.startId);
                } else {
                    s.onTaskRemoved(data.args);
                    res = Service.START_TASK_REMOVED_COMPLETE;
                }
                // 這裡在前面講解SharedPreferences的時候有提到,是在等待sp的任務寫入完成
                QueuedWork.waitToFinish();
                try {
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
                ensureJitEnabled();