美文网首页
startService启动流程分析记录(api26)

startService启动流程分析记录(api26)

作者: r09er | 来源:发表于2018-01-25 16:54 被阅读70次

Service一般会有两种状态,启动状态,通过startService启动,一般用于后台计算,另一种是绑定状态,通过bindService启动,用于和其他组件和Service进行通信.两种状态可以共存,可以startService之后又bindService

startService启动流程图

图1-1 startService启动流程

startService启动流程分析

1. startService执行在ContextWrapper中,mBase的类型是ContextImpl.通过上次Activity启动流程的分析,在Activity创建过程中会通过activity.attach方法与ContextImpl关联,ContextWrapper内部大部分方法都是通过mBase实现,所以startService其实是执行在ContextImpl内部,startService会调用内部的startServiceCommon方法,最终会调用到AMS中的startService方法
@Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }
 private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            ...
            //调用了AMS的startService方法
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
            ...
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
2.AMS中startService方法又调用了startServiceLocked方法,startServiceLocked最后会执行startServiceInnerLocked方法,但是在startServiceInnerLocked并没有完成具体的启动工作,而是再调用了bringUpServiceLocked方法,
public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
        ...
        synchronized(this) {
            ...
            try {
                //调用了内部的startServiceLocked
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
...
//调用startServiceInnerLocked
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
}
//调用bringUpServiceLocked
 ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
...
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);

...

}
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
...
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);
                }

...
}
2.1在bringUpServiceLocked中,调用realStartServiceLocked,最后在realStartServicdeLocked中会调用IApplicationThread的scheduleCreateService方法,IApplicationThread在前一篇中也分析过,所以最终会调用到ActivityThread中ApplicationThread的scheduleCreateService方法
 private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
...
app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
...

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);
        }
3.熟悉的handler处理消息,调用handleCreateService方法
 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;


...
//反射生成service对象
 java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();
...
//调用service的onCreate方法
            service.onCreate();

...
3.1 在bringUpServiceLocked的方法中,还会调用一个sendServiceArgsLocked的方法,这个会调用到ApplicationThread中的scheduleServiceArgs方法,最终会在service的onStartCommand方法中回调
    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        ...
        if (r.app != null && r.app.thread != null) {
            //调用方法ApplicationThread方法
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
...

 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处理消息

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;

最后回调Service的onStartCommond方法

  private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
...
if (!data.taskRemoved) {
                    res = s.onStartCommand(data.args, data.flags, data.startId);
                }
...
}

相关文章

网友评论

      本文标题:startService启动流程分析记录(api26)

      本文链接:https://www.haomeiwen.com/subject/zcwmaxtx.html