美文网首页
startService流程梳理

startService流程梳理

作者: 付凯强 | 来源:发表于2023-04-26 22:07 被阅读0次

app

MainActivity.java:

startService(new Intent(this,TestService.class));

ContextWrapper.java

    @Override
    public @Nullable ComponentName startService(Intent service) {
        return mBase.startService(service);
    }

这里的mBase是代理模式,其对象是ContextImpl对象。

ContextImpl.java

    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
            ...
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
            ...
    }

ActivityManager.getService().startService 通过binder通信,会调用ActivityManagerService中的startService。

system_server

ActivityManagerService.java

    @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
        ...
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
        ...
    }

mServices是类型为ActiveServices。

ActiveServices.java

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage,
            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;
    }

它的返回值是ComponentName,与startService相同,在执行完bringUpServiceLocked之后就返回了,所以重点看下bringUpServiceLocked方法。

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        // 第一种情况: 当进程存在,service存在
        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
        // 第二种情况:当进程存在,service不存在
        if (!isolated) {
            if (app != null && app.thread != null) {
                    realStartServiceLocked(r, app, execInFg);
            }
        }
        // 第三种情况:当进程不存在,service自然也不存在
        if (app == null && !permissionsReviewRequired) {
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingRecord, false, isolated, false)) == null) {
            }
        }
}

以上三种情形分别会调用不同的方法进行处理,现在就分别看下这三个方法的实现。

  1. sendServiceArgsLocked方法
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
            boolean oomAdjusted) throws TransactionTooLargeException {
            bumpServiceExecutingLocked(r, execInFg, "start");
            r.app.thread.scheduleServiceArgs(r, slice);
}

scheduleServiceArgs是发送应用的binder调用,对应应用中的onStartCommand方法。

  1. realStartServiceLocked方法
    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        bumpServiceExecutingLocked(r, execInFg, "create");
        ...
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                    app.getReportedProcState());
        ...
        requestServiceBindingsLocked(r, execInFg);
        ...
        sendServiceArgsLocked(r, execInFg, true);
        ...
    }
    private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
            throws TransactionTooLargeException {
    ...
            if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
    ...
    }
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
...
                bumpServiceExecutingLocked(r, execInFg, "bind");
...
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.getReportedProcState());
                ...
    }

realStartServiceLocked方法会执行三个主逻辑,并分别对应三个binder调用,分别是scheduleCreateService、scheduleBindService、scheduleServiceArgs,并分别对应binder对端,即app service组件的onCreate、onBind、onStartCommand方法。

  1. startProcessLocked方法

这里不再详述,但能想到它会做两件事情,第一件事情是创建进程,第二件事情就是执行realStartServiceLocked,因为realStartServiceLocked对应了“当进程存在,service不存在”这种场景。

app

ActivityThread.java

  1. scheduleCreateService
        public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
            ...
            sendMessage(H.CREATE_SERVICE, s);
        }
  1. scheduleBindService
        public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState) {
            ...
            sendMessage(H.BIND_SERVICE, s);
        }
  1. scheduleServiceArgs
        public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
                ...
                sendMessage(H.SERVICE_ARGS, s);
            }
        }

scheduleCreateService、scheduleBindService、scheduleServiceArgs三个方法其实运行在binder线程,这个时候需要通过消息机制的sendMessage让主线程去执行相应的操作。分别对应下面的三个case:

  1. CREATE_SERVICE
                case CREATE_SERVICE:
                    handleCreateService((CreateServiceData)msg.obj);
                    break;
  1. BIND_SERVICE
                case BIND_SERVICE:
                    handleBindService((BindServiceData)msg.obj);
                    break;
  1. SERVICE_ARGS
                case SERVICE_ARGS:
                    handleServiceArgs((ServiceArgsData)msg.obj);
                    break;

三个case分别执行下面的三个方法

    @UnsupportedAppUsage
    private void handleCreateService(CreateServiceData data) {
        ...
            service.onCreate();
            ...
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
        ...
    }
    private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
             ...
                        IBinder binder = s.onBind(data.intent);
             ...
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
             ...
    }
private void handleServiceArgs(ServiceArgsData data) {
        Service s = mServices.get(data.token);
             ...
                    res = s.onStartCommand(data.args, data.flags, data.startId);
             ...
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
                    ...
}

可见handleCreateService、handleBindService、handleServiceArgs分别调用了Service组件的onCreate、onBind、onStartCommand,并且执行完成后通过调用binder方法serviceDoneExecuting告诉system_server操作已完成。

加油吧,少年!

相关文章

  • 源码分析:service启动流程

    目的:梳理一下service的启动流程 从context.startService入口,其实现类为ContextI...

  • 组件之Service源码解析

    一、startService源码启动流程 (1)启动流程是从ContextWraper的startService方...

  • StartService流程

    概述: Ams在整个流程中充当server端的作用, ActivityManagerNative两次调用AMS,...

  • startService() 流程分析

    总结了几篇系统底层相关的文章,终于要接触到应用层了,不过需要提前掌握 Binder架构,系统启动流程,进程启动流程...

  • startService流程分析

    启动service的方式有两种: 现在来分析startService流程。 mBase的真正实现是ContextI...

  • startService启动流程

    本次源码基于Android11分析 相关源码: 启动Service有两种方式,一种是 startService,一...

  • Service组件

    一、流程图 启动Service的流程(bindService和StartService)如下: 参考:bindSe...

  • bindService启动流程分析与记录(api26)

    流程图 流程分析 1.bindService与startService一样,都是从ContextWrapper开始...

  • service难点

    service学习加开发经验startservice启动流程同act启动流程类似(都是通过ams,流程图也不画了,...

  • android startservice流程分析

    一 startservice流程 之前简单分析了startActivity启动新的process运行activit...

网友评论

      本文标题:startService流程梳理

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