Android -- 系統start Service流程簡要分析

Android -- 系統start Service流程簡要分析


Service是Android系統四大組件之一,它主要被用來在後臺處理一些耗時操作,也會被設計成對Client提供業務的服務模塊。Activity組件主要用來和用戶進行交互,Service組件則可以在後臺處理用戶觸發的一些請求操作,然後直接在Activity中展現請求結果。Activity和Service組件結合使用,能讓我們設計出模塊更清晰的應用。


Service有兩種啓動方式,一種是Start方式;一種是Bind方式。兩種方式的使用細節可以參照之前轉載的Service官方文檔。此次,我們就先分析start Service的系統流程,Binde Service的分析會在下一篇講述。


start Service,實際調用的是ContextImpl::startService()函數:

    @Override
    public ComponentName ContextImpl::startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, mUser);
    }

    private ComponentName ContextImpl::startServiceCommon(Intent service, UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread()/*AMS可以通過該ApplicationThread的Binder對象跟當前的應用進程通信*/, service, service.resolveTypeIfNeeded(
                            getContentResolver()), getOpPackageName(), user.getIdentifier());//進入AMS::startService()
            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());
                }
            }
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
參數mMainThread指向啓動該服務的應用進程,參數intent中一般會指定Service的class信息,或者服務的類型全限定名稱。之後,實際調用AMS::startService(),返回值是啓動的Service組件的名稱。我們進入AMS分析:

    @Override
    public ComponentName AMS::startService(IApplicationThread caller, Intent service,
            String resolvedType, String callingPackage, int userId)
            throws TransactionTooLargeException {
        enforceNotIsolatedCaller("startService");
        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        if (callingPackage == null) {
            throw new IllegalArgumentException("callingPackage cannot be null");
        }

        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
                "startService: " + service + " type=" + resolvedType);
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid, callingPackage, userId);//調用startServiceLocked()
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }
mService是AMS內部,類型爲ActiveService的實例對象;它是AMS啓動一個服務的輔助類,封裝了很多啓動Service的業務函數。收下判斷傳參的合法性,隨後調用ActiveService::startServiceLocked():

ComponentName ActiveService::startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
                + " type=" + resolvedType + " args=" + service.getExtras());

        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 != ProcessList.SCHED_GROUP_BACKGROUND;
        } else {
            callerFg = true;
        }

		//ServiceRecord是AMS中描述一個Service組件的類型
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false);//查找AMS中是否存在與參數service對應的ServiceRecord對象;如果不存在,則會通過PMS去獲取與service對應的Service組件信息,並封裝成ServiceLookupResult對象返回
        if (res == null) {
            return null;
        }
        if (res.record == null) {
            return new ComponentName("!", res.permission != null
                    ? res.permission : "private to package");
        }

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

        ...

        return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);//調用startServiceInnerLocked()去bring up一個Service
    }
一個服務的啓動必須由一個應用組件去觸發,所以啓動Service的應用組件進程是不能不存在的。接着根據參數,檢查AMS中是否已經這個服務的信息,即是否已經啓動過它;如果AMS不存在當前需要啓動的Service組件的信息,則去PMS查詢,因爲PMS會掃描所有Apk中的組件,根據參數從PMS查詢,就會得到當前需要啓動的Service對應的ServiceRecord對象,隨後將它封裝成ServiceLookupResult對象返回。


ServiceRecord是AMS用於管理Service的類型,每一個啓動的Service,在AMS中都以ServiceRecord對象描述;就如ActivityRecord一樣。


