startService源碼解讀

之前分析過startActivity方法的源碼,知道了startActivity的調用流程,大致的流程就是app通過Binder調用AMS的方法,然後AMS也通過Binder調用app的方法,app再回調我們的Activity的生命週期方法。AMS並不是直接保存我們的Activity的引用,而是通過每個Activity對應一個ActivityInfo信息在AMS保存。因爲Activityandroid 四大組件中最重要的也是最常用的,所以其調用流程比其他組件的流程複雜的多。

有興趣的可以查看startActivity源碼https://blog.csdn.net/Mr_lu_/article/details/80137617

瞭解了startActivity的調用流程後再看startService方法就感覺沒那麼困難了。

首先同樣查看ContextImplstartService方法

```

@Override

public ComponentName startService(Intent service) {

    warnIfCallingFromSystemProcess();

    return startServiceCommon(service, false, mUser);

}

```

內部調用了startServiceCommon方法,startServiceCommon調用了ActivityManagerstartService.

```

private ComponentName startServiceCommon(Intent service, boolean requireForeground,

        UserHandle user) {

    try {

        validateServiceIntent(service);

        service.prepareToLeaveProcess(this);

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

    }

}

```

內部有個驗證Intent的方法。在api21之後的開啓服務都要顯示聲明,不然就直接拋異常

```

private void validateServiceIntent(Intent service) {

    if (service.getComponent() == null && service.getPackage() == null) {

        if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {

            IllegalArgumentException ex = new IllegalArgumentException(

                    "Service Intent must be explicit: " + service);

            throw ex;

        } else {

            Log.w(TAG, "Implicit intents with startService are not safe: " + service

                    + " " + Debug.getCallers(2, 3));

        }

    }

}

```

 

我這裏看的是26版本的源碼,以前的源碼是ActivityManagerNative.getDefault的方法。再看ActivityManagerNative類時,發現已經標了棄用的標籤,其內部的getDefault方法也是調用getService方法

```

/**

 * {@hide}

 * @deprecated will be removed soon. See individual methods for alternatives.

 */

 

public abstract class ActivityManagerNative {

    /**

     * Retrieve the system's default/global activity manager.

     *

     * @deprecated use ActivityManager.getService instead.

     */

    static public IActivityManager getDefault() {

        return ActivityManager.getService();

    }

```

這個時候到AMS裏面的startService方法

```

@Override

public ComponentName startService(IApplicationThread caller, Intent service,

        String resolvedType, boolean requireForeground, String callingPackage, int userId)

        throws TransactionTooLargeException {

    enforceNotIsolatedCaller("startService");

        synchronized(this) {

        final int callingPid = Binder.getCallingPid();

        final int callingUid = Binder.getCallingUid();

        final long origId = Binder.clearCallingIdentity();

        ComponentName res;

        try {

            res = mServices.startServiceLocked(caller, service,

                    resolvedType, callingPid, callingUid,

                    requireForeground, callingPackage, userId);

        } finally {

            Binder.restoreCallingIdentity(origId);

        }

        return res;

    }

}

```

裏面調用了ActiviServicesstartServiceLocked方法

ActiviServices.java

```

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,

        int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)

        throws TransactionTooLargeException {

       final boolean callerFg;

    if (caller != null) {

        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);

                callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;

    } else {

        callerFg = true;

    }

 

    ServiceLookupResult res =

        retrieveServiceLocked(service, resolvedType, callingPackage,

                callingPid, callingUid, userId, true, callerFg, false);

    if (res == null) {

        return null;

    }

    if (res.record == null) {

        return new ComponentName("!", res.permission != null

                ? res.permission : "private to package");

    }

 

    ServiceRecord r = res.record;

 

    if (!mAm.mUserController.exists(r.userId)) {

        Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);

        return null;

    }

 

    // If this isn't a direct-to-foreground start, check our ability to kick off an

    // arbitrary service

    if (!r.startRequested && !fgRequired) {

        // Before going further -- if this app is not allowed to start services in the

        // background, then at this point we aren't going to let it period.

        final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,

                r.appInfo.targetSdkVersion, callingPid, false, false);

        if (allowed != ActivityManager.APP_START_MODE_NORMAL) {

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

                // In this case we are silently disabling the app, to disrupt as

                // little as possible existing apps.

                return null;

            }

            // This app knows it is in the new model where this operation is not

            // allowed, so tell it what has happened.

            UidRecord uidRec = mAm.mActiveUids.get(r.appInfo.uid);

            return new ComponentName("?", "app is in background uid " + uidRec);

        }

    }

 

    NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(

            callingUid, r.packageName, service, service.getFlags(), null, r.userId);

 

    // If permissions need a review before any of the app components can run,

    // we do not start the service and launch a review activity if the calling app

    // is in the foreground passing it a pending intent to start the service when

    // review is completed.

    if (mAm.mPermissionReviewRequired) {

        if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage,

                callingUid, service, callerFg, userId)) {

            return null;

        }

    }

 

    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;

    if (!callerFg && !fgRequired && r.app == null

            && mAm.mUserController.hasStartedUserState(r.userId)) {

        ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);

    ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);

    return cmp;

}

```

