Service的启动流程(Android14)

一:启动方式 

  Service的启动一般分为两种,一种是直接调用context.startService()来启动一个新的Service,一种是调用context.bindService(),把Service与Activity组件绑定来启动新的Service。

二:startService流程

2.1 Context.startService()

    我们启动一个Service,一般会在Activity里调用context.startService(launchIntent); context是Context的对象,Context类是一个抽象类,其具体实现类是ContextImpl,所以会调用到ContextImpl的startService函数中。

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

2.2 ContextImpl.startServiceCommon()

    会先检查intent是否合法,做一些离开进程的准备工作,然后通过Binder跨进程调用ActivityManagerService的startService函数

    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            //检查intent的package和component是否合法
            validateServiceIntent(service);
            //做一些离开进程的准备工作
            service.prepareToLeaveProcess(this);
            //跨进程调用AMS的startService
            ComponentName cn = ActivityManager.getService().startService(
                    mMainThread.getApplicationThread(), service,
                    service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
                    getOpPackageName(), getAttributionTag(), user.getIdentifier());
            ...
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

2.3 ActivityManagerService.startService

    检查调用对象的合法性,获取pid、uid等,调用ActiveServices的startServiceLocked函数

    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage,
            String callingFeatureId, int userId)
            throws TransactionTooLargeException {
        //检查是否属于被隔离的对象
        enforceNotIsolatedCaller("startService");
        //如果是沙盒机制下的SDK,检查其权限。一般用于应用双开?
        enforceAllowedToStartOrBindServiceIfSdkSandbox(service);

        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            ...
            try {
                //获取到调用的pid和uid,执行ActiveService的startServiceLocked函数
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, callingFeatureId, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

2.4 ActiveService.startServiceLoaked

    进行一些Permission、Ops、standby检查,把传入的参数封装成ServiceRecord

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired,
            String callingPackage, @Nullable String callingFeatureId, final int userId,
            boolean allowBackgroundActivityStarts, @Nullable IBinder backgroundActivityStartsToken)
            throws TransactionTooLargeException {
        ...
        //在smap(现有Service集合)中查找是否有与传入参数对应的ServiceRecord,如果没有则通过PMS去获取与传入参数对应的Service信息并封装成ServiceRecord,最后把ServiceRecord封装成ServiceLookupResult并返回
        ServiceLookupResult res =
            retrieveServiceLocked(service, null, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false, false);
        ...
        //判断是否允许从后台启动前台服务
        setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, r, userId,
                allowBackgroundActivityStarts);
        ...
        //继续启动Service
        final ComponentName realResult =
                startServiceInnerLocked(r, service, callingUid, callingPid, fgRequired, callerFg,
                allowBackgroundActivityStarts, backgroundActivityStartsToken);
        ...
    }

    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting, int callingUid, boolean wasStartRequested)
            throws TransactionTooLargeException {
        ...
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg,
                false /* whileRestarting */,
                false /* permissionsReviewRequired */,
                false /* packageFrozen */,
                true /* enqueueOomAdj */);
        ...
    }

2.5 ActiveService.bringUpServiceLocked

    判断Service所在进程有没有启动,没有则通过AMS启动进程,有则继续启动Service

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen,
            boolean enqueueOomAdj)
            throws TransactionTooLargeException {
        if (r.app != null && r.app.getThread() != null) {
            //首次启动Service时,ServiceRecord是属于新创建的,而非从AMS的缓存mServices中检索而来,所以此时的ServiceRecord的ProcessRecord类型app和IApplicationThread类型thread都是null。只有启动过后的ServiceRecord才有值,才会执行sendServiceArgsLocked函数,开启Service启动的anr超时检测,调用Service的生命周期onStartCommand,而不调用onCreate函数。
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
        ...
        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);
            ...
            if (app != null) {
                final IApplicationThread thread = app.getThread();
                if (thread != null) {
                    try {
                        //继续启动Service
                        realStartServiceLocked(r, app, thread, pid, uidRecord, execInFg,
                                enqueueOomAdj);
                    }
                }
            }
        }

        if (app == null && !permissionsReviewRequired && !packageFrozen) {
            if (r.isSdkSandbox) {
                //如果是沙盒,调用startSdkSandboxProcessLocked来启动进程
                app = mAm.startSdkSandboxProcessLocked(procName, r.appInfo, true, intentFlags,
                        hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, uid, r.sdkSandboxClientAppPackage);
            } else {
                //如果Service所在进程还未启动,则调用AMS的startProcessLocked来启动进程
                app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                        hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated);
            }
        }
    }