隨後調用ActiveService::startServiceInnerLocked():

    ComponentName ActiveService::startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
        ServiceState stracker = r.getTracker();
        if (stracker != null) {
            stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
        }
        r.callStart = false;
        synchronized (r.stats.getBatteryStats()) {
            r.stats.startRunningLocked();
        }
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);//調用bringUpServiceLocked()去啓動服務
        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 (DEBUG_DELAYED_SERVICE) {
                RuntimeException here = new RuntimeException("here");
                here.fillInStackTrace();
                Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here);
            } else if (DEBUG_DELAYED_STARTS) {
                Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r);
            }
            if (first) {
                smap.rescheduleDelayedStarts();
            }
        } else if (callerFg) {
            smap.ensureNotStartingBackground(r);
        }

        return r.name;
    }
主要處理就是調用bringUpServiceLocked()函數去啓動當前的服務:
  private String ActiveService::bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        //Slog.i(TAG, "Bring up service:");
        //r.dump("  ");

        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);//如果該Service已經啓動,則直接傳遞Service參數到進程的主線程中,此時會觸發調用onStartCommand();此次Service啓動已經完成
            return null;
        }

        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) {
            ...
        }

        // Make sure that the user who owns this service is started.  If not,
        // we don't want to allow it to run.
        if (!mAm.mUserController.hasStartedUserState(r.userId)) {
            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;
        }

        // Service is now being launched, its package can't be stopped.
        try {
            AppGlobals.getPackageManager().setPackageStoppedState(
                    r.packageName, false, r.userId);
        } catch (RemoteException e) {
        } catch (IllegalArgumentException e) {
            Slog.w(TAG, "Failed trying to unstop package "
                    + r.packageName + ": " + e);
        }

        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;//表示當前Service組件想要運行在其中的進程的名字
        ProcessRecord app;

        if (!isolated) {//isolated表示是否要求一個單獨的進程來運行服務;TRUE爲需要
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);//根據這個進程名字在AMS中查找該進程是否已經存在
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            if (app != null && app.thread != null) {//如果進程已經啓動,調用realStartServiceLocked()直接去啓動Service
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);//該service想運行的進程已經存在,此時直接去啓動該Service即可
                    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;//得到運行Service的單獨的進程,第一次爲null
        }

        // Not running -- get it started, and enqueue this service record
        // to be executed when the app comes up.
        if (app == null && !permissionsReviewRequired) {//如果該服務想要運行的進程還沒有啓動,則調用startProcessLocked()先去啓動進程,再去啓動Service
            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)) {//將當前需要啓動Service的ServcieRecord對象加入到mPendingServices
            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;
    }
與Activity的啓動類似,我們啓動一個Service時,也需要判斷當前Service是否已經啓動過。結合Service的生命週期,如果該Service已經啓動過,則直接去啓動Service即可(即調用Service::onStartCommnad()函數),但Service::onCreate()不會被調用,因爲onCreate()只在Service第一次創建時纔會被調用;如果Service的宿主進程不存在,我們就先爲該Service創建運行所需要的進程,然後再去啓動它。爲Service創建進程的流程與之前Activity啓動時創建進程的過程基本一致,此處就不再分析。


我們假設此時我們是第一次啓動該Service,此時需要爲它創建進程。結合代碼可知,在AMS發出了爲Service創建進程的請求之後,會將當前的Service添加到mPendingServices集合中,它保存了所有需要去的Service的ServiceRecord對象。在進程創建完畢後,AMS就會遍歷mPendingServices,去啓動服務。


由Activity的啓動過程分析可知,應用進程的入口函數是ActivityThread::main();應用進程啓動完畢後,就會給AMS發送一個通知,告知AMS進程已經創建好了,可以去啓動組件了。這個動作是在AMS::attachApplication(IApplicationThread)中處理的,參數是IApplicationThread類型;它用於AMS與當前應用進程的主線程交互。


