天天看点

Android 11 Service启动流程分析Android 11 Service启动流程分析

Android 11 Service启动流程分析

上一篇我们介绍了Activity启动流程,接下来的这一篇我们接着分析一下Service的启动流程。不了解Activity的启动流程的可以看我的这篇文章Android 11 Activity启动流程分析。本篇文章是基于android11源码来分析的。

Service启动流程调用时序图

Android 11 Service启动流程分析Android 11 Service启动流程分析

service启动流程源码分析

首先,我们在启动一个服务时会在Activity中调用startService方法,它的实现在ContextWrapper中,代码如下:

public class ContextWrapper extends Context {
    Context mBase;
...
  @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }
...    
}
           

还记得在上一片文章中我们介绍的Activity的启动流程,会调用到ActivityThread的performLaunchActivity方法,在这个方法中会对上下文进行初始化赋值。不太了解的可以查看我的这篇文章Android 11 Activity启动流程分析。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  ...
            if (activity != null) {
                ContextImpl appContext = createBaseContextForActivity(r);//1
         ...
                }
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window);
                ...
        }
        return activity;
}
           

在注释1处创建了上下文对象appContext,这个上下文就是ContextImpl,然后再通过activity的attach方法把appContext赋值给ContextWrapper的mBase成员变量。所以接下来我们应该看ContextImpl中的startService方法。

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

private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        ...
         //1
        ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service,
                service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
                getOpPackageName(), getAttributionTag(), user.getIdentifier());
      	...
                return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}
           

startService中会return一个startServiceCommon方法,这个方法内部又调用了ActivityManagerService的startService方法。接下来我们就要关注ActivityManagerService是怎么启动的Service。

@Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage,
            String callingFeatureId, int userId)
            throws TransactionTooLargeException {
        ...
        synchronized(this) {
            ...
            ComponentName res;
            try {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, callingFeatureId, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }
           

这里调用了ActiveServices的startServiceLocked方法,代码如下:

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage,
            @Nullable String callingFeatureId, final int userId,
            boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
            ...
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);

        ...
    }
    
  ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
          ...
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
         ...

        return r.name;
    }
           

在startServiceLocked内部调用了自己的startServiceInnerLocked方法,而startServiceInnerLocked方法又调用了bringUpServiceLocked方法:

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }

        ...
        final String procName = r.processName;//1
        HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
        ProcessRecord app;

        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);//2
            if (app != null && app.thread != null) {//3
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);//4
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
                }
            }
        } else {
            app = r.isolatedProc;
            ...
        }
        if (app == null && !permissionsReviewRequired) {//5
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {//6
               ...
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }
        ...
        return null;
    }
           

在注释1处得到ServiceRecord的processName的值赋值给procName ,其中processName用来描述Service想要在哪个进程运行,默认是当前进程,我们也可以在AndroidManifes配置文件中设置android:process属性来新开启一个进程运行Service。注释2处将procName和Service的uid传入到AMS的getProcessRecordLocked方法中,来查询是否存在一个与Service对应的ProcessRecord类型的对象app,ProcessRecord主要用来记录运行的应用程序进程的信息。注释5处判断两个条件一个是当前Service的进程是否不存在,另一个是需不需要检查权限。这两个条件满足后,就会调用注释6处的AMS的startProcessLocked方法创建一个指定进程。注释3处判断所需的应用进程存在,那么就直接调用realStartServiceLocked方法来启动服务。代码如下:

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

        boolean created = false;
        try {
             ...
             //1
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                    app.getReportedProcState());
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app, "Died when creating service");
            throw e;
        } 
        ...

        sendServiceArgsLocked(r, execInFg, true);//2

        ...
    }
           

注释1处realStartServiceLocked会调用 app.thread的scheduleCreateService,完成Service创建和onCreate方法的回调工作。其中app.thread其实指的就是IApplicationThread的类型的aidl接口,其实现类是ActivityThread的内部类ApplicationThread,而ApplicationThread又继承自IApplicationThread.Stub,这个IApplicationThread.Stub类继承自Binder并实现了IApplicationThread接口的抽象类。注释2处会调sendServiceArgsLocked方法用来处理启动服务后的后续操作,比如Service的回调onStartCommand方法,接下来我们看一下ApplicationThread的scheduleCreateService方法。

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

这里它封装了一个CreateServiceData对象然后传给了sendMessage方法并想H这个Handler类发送了一条CREATE_SERVICE消息。然后在H类的handleMessage方法中进行了处理。这个流程和Activity的启动流程是类似的。接下来我们主需要看handleMessage方法中对应的CREATE_SERVICE消息的处理。

public void handleMessage(Message msg) {
     ...
       case CREATE_SERVICE:
                    if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                                ("serviceCreate: " + String.valueOf(msg.obj)));
                    }
                    handleCreateService((CreateServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    ...
     }
           

这里可以看到它调用了ActivityThread的handleCreateService方法

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

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);//1
        Service service = null;
        try {

            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);//2
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            java.lang.ClassLoader cl = packageInfo.getClassLoader();//3
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);//4
            context.getResources().addLoaders(
                    app.getResources().getLoaders().toArray(new ResourcesLoader[0]));

            context.setOuterContext(service);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());//5
            service.onCreate();//6
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
               ...
            }
        } catch (Exception e) {
           ...
        }
    }
           

首先通过注释1处获取要启动Service应用程序的LoadedApk 对象,LoadedApk其实就是一个apk信息的封装类。然后通过注释2处创建Service所需的上下文对象ContextImpl ,接着在注释3处获取LoadedApk 的类加载器ClassLoader,接着通过类加载器和Service信息把Service加载到内存并创建一个实例,然后在注释5处调用service的attach方法关联上下文环境context和做些初始化工作,紧接着调用service的onCreate方法服务正式启动。Service启动后就会进行后续操作会调用ActiveServices的sendServiceArgsLocked方法

private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
            boolean oomAdjusted) throws TransactionTooLargeException {
        ...
        try {
            r.app.thread.scheduleServiceArgs(r, slice);
        } catch (TransactionTooLargeException e) {
          ...
        }
      ...
    }
           

这里调用了app.thread的scheduleServiceArgs方法,这里和启动服务调用方式是一样的会调用到ApplicationThread的scheduleServiceArgs方法

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

这里还是通过Handler发送了一个SERVICE_ARGS消息,然后到handleMessage会调用ActivityThread的handleServiceArgs方法

private void handleServiceArgs(ServiceArgsData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                ...
                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;
                }
                ...
            } catch (Exception e) {
                ...
            }
        }
    }
           

在这个方法内部我们就可以看到我们在开发中常常会复写的Service的方法onStartCommand了。到这里Service的启动流程也就结束了,其实到Servcie的onCreate被调用时Service的启动流程就已经结束了。这里只是为了说明一下onStartCommand到底是在哪被调用的。