內部調用了startServiceInnerLocked方法

```

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

    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() + mAm.mConstants.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.rescheduleDelayedStartsLocked();

        }

    } else if (callerFg || r.fgRequired) {

        smap.ensureNotStartingBackgroundLocked(r);

    }

 

    return r.name;

}

```

調用了bringUpServieLocked方法,這個方法裏面有判斷service是否有start過,如果start了,則會跳過onCreate方法的回調

```

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,

        boolean whileRestarting, boolean permissionsReviewRequired)

        throws TransactionTooLargeException {

    //Slog.i(TAG, "Bring up service:");

    //r.dump("  ");

//Service還沒創建前,這裏的r.appnull

//在後面的realStartServiceLocked方法裏面設置的

    if (r.app != null && r.app.thread != null) {

        sendServiceArgsLocked(r, execInFg, false);

        return null;

    }

    // We are now bringing the service up, so no longer in the

    // restarting state.

    if (mRestartingServices.remove(r)) {

        clearRestartingIfNeededLocked(r);

    }

    // Make sure this service is no longer considered delayed, we are starting it now.

    if (r.delayed) {

        if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (bring up): " + r);

        getServiceMapLocked(r.userId).mDelayedStartList.remove(r);

        r.delayed = false;

    }

    // Make sure that the user who owns this service is started.  If not,

    // we don't want to allow it to run.

    if (!mAm.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;

    String hostingType = "service";

    ProcessRecord app;

 

    if (!isolated) {

        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);

        if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid

                    + " app=" + app);

        if (app != null && app.thread != null) {

            try {

                app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);

      //關鍵代碼,調用了realStartServiceLocked方法

                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;

        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;

        }

    }

    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;

}

```

最終調用了realStartServiceLocked方法

```

private final void realStartServiceLocked(ServiceRecord r,

        ProcessRecord app, boolean execInFg) throws RemoteException {

    if (app.thread == null) {

        throw new RemoteException();

    }

//設置 app屬性

    r.app = app;

    r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

 

    final boolean newService = app.services.add(r);

    bumpServiceExecutingLocked(r, execInFg, "create");

    mAm.updateLruProcessLocked(app, false, null);

    updateServiceForegroundLocked(r.app, /* oomAdj= */ false);

    mAm.updateOomAdjLocked();

 

    boolean created = false;

    try {

        mAm.notifyPackageUse(r.serviceInfo.packageName,

                             PackageManager.NOTIFY_PACKAGE_USE_SERVICE);

        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);

      //關鍵代碼,這裏通過Binder機制調用了ActivityThread的方法了  

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

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

 

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

    }

    //關鍵代碼,這裏後面會調用serviceonStart方法

    sendServiceArgsLocked(r, execInFg, true);

 

    if (r.delayed) {

        if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);

        getServiceMapLocked(r.userId).mDelayedStartList.remove(r);

        r.delayed = false;

    }

 

    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 (from start): " + r);

            stopServiceLocked(r);

        }

    }

}

```

ActivityThread.java

```

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

}

```

查看處理CREATE_SETVICE的消息的地方

```

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;

```

handleCreateService方法

在這裏終於回調我們的ServiceonCreate方法。先創建了一個Service實例,調用其attach方法。後調用了onCreate方法,然後放入了mServices集合中