集合之前分析Activity啓動部分的內容,最終是在AMS::attachApplicationLocked(IApplicationThread, int)中處理:

    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {

        // Find the application record that is being attached...  either via
        // the pid if we are running in multiple processes, or just pull the
        // next app record if we are emulating process with anonymous threads.
        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);//創建應用進程時,會將進程對象和pid保存到mPidsSelfLocked集合中,所以此時可以取出對應的進程對象
            }
        } else {
            app = null;
        }

        ...

        // If this application record is still attached to a previous
        // process, clean it up now.
        if (app.thread != null) {//如果app中已經有線程,說明app以前存在,現在是重啓;先清理掉這些信息
            handleAppDiedLocked(app, true, true);
        }

        // Tell the process all about itself.

        if (DEBUG_ALL) Slog.v(
                TAG, "Binding process pid " + pid + " to record " + app);

        final String processName = app.processName;
        try {
            AppDeathRecipient adr = new AppDeathRecipient(
                    app, pid, thread);//創建app死亡監聽對象
            thread.asBinder().linkToDeath(adr, 0);
            app.deathRecipient = adr;
        } catch (RemoteException e) {
            app.resetPackageList(mProcessStats);
            startProcessLocked(app, "link fail", processName);
            return false;
        }

        EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);

        app.makeActive(thread, mProcessStats);//會將創建的ActivityThread對應的ApplicationThread對象的Binder實例保存到該ProcessRecord對象的thread成員中,用以和該進程的主線程交互
        ...
        try {
            ...
            thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());//調用bindApplication()方法
            updateLruProcessLocked(app, false, null);
            app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
        } catch (Exception e) {
            // todo: Yikes!  What should we do?  For now we will try to
            // start another process, but that could easily get us in
            // an infinite loop of restarting processes...
            Slog.wtf(TAG, "Exception thrown during bind of " + app, e);

            app.resetPackageList(mProcessStats);
            app.unlinkDeathRecipient();
            startProcessLocked(app, "bind fail", processName);
            return false;
        }

        // Remove this record from the list of starting applications.
        mPersistentStartingProcesses.remove(app);
        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
                "Attach application locked removing on hold: " + app);
        mProcessesOnHold.remove(app);

        boolean badApp = false;
        boolean didSomething = false;

        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {//調用attachApplicationLocked(),去啓動當前Activity組件堆棧最頂端的Activity
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }

        // Find any services that should be running in this process...
        if (!badApp) {
            try {
                didSomething |= mServices.attachApplicationLocked(app, processName);//檢查mPendingServices中是否有Service組件需要在該新創建的進程中啓動;在此之前,我們會把需要啓動的Service組件添加到mPendingServices中
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            }
        }

        ...
        return true;
    }
與之前一樣,先得到爲當前Service啓動而創建的新應用進程的ProcessRecord對象;調用ActivityThread::bindApplication()綁定應用信息,創建Instrumentation、LoadedApk和Application等對象。接着調用ActiveService::boolean attachApplicationLocked(ProcessRecord proc, String processName)啓動服務:   

    boolean ActiveService::attachApplicationLocked(ProcessRecord proc, String processName)
            throws RemoteException {
        boolean didSomething = false;
        // Collect any services that are waiting for this process to come up.
        if (mPendingServices.size() > 0) {
            ServiceRecord sr = null;
            try {
                for (int i=0; i<mPendingServices.size(); i++) {//在mPendingServices中找到需要在當前新創建進程中運行的Service組件
                    sr = mPendingServices.get(i);
                    if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                            || !processName.equals(sr.processName))) {
                        continue;
                    }

                    mPendingServices.remove(i);//先從mPendingServices中移除它
                    i--;
                    proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
                            mAm.mProcessStats);
                    realStartServiceLocked(sr, proc, sr.createdFromFg);//調用realStartServiceLocked,在新創建的進程中啓動該Service
                    didSomething = true;
                    if (!isServiceNeeded(sr, false, false)) {
                        // We were waiting for this service to start, but it is actually no
                        // longer needed.  This could happen because bringDownServiceIfNeeded
                        // won't bring down a service that is pending...  so now the pending
                        // is done, so let's drop it.
                        bringDownServiceLocked(sr);
                    }
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception in new application when starting service "
                        + sr.shortName, e);
                throw e;
            }
        }
        // Also, if there are any services that are waiting to restart and
        // would run in this process, now is a good time to start them.  It would
        // be weird to bring up the process but arbitrarily not let the services
        // run at this point just because their restart time hasn't come up.
        if (mRestartingServices.size() > 0) {
            ServiceRecord sr;
            for (int i=0; i<mRestartingServices.size(); i++) {
                sr = mRestartingServices.get(i);
                if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                        || !processName.equals(sr.processName))) {
                    continue;
                }
                mAm.mHandler.removeCallbacks(sr.restarter);
                mAm.mHandler.post(sr.restarter);
            }
        }
        return didSomething;
    }