2.6 ActivityManagerService.startProcessLocked

    通过ProcessList的startProcessLocked函数来启动进程,此过程后续有专门文章介绍,在此就不详述了

    final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
            boolean isolated) {
        return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
                hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
                false /* isSdkSandbox */, 0 /* sdkSandboxClientAppUid */,
                null /* sdkSandboxClientAppPackage */,
                null /* ABI override */, null /* entryPoint */,
                null /* entryPointArgs */, null /* crashHandler */);
    }

2.7 ActiveService.realStartServiceLocked

    开始anr超时检测,更新进程列表,更新进程优先级

    private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
            IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,
            boolean enqueueOomAdj) throws RemoteException {
        ...
        //使此ServiceRecord进入执行状态,开始anr超时检测
        bumpServiceExecutingLocked(r, execInFg, "create", null /* oomAdjReason */);
        //更新进程列表
        mAm.updateLruProcessLocked(app, false, null);
        //通过前台服务Listener,通知前台服务更新
        updateServiceForegroundLocked(psr, /* oomAdj= */ false);
        //讲给定的进程排队到todo列表中
        mAm.enqueueOomAdjTargetLocked(app);
        //更新进程优先级
        mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
        ...
        try {
            ...
            //继续启动Service
            thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                    app.mState.getReportedProcState());
        }
        ...
    }

2.8 ActivityThread.ApplicationThread.scheduleCreateService

    把Service相关信息封装成CreateServiceData,并发送到ActivityThread中

        public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
            //更新进程状态
            updateProcessState(processState, false);
            //把Service相关信息封装成CreateServiceData
            CreateServiceData s = new CreateServiceData();
            s.token = token;
            s.info = info;
            s.compatInfo = compatInfo;
            //发送CREATE_SERVICE的Message
            sendMessage(H.CREATE_SERVICE, s);
        }

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case CREATE_SERVICE:
                    handleCreateService((CreateServiceData)msg.obj);
                    break;
            }
        }

2.9 ActivityThread.handleCreateService

    如果是新启动进程,则进行Application的初始化工作,然后依次调用Service的attach和onCreate函数,在执行完毕后表示Service正常启动成功,移除anr超时检测的Message

    private void handleCreateService(CreateServiceData data) {
        //停止gc
        unscheduleGcIdler();
        ...
        try {
            //如果是新启动进程,进行Application的一些初始化工作,例如调用Application的onCreate
            Application app = packageInfo.makeApplicationInner(false, mInstrumentation);

            ...
            //调用Service的attach函数
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            //调用Service的onCreate函数
            service.onCreate();
            ...
            try {
                //Service启动完成,移除anr超时检测的Message
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            }
        }
    }

三:bindService流程

3.1 Context.bindService()

    我们绑定一个Service,一般会在Activity里调用getContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);; context是Context的对象,Context类是一个抽象类,其具体实现类是ContextImpl,所以会调用到ContextImpl的bindService函数中。

    public boolean bindService(Intent service, ServiceConnection conn, int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
                getUser());
    }

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
            String instanceName, Handler handler, Executor executor, UserHandle user) {
        ...
        try {
            ...
            //调用AMS的bindServiceInstance
            int res = ActivityManager.getService().bindServiceInstance(
                    mMainThread.getApplicationThread(), getActivityToken(), service,
                    service.resolveTypeIfNeeded(getContentResolver()),
                    sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
            ...
            return res != 0;
        }
    }

3.2 ActivityManagerService.bindServiceInstance

    检查调用对象的合法性,调用ActiveServices的bindServiceInstance函数

    private int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String instanceName,
            boolean isSdkSandboxService, int sdkSandboxClientAppUid,
            String sdkSandboxClientAppPackage, String callingPackage, int userId)
            throws TransactionTooLargeException {
        ...
        try {
            ...
            synchronized (this) {
                //调用到ActiveService的bindServiceLocked函数
                return mServices.bindServiceLocked(caller, token, service, resolvedType, connection,
                        flags, instanceName, isSdkSandboxService, sdkSandboxClientAppUid,
                        sdkSandboxClientAppPackage, callingPackage, userId);
            }
        }
    }

