Android10.0 Service启动源码解析

本文出自门心叼龙的博客,属于原创类容,转载请注明出处。

Service的启动流程的还是比较简单的,不像Activity那么复杂,相关联的类和方法都少了很多,不像Activity启动流程里面走着走着就会迷失方向,源码分析这是加强Android内功修炼的必修课,分析了几个流程之后,你就会觉得也不过如此,因为他们的套路都是一样的,大体的实现思想都是相通的,只是具体的代码实现不同罢了。

在上一篇文章我们主要分析了Android10.0 Activity的启动过程,今天我们主要来探索Service的启动过程,本来打算先从5.0开始,然后在分析最新版10.0的启动过程,结果让我失望了,10.0的启动过程和5.0的是方法调用链是一样的,只是有些方法的代码逻辑有些小的改动,它不像Activity的启动流程变化那么大,这说明当时Service启动这块的代码逻辑写的还是非常不错的,Android已经迭代到10了经历了那么版本,这块的代码还是那么的完美稳定,没有什么需要大的改造的地方,10.0中有些小变化会在下面的详解过程会提到,既然5.0和10.0差别不大,索性就以5.0作为研究版本写了这篇文章。

Service是Android四大组件中排行老二,地位仅次于Activity,Activity位于前台向用户展示界面;Service位于后台不可见,但是它承担了大部分的的数据处理工作,主要为其他组件提供后台服务,监控其他组件的运行状态。

Activity中的流程

Service的启动是从Activity的startService方法开始的,这个方法是从他的父类ContextWrapper继承而来的,下面这是Activity的继承关系图:


在这里插入图片描述

从上图我们很清晰的看到,Activity继承了ContextThemeWraper,而ContextThemeWraper又继承了ContextWrawper,startService方法正是ContextWraper所提供的,如下所示:


在这里插入图片描述

ContextWrapter不但提供了开启服务的startService的方法,而且还提供了停止服务的stopService方法、绑定服务的bindService方法、Activity启动的startActivity方法、广播注册的registerReceiver方法、广播发送的sendBroadcast方法等,Context从英文翻译过来是环境,上下文的意思,它在整个Android操作系统中有着举足轻重的作用,在我们平时的应用开发过程中无处不在的Context,几乎随处可见,因为他是维持各大组件正常工作的核心功能类,它提供了一些系统级别的最基本的操作。

从上面代码的515行,我们看到ContextWraper的startService方法内部调用了mBase的startService方法,mBase的类型是ContextImpl, Activity在创建的时候通过attach方法给mBase变量赋值的,具体代码如下:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
       ...

        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            //注释1
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

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

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) {
                //注释2
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                //注释3
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.voiceInteractor);

                if (customIntent != null) {
                    activity.mIntent = customIntent;c
                }
              ...
            

ActivityThread的performLaunchActivity方法是不是很熟悉,这是前面文章Activity启动流程中所讲到最重要的一个方法,Activity的创建,Application的创建都是有它来完成的,注释1处通过反射创建了一个activity,注释2处是上下文appContext的创建,注释3 activity调用了attach方法给mBase变量赋值。

注释2处appContext对象是由createBaseContextForActivity创建的,具体代码实现如下:

private Context createBaseContextForActivity(ActivityClientRecord r,
            final Activity activity) {
        //注释1    
        ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
        appContext.setOuterContext(activity);
        Context baseContext = appContext;

        final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
        try {
            IActivityContainer container =
                    ActivityManagerNative.getDefault().getEnclosingActivityContainer(r.token);
            final int displayId =
                    container == null ? Display.DEFAULT_DISPLAY : container.getDisplayId();
            if (displayId > Display.DEFAULT_DISPLAY) {
                Display display = dm.getRealDisplay(displayId, r.token);
                baseContext = appContext.createDisplayContext(display);
            }
        } catch (RemoteException e) {
        }
        ...
        return baseContext;

在以上代码的注释1处很清楚的看到 appContext 的类型就是ContextImpl,并且是由它的静态方法 createActivityContext创建的,创建完毕通过activity的attach方法给mBase赋值了。通过这些探索就是为了证实mBase的实现就是ContextImpl,现在我回到之前的启动流程mBase.startServcie(service)这一行,其实就是调用了ContextImpl的startService方法,我们继续看该方法的具体实现:

@Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, mUser);
    }
    private ComponentName startServiceCommon(Intent service, UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess();
            //注释1
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread(), service,
                service.resolveTypeIfNeeded(getContentResolver()), 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());
                }
            }
            return cn;
        } catch (RemoteException e) {
            return null;
        }
    }