```

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

    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 {

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

        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);

        context.setOuterContext(service);

        Application app = packageInfo.makeApplication(false, mInstrumentation);

        service.attach(context, this, data.info.name, data.token, app,

                ActivityManager.getService());

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

        }

    }

}

```

onCreate方法回調流程查看完畢,現在往後面看sendServiceArgsLocked方法

```

private final void realStartServiceLocked(ServiceRecord r,

        ProcessRecord app, boolean execInFg) throws RemoteException {

    

 

    boolean created = false;

    try {

        mAm.notifyPackageUse(r.serviceInfo.packageName,

                             PackageManager.NOTIFY_PACKAGE_USE_SERVICE);

        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);

      //關鍵代碼,這裏通過Binder機制調用了ActivityThread的方法了  

app.thread.scheduleCreateService(r, r.serviceInfo,

    //省略部分代碼....                   

//關鍵代碼,這裏後面會調用serviceonStart方法

    sendServiceArgsLocked(r, execInFg, true);

   }

```

sendServiceArgsLocked方法

```

private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,

        boolean oomAdjusted) throws TransactionTooLargeException {

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

        }

        mAm.grantEphemeralAccessLocked(r.userId, si.intent,

                r.appInfo.uid, UserHandle.getAppId(si.callingId));

        bumpServiceExecutingLocked(r, execInFg, "start");

        if (!oomAdjusted) {

            oomAdjusted = true;

            mAm.updateOomAdjLocked(r.app, true);

        }

        if (r.fgRequired && !r.fgWaiting) {

            if (!r.isForeground) {

                if (DEBUG_BACKGROUND_CHECK) {

                    Slog.i(TAG, "Launched service must call startForeground() within timeout: " + r);

                }

                scheduleServiceForegroundTransitionTimeoutLocked(r);

            } else {

                if (DEBUG_BACKGROUND_CHECK) {

                    Slog.i(TAG, "Service already foreground; no new timeout: " + r);

                }

                r.fgRequired = false;

            }

        }

        int flags = 0;

        if (si.deliveryCount > 1) {

            flags |= Service.START_FLAG_RETRY;

        }

        if (si.doneExecutingCount > 0) {

            flags |= Service.START_FLAG_REDELIVERY;

        }

        args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));

    }

 

    ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);

    slice.setInlineCountLimit(4);

    Exception caughtException = null;

    try {

//關鍵代碼,又調用了ActivityThread的方法

        r.app.thread.scheduleServiceArgs(r, slice);

    } catch (TransactionTooLargeException e) {

        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large for " + args.size()

                + " args, first: " + args.get(0).args);

        Slog.w(TAG, "Failed delivering service starts", e);

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

        Slog.w(TAG, "Failed delivering service starts", e);

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

        for (int i = 0; i < args.size(); i++) {

            serviceDoneExecutingLocked(r, inDestroying, inDestroying);

        }

        if (caughtException instanceof TransactionTooLargeException) {

            throw (TransactionTooLargeException)caughtException;

        }

    }

}

```

AMS調用了ActivityThreadscheduleSerivceArgs方法,發送了一個SERVICE_ARGS消息

```

public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {

    List<ServiceStartArgs> list = args.getList();

 

    for (int i = 0; i < list.size(); i++) {

        ServiceStartArgs ssa = list.get(i);

        ServiceArgsData s = new ServiceArgsData();

        s.token = token;

        s.taskRemoved = ssa.taskRemoved;

        s.startId = ssa.startId;

        s.flags = ssa.flags;

        s.args = ssa.args;

 

        sendMessage(H.SERVICE_ARGS, s);

    }

}

```

處理SERVICE_ARGS方法

```

case SERVICE_ARGS:

    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));

    handleServiceArgs((ServiceArgsData)msg.obj);

    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

    break;

```

調用handleServiceArgs方法。裏面回調了我們的ServiceonStartCommand方法

```

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

            } else {

                s.onTaskRemoved(data.args);

                res = Service.START_TASK_REMOVED_COMPLETE;

            }

 

            QueuedWork.waitToFinish();

 

            try {

                ActivityManager.getService().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);

            }

        }

    }

}

```

可以看到和AMS交互的調用過程和startActivity方法是一樣的,只不過Service不需要顯示給用戶看,因此流程比Activity簡單的多。

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