理解四大组件Service之 startService() 启动流程(基于Android10)

一、概览

这次继续分析 startService() 的启动过程。 相比于activity,服务可提供在后台长时间的运行操作,同时没有界面。即使切换到后台,服务仍然在后台继续运行。

1.1 服务的三种类型

前台服务
后台服务
绑定服务

1.2 服务的生命周期

service的生命周期如下:

1.3 startService 和 bindService的区别

生命周期区别已经在上面的生命周期图中展示了出来。前者用来做长时间的单一工作,启动后独自运行。后者适合需要多次调用接口的RPC交互场景,偏重于交互。

虽然区分了两种方式,但是一个service可以支持在启动的情况下,再对其进行绑定操作。也就是说, 同时支持两种方式运行 。

1.4 系统服务提供的子类

service
IntentService

1.5 服务与线程的选择

服务一般适用于 长时间后台工作 ,如网络事务、播放音乐、文件I/O等。线程适合执行耗时操作。如:服务跟随组件如activity的生命周期,那么选择线程即可。

Activity 继承了 ContextWrapper:

二、App端 startService()

2.1 ContextImpl.startService()

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

    // 前台服务
    @Override
    public ComponentName startForegroundService(Intent service) {
        return mBase.startForegroundService(service);
    }

ContextWrapper内部有代理了 ContextImpl ,所以我们看看 ContextImpl的 startService():

2.2 ContextImpl.startService()

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

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

2.2.1 startServiceCommon()

private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            // 直接调用 AMS的 startService方法 , 返回一个 ComponentName 对象。
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), 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());
                } else if (cn.getPackageName().equals("?")) {
                    throw new IllegalStateException(
                            "Not allowed to start service " + service + ": " + cn.getClassName());
                }
            }
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

直接调用 AMS的 startService方法 , 返回一个 ComponentName 对象。

三、AMS 端 startService

3.1 startService()

ActivityManagerService.java
@Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
            // requireForeground 是否是前台服务 
        enforceNotIsolatedCaller("startService");
       ...
        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
                "*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
            // 调用  startServiceLocked
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

调用 ActiveServices的 startServiceLocked()。

allowBackgroundActivityStarts属性传入false ,再内部继续调用同名的方法startServiceLocked():

3.2 ActiveServices.startServiceLocked()

ActiveServices.java

ActiveServices 是系统用来管理服务的类。内部有一系列的集合list,用来存储ServiceRecord 对象。 也就是系统所有的service都由 ActiveServices 来管理。

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage,
            final int userId, boolean allowBackgroundActivityStarts)
            throws TransactionTooLargeException {
            
            // fgRequired 是否是前台服务 
            //  allowBackgroundActivityStarts 为false。
            
            
            final boolean callerFg;
            // 获取当前进程对象 ProcessRecord 
            if (caller != null) {
                final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
                if (callerApp == null) {
                    throw new SecurityException(
                            "Unable to find app for caller " + caller
                            + " (pid=" + callingPid
                            + ") when starting service " + service);
                }
                callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
            } else {
                callerFg = true;
            }
            
            // 内部通过PMS解析得到 serviceRecord 对象信息 
            ServiceLookupResult res =
            retrieveServiceLocked(service, null, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false, false);
            if (res == null) {
                return null;
            }
            if (res.record == null) {
                return new ComponentName("!", res.permission != null
                        ? res.permission : "private to package");
            }
        
       ServiceRecord r = res.record;
    
            // ...
        // 继续启动服务
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;

}

retrieveServiceLocked()方法内部最终通过PMS来解析得到 ServiceRecord对象,返回ServiceLookupResult。 ServiceLookupResult 内部封装了 ServiceRecord 对象。

3.2.1 startServiceInnerLocked()

ActiveServices.java
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean ca
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值