ContextImpl中startService方法会调用startServiceCommon方法,而startServiceCommon方法又会在注释1处调用ActivityManagerNative.getDefault()对象来启动一个服务,注意了这块的逻辑在Android10.0中是这式样的:

  ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());

很显然获取服务这块有所变化,在5.0中是由ActivityManagerNative来完成的,在10.0中这个工作交给ActivityManager了,5.0和10.0最主要的变化就在这里,但是他们最终的逻辑都是一样的,最后都走ActivityManagerService的startService方法,此外,其他的逻辑基本没有什么大的改变,我们还是以5.0为研究版本,继续往下走。

在前面的分析Activity启动的时候我们知道ActivityManagerNative.getDefault()对象其实就是ActivityManagerService,此时Service的启动流程直接就走到了ActivityManagerService中,想必很多人还是不很清楚方法的调用流程怎么就过渡到了ActivityManagerService,其实这里用到了Android跨进程通信技术Binder,下面我们看看他的工作原理,搞清楚是怎么由ActivityManagerNative.getDefault()对象的startService方法过渡到ActivityManagerService的startService方法,ActivityManagerNative的getDefault方法的代码实现如下:

static public IActivityManager getDefault() {
       return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        //注释1
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            //注释2
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };   
static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            //注释3
            return in;
        }
        //注释4
        return new ActivityManagerProxy(obj);
    }     

ActivityManagerNative中的getDefault方法很简单只有一行gDefault.get,而gDefault就是Singleton,他是一个单例对象,当调用它的get方法的时候就会执行注释1处onCreate方法,首先通过ServiceManager的getService方法获取了一个Binder,然后在注释2处把这个binder交给了asInterface方法、该方法的主要作用是将服务端binder对象转换为客户端所需要的IActivityManager 接口对象,如果在客户端和服务端在同一进程就会返回本地接口IActivityManager的实现对象,否则就会返回一个ActivityManagerProxy类型的代理对象,很显然该方法最后直接返回的就是一个代理对象ActivityManagerProxy,因为此时需要进行跨进程调用。因此ActivityManagerNative.getDefault()最终获取的是一个代理对象ActivityManagerProxy,紧着会调用这个对象ActivityManagerProxy的startService方法,方法实现如下:

 public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, int userId) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        service.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeInt(userId);
        //注释1
        mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        ComponentName res = ComponentName.readFromParcel(reply);
        data.recycle();
        reply.recycle();
        return res;
    }

startService方法会把传递过来的参数进行用Parcel 进行封装,然后在注释1处会调用mRemote的transact方法进行远程方法调用,mRemote对象就是我们前面代码注释4处实例化ActivityManagerProxy对象的时候通过构造方法传递给它的服务端Binder对象。此时客户端会处于挂起状态,ActivityManagerNative的实现类ActivityManagerService的onTransact方法响应,该方法的具体实现如下:

    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
         case START_SERVICE_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            Intent service = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            int userId = data.readInt();
            //注释1
            ComponentName cn = startService(app, service, resolvedType, userId);
            reply.writeNoException();
            ComponentName.writeToParcel(cn, reply);
            return true;
        }

onTransact方法响应后会从参数data中解析startService方法所需要的参数,然后在注释1处会调用它的startService方法进行启动服务的操作,至此启动服务的操作由客户端进程切换到了服务端进程,实现了方法的跨进行调用,接下来的我们看ActivityManagerService的startService的方法实现,方法实现如下:

ActivityManagerService的流程

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

        if (DEBUG_SERVICE)
            Slog.v(TAG, "startService: " + service + " type=" + resolvedType);
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            //注释1
            ComponentName res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