從mPendingServices中找到和當前進程匹配的ServiceRecord對象,即需要運行在當前新建進程的服務。調整mPendingServices集合,並調用ActiveService::realStartServiceLocked()去啓動Service。除此之外,還會處理需要重啓的Service。


分析ActiveService::realStartServiceLocked():

    private final void ActiveService::realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        if (app.thread == null) {
            throw new RemoteException();
        }
        if (DEBUG_MU)
            Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
                    + ", ProcessRecord.uid = " + app.uid);
        r.app = app;//將Service運行的進程信息保存到對應的ServiceRecord對象中
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

        final boolean newService = app.services.add(r);
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        mAm.updateOomAdjLocked();

        boolean created = false;
        try {
            if (LOG_SERVICE_START_STOP) {
                String nameTerm;
                int lastPeriod = r.shortName.lastIndexOf('.');
                nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
                EventLogTags.writeAmCreateService(
                        r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
            }
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startLaunchedLocked();
            }
            mAm.notifyPackageUse(r.serviceInfo.packageName,
                                 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);//調用scheduleCreateService在服務進程中創建Service對象,它會發送CREATE_SERVICE消息,最終在該進程的ActivityThread中處理會觸發調用onCreate()
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
            if (!created) {
                // Keep the executeNesting count accurate.
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);

                // Cleanup.
                if (newService) {
                    app.services.remove(r);
                    r.app = null;
                }

                // Retry.
                if (!inDestroying) {
                    scheduleServiceRestartLocked(r, false);
                }
            }
        }

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

        requestServiceBindingsLocked(r, execInFg);//處理bind service的情況:會將Service組件連接到請求綁定它的Activity中;內部會調用scheduleBindService()->handleBindService() -> onBind()被調用

        updateServiceClientActivitiesLocked(app, null, true);

        // If the service is in the started state, and there are no
        // pending arguments, then fake up one so its onStartCommand() will
        // be called.
        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    null, null));
        }

        sendServiceArgsLocked(r, execInFg, true);//會觸發調用Service::onStartCommand()

        ...
    }
首先,調用ActivityThread::scheduleCreateService()函數去創建當前啓動的Service;中間的Binder調用關係就不再描述,之前已有過類似分析。直接看它的處理:
    private void ActivityThread::handleCreateService(CreateServiceData data) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);//得到進程中加載的應用程序,以LoadedApk描述
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();//加載此時要啓動的Service類,並創建其Servcie實例
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to instantiate service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

			//爲該Service設置Context上下文環境
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            Application app = packageInfo.makeApplication(false, mInstrumentation);//創建一個Application對象,用來描述該Service所屬的應用程序;
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());//將一些信息與該Service組件進行綁定
            service.onCreate();//調用Service的onCreate()
            mServices.put(data.token, service);//token指向AMS中管理Service的ServiceRecord對象,保存到mService集合中
            try {
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);//通知AMS服務已經創建
            } 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);
            }
        }
    }