3.3 ActiveServices.bindServiceLocked

    与进程建立关联并保存相关信息,如果进程没有启动则启动进程

    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid,
            String sdkSandboxClientAppPackage, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        ...
        //在smap(现有Service集合)中查找是否有与传入参数对应的ServiceRecord,如果没有则通过PMS去获取与传入参数对应的Service信息并封装成ServiceRecord,最后把ServiceRecord封装成ServiceLookupResult并返回
        ServiceLookupResult res = retrieveServiceLocked(service, instanceName,
                isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
                resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg,
                isBindExternal, allowInstant);
        ...
        try {
            ...
            //更新关联进程
            mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
                    callerApp.mState.getCurProcState(), s.appInfo.uid, s.appInfo.longVersionCode,
                    s.instanceName, s.processName);
            //Service与进程之间关联,包含service、进程等所有绑定信息
            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
            //进程与service建立的一次连接
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent,
                    callerApp.uid, callerApp.processName, callingPackage, res.aliasComponent);

            IBinder binder = connection.asBinder();
            s.addConnection(binder, c);
            b.connections.add(c);
            if (activity != null) {
                activity.addConnection(c);
            }
            final ProcessServiceRecord clientPsr = b.client.mServices;
            clientPsr.addConnection(c);
            c.startAssociationIfNeeded();
            ...
            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                needOomAdj = true;
                //参考startService的bringUpServiceLocked流程
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired, packageFrozen, true) != null) {
                    mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
                    return 0;
                }
            }
            ...
            if (s.app != null && b.intent.received) {
                ...
                try {
                    //建立连接
                    c.conn.connected(clientSideComponentName, b.intent.binder, false);
                }

                //第一个绑定该Service的进程且要重新绑定
                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
                }
            //首次绑定
            } else if (!b.intent.requested) {
                requestServiceBindingLocked(s, b.intent, callerFg, false);
            }
        }
        ...
    }

3.4 ActiveServices.requestServiceBindingLocked

    开始anr超时检测,跨进程调用ActivityThread的scheduleBindService函数

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        ...
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                //开始anr超时检测
                bumpServiceExecutingLocked(r, execInFg, "bind",
                        OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
                //调用ActivityThread的scheduleBindService函数继续bind流程
                r.app.getThread().scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.mState.getReportedProcState());
                ...
            }
        }
    }

3.5 ActivityThread.ApplicationThread.scheduleBindService

    发送BIND_SERVICE的message,调用ActivityThread的handleBindService函数

        public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState) {
            ...
            //发送BIND_SERVICE的message
            sendMessage(H.BIND_SERVICE, s);
        }

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BIND_SERVICE:
                    handleBindService((BindServiceData)msg.obj);
                    break;
            }
        }

3.6 ActivityThread.handleBindService

    根据进程与Service的绑定状态,执行不同的函数

    private void handleBindService(BindServiceData data) {
        ...
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                ...
                try {
                    if (!data.rebind) {
                        //进程与Service没有绑定过,执行Service的onBind函数
                        IBinder binder = s.onBind(data.intent);
                        //执行AMS的publishService
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        //如果进程第一个与Service绑定且已经执行过onBind函数,直接执行Service的onRebind函数
                        s.onRebind(data.intent);
                        //移除anr超时检测的message
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                }
            }
        }
    }

    public void publishService(IBinder token, Intent intent, IBinder service) {
        ...
        synchronized(this) {
            ...
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }

3.7 ActiveServices.publishServiceLocked

    建立连接并移除anr超时检测的message

    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        ...
        try {
            if (r != null) {
                if (b != null && !b.received) {
                    for (int conni = connections.size() - 1; conni >= 0; conni--) {
                        ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
                        for (int i=0; i<clist.size(); i++) {
                            ...
                            try {
                                //建立连接
                                c.conn.connected(clientSideComponentName, service, false);
                            }
                        }
                    }
                }
                //移除anr超时检测的message
                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false, false);
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值