该方法也不长,在最后ActivityManagerService会通过mServices来完成后续的启动操作,mServices的类型是ActiveServices,他是辅助ActivityManagerService进行Service管理的辅助类,包括Service的启动,绑定,停止等。在startService方法的尾部会调用ActiveServices的startServiceLocked方法,该方法的实现如下:

ActiveServices的流程

ComponentName startServiceLocked(IApplicationThread caller,
            Intent service, String resolvedType,
            int callingPid, int callingUid, int userId) {
        ....
        ServiceRecord r = res.record;

        if (!mAm.getUserManagerLocked().exists(r.userId)) {
            Slog.d(TAG, "Trying to start service with non-existent user! " + r.userId);
            return null;
        }

        NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
                callingUid, r.packageName, service, service.getFlags(), null, r.userId);
        if (unscheduleServiceRestartLocked(r, callingUid, false)) {
            if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
        }
        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);
        boolean addToStarting = false;
        ...
        return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    }

在 ActiveServices的startServiceLocked方法的最后会把后续的启动工作交给startServiceInnerLocked方法来处理,它的代码实现如下所示:

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,
            ServiceRecord r, boolean callerFg, boolean addToStarting) {
        ProcessStats.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();
        }
        //注释1
        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 (DEBUG_DELAYED_SERVICE) {
                RuntimeException here = new RuntimeException("here");
                here.fillInStackTrace();
                Slog.v(TAG, "Starting background (first=" + first + "): " + r, here);
            } else if (DEBUG_DELAYED_STARTS) {
                Slog.v(TAG, "Starting background (first=" + first + "): " + r);
            }
            if (first) {
                smap.rescheduleDelayedStarts();
            }
        } else if (callerFg) {
            smap.ensureNotStartingBackground(r);
        }

        return r.name;
    }   

在上述代码的注释1处会继续调用bringUpServiceLocked方法,它的源码如下:

private final String bringUpServiceLocked(ServiceRecord r,
            int intentFlags, boolean execInFg, boolean whileRestarting) {
   
        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        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);
                    //注释1
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } 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;
        }
    ...
        return null;
    }

在bringUpServiceLocked方法的注释1处会调用realStartServiceLocked方法,从名字上看来该方法应该会最终完成服务的启动工作,它的具体实现如下:

 private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        ...
        boolean created = false;
        try {
            String nameTerm;
            int lastPeriod = r.shortName.lastIndexOf('.');
            nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
            if (LOG_SERVICE_START_STOP) {
                EventLogTags.writeAmCreateService(
                        r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
            }
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startLaunchedLocked();
            }
            mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            //注释1
            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);
        } finally {
            if (!created) {
                app.services.remove(r);
                r.app = null;
                scheduleServiceRestartLocked(r, false);
                return;
            }
        }
        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));
        }
        //注释2
        sendServiceArgsLocked(r, execInFg, true);
        ...
    }

在realStartServiceLocked方法中首先会调用注释1处app.thread对象的scheduleCreateService方法来完成Servic的创建和onCreate方法的调用,然后在注释2处会调用sendServiceArgsLocked方法完成后续的处理工作,如onStartCommand方法的执行,在分析Activity启动流程的时候我们知道app.thread对象就是ApplicationThread,他是ActivityThread的一个内部类,其本质也是一个Bidner,因此scheduleCreateService方法调用后,启动Service的流程就由服务端进程切换到了客户端进程,接下来我们看ApplicationThread的scheduleCreateService方法实现:

ActivityThread的流程

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