CreateServiceData封裝了AMS傳遞的參數信息。首先,是去加載這個需要啓動的Service。LoadedApk實例代表了一個被加載的應用信息,它與Application實例一樣,都是在進程創建後的bindApplication()調用中被創建的;且進程內部,所有組件都共用這些對象。加載Service類之後,便會爲Service設置當前Context信息;之後便將一些信息綁定到Service中,隨後就會觸發Service::onCreate()被調用,這時服務就已經創建完成,它的整個生命週期也就開始了。


再回到ActiveService::realStartServiceLocked()中,Service創建完畢後,start Service又會調用sendServiceArgsLocked()函數:

    private final void ActiveService::sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
            boolean oomAdjusted) throws TransactionTooLargeException {
        final int N = r.pendingStarts.size();
        if (N == 0) {
            return;
        }

        while (r.pendingStarts.size() > 0) {
            Exception caughtException = null;
            ServiceRecord.StartItem si = null;
            try {
                si = r.pendingStarts.remove(0);
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Sending arguments to: "
                        + r + " " + r.intent + " args=" + si.intent);
                if (si.intent == null && N > 1) {
                    // If somehow we got a dummy null intent in the middle,
                    // then skip it.  DO NOT skip a null intent when it is
                    // the only one in the list -- this is to support the
                    // onStartCommand(null) case.
                    continue;
                }
                si.deliveredTime = SystemClock.uptimeMillis();
                r.deliveredStarts.add(si);
                si.deliveryCount++;
                if (si.neededGrants != null) {
                    mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
                            si.getUriPermissionsLocked());
                }
                bumpServiceExecutingLocked(r, execInFg, "start");
                if (!oomAdjusted) {
                    oomAdjusted = true;
                    mAm.updateOomAdjLocked(r.app);
                }
                int flags = 0;
                if (si.deliveryCount > 1) {
                    flags |= Service.START_FLAG_RETRY;
                }
                if (si.doneExecutingCount > 0) {
                    flags |= Service.START_FLAG_REDELIVERY;
                }
                r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);//最終會調用Service::onStartCommand()
            } catch (TransactionTooLargeException e) {
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large: intent="
                        + si.intent);
                caughtException = e;
            } catch (RemoteException e) {
                // Remote process gone...  we'll let the normal cleanup take care of this.
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while sending args: " + r);
                caughtException = e;
            } catch (Exception e) {
                Slog.w(TAG, "Unexpected exception", e);
                caughtException = e;
            }

            if (caughtException != null) {
                // Keep nesting count correct
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                if (caughtException instanceof TransactionTooLargeException) {
                    throw (TransactionTooLargeException)caughtException;
                }
                break;
            }
        }
    }
如果這次Service start過程有參數(如參數intent中會封裝一些指令)需要投遞,則會觸發ActivityThread::scheduleServiceArgs()將參數投遞到Service中,觸發一些後臺執行流程:
    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) {
                    res = s.onStartCommand(data.args, data.flags, data.startId);//此處會調用Service::onStartCommand()函數
                } else {
                    s.onTaskRemoved(data.args);
                    res = Service.START_TASK_REMOVED_COMPLETE;
                }

                QueuedWork.waitToFinish();

                try {
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
                ensureJitEnabled();
            } catch (Exception e) {
                if (!mInstrumentation.onException(s, e)) {
                    throw new RuntimeException(
                            "Unable to start service " + s
                            + " with " + data.args + ": " + e.toString(), e);
                }
            }
        }
    }
ServiceArgsData封裝了AMS傳遞的參數信息,我們的分析場景中不會牽扯到設置taskRemoved,所以這時就會觸發調用Service::onStartCommand()調用,此時我們可以通過讀取參數,來啓動一些我們需要在該Service中執行的操作;至此,Service的有效生命週期就開始了。


回顧之前的分析,如果當時判斷該Service已經啓動過,即onCreate()已經調用過;則此時會直接調用sendServiceArgsLocked()函數,向Service中投遞傳入的參數,觸發Service::onStartCommand()調用,而不會再去觸發Service::onCreate()。這與我們所瞭解的Service的start生命週期是一致的。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章