ApplicationThread的scheduleCreateService方法的内部实现很简单,就发送了一个CREATE_SERVICE类型的消息,这个消息会被ActivityThread的mH消息处理器所接收,之后会调用ActivityThread的方法handleCreateService进行处理,该方法的实现如下:

 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();
            //注释1
            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);
            //注释2
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
            //注释3
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //注释4
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());
            //注释5
            service.onCreate();
            mServices.put(data.token, service);
            try {
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, 0, 0, 0);
            } catch (RemoteException e) {
                // nothing to do.
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

在handleCreateService方法中代码还是很精炼的,主要完成了以下几个工作:

  • 1.在注释1处通过反射完成了Service的创建
  • 2.在注释2处创建了上下文对象Context
  • 3.在注释3处创建了Application对象,当然该对象只有一个,如果没有的话会创建,否则就直接返回一个已创建的Application
  • 4.在注释4处完成了Service的挂载操作,初始化了一些变量,如context等
  • 5.在注释5处完成了Service的onCreate方法的回调
    Service的onCreate方法的执行也就意味着Service已经被启动了,启动完成之后还要调用ActiveServcie的sendServiceArgsLocked方法来完成Service的onStartCommand方法的回调,该方法的代码实现如下:
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
            boolean oomAdjusted) {
        final int N = r.pendingStarts.size();
        if (N == 0) {
            return;
        }

        while (r.pendingStarts.size() > 0) {
            try {
                ServiceRecord.StartItem si = r.pendingStarts.remove(0);
                if (DEBUG_SERVICE) Slog.v(TAG, "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;
                }
                //注释1
                r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
            } catch (RemoteException e) {
                // Remote process gone...  we'll let the normal cleanup take
                // care of this.
                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
                break;
            } catch (Exception e) {
                Slog.w(TAG, "Unexpected exception", e);
                break;
            }
        }
    }

在注释1处会调用r.app.thread对象的scheduleServiceArgs方法,从此调用流程再次切换到ActivityThrad的内部类对象ApplicationThread的scheduleServiceArgs方法,下面我们看该方法的具体实现:

 public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
            int flags ,Intent args) {
            ServiceArgsData s = new ServiceArgsData();
            s.token = token;
            s.taskRemoved = taskRemoved;
            s.startId = startId;
            s.flags = flags;
            s.args = args;

            sendMessage(H.SERVICE_ARGS, s);
        }

其实不用贴代码我们也能猜到必然是发了一个消息,这和Service的onCreate方法的执行是一个套路,ActivityThread的消息处理器收到消息后会调用handleServiceArgs来完成onStartCommand的回调

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) {
                   //注释1
                   res = s.onStartCommand(data.args, data.flags, data.startId);
               } else {
                   s.onTaskRemoved(data.args);
                   res = Service.START_TASK_REMOVED_COMPLETE;
               }

               QueuedWork.waitToFinish();

               try {
                   ActivityManagerNative.getDefault().serviceDoneExecuting(
                           data.token, 1, data.startId, res);
               } catch (RemoteException e) {
                   // nothing to do.
               }
               ensureJitEnabled();
           } catch (Exception e) {
               if (!mInstrumentation.onException(s, e)) {
                   throw new RuntimeException(
                           "Unable to start service " + s
                           + " with " + data.args + ": " + e.toString(), e);
               }
           }
       }
   }

在handleServiceArgs方法的注释1处我们清楚的看到了 s.onStartCommand,这时候Service的onStartCommand方法也被回调了,至此Service的启动流程就全部走完了。

总结

Service的启动流程的还是比较简单的,不像Activity那么复杂,相关联的类和方法都少了很多,不像Activity启动流程里面走着走着就会迷失方向,源码分析这是加强Android内功修炼的必修课,分析了几个流程之后,你就会觉得也不过如此,因为他们的套路都是一样的,大体的实现思想都相通的,只是具体的代码实现不同罢了。最后方便大家对Service启动的理解,我画了一张方法调用时序图,如下:


在这里插入图片描述

Activity.startService
ContextWraper.startService
ContextImpl.startService
ContextImpl.startServiceCommon
ActivityManagerService.startService
ActiveService.startServiceLocked
ActiveService.startServiceInnerLocked
ActiveService.bringUpServiceLocked
ActiveService.realStartServiceLocked
ApplicationThread.scheduleCreateService
ActivityThread.handleCreateService
Service.onCreate
ActiveService.sendServiceArgsLocked
ApplicationThread.scheduleServiceArgs
ActivityThread.handleServiceArgs
Service.onStartCommand

问题反馈

在使用学习中有任何问题,请留言,或加入Android、Java开发技术交流群

image
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容