startService启动过程-Android12

startService启动过程-Android12

android12-release


时序图

startService启动过程

1. startService启动简要流程

查看上图,startService启动简要流程如下,主要关注ActiveServices.java:启动前台服务、Service超时检查、APP进程未启动情况

Activity.startService -> ContextImpl.startService -> ContextImpl.startServiceCommon -> AMS.startService -> ActiveServices.startServiceLocked -> ActiveServices.startServiceInnerLocked -> ActiveServices.bringUpServiceLocked -> ActiveServices.realStartServiceLocked -> ApplicationThread.scheduleCreateService -> ActivityThread.handleCreateService -> Service.onCreate()

2. 启动前台服务

在 Android 8.0(API 级别 26)及更高版本中,系统会限制应用在后台运行时可以执行的操作。
以 Android 12 或更高版本为目标平台的应用无法在后台运行时启动前台服务,少数特殊情况除外。如果应用尝试在后台运行时启动前台服务,则会引发异常(少数特殊情况除外)。

2.1 Android 8.0:Service 后台定义

  系统可以区分前台和后台应用。 (用于 Service 限制目的的后台定义内存管理使用的定义不同;一个应用按照内存管理的定义可能处于后台,但按照能够启动 Service 的定义又处于前台。)如果满足以下任意条件,应用将被视为处于前台:

  • 具有可见 Activity(不管该 Activity 已启动还是已暂停)。
  • 具有前台 Service。
  • 另一个前台应用已关联到该应用(不管是通过绑定到其中一个 Service,还是通过使用其中一个内容提供程序)。 例如,如果另一个应用绑定到该应用的 Service,那么该应用处于前台:1. IME,2. 壁纸 Service,3. 通知侦听器,4. 语音或文本 Service

如果以上条件均不满足,应用将被视为处于后台。

2.1.1 startForegroundService启动前台服务

在这里插入图片描述
  在 Android 8.0 之前,创建前台 Service 的方式通常是先创建一个后台 Service,然后将该 Service 推到前台。 Android 8.0 有一项复杂功能:系统不允许后台应用创建后台 Service。 因此,Android 8.0 引入了一种全新的方法,即 startForegroundService(),以在前台启动新 Service。 在系统创建 Service 后,应用有5秒的时间来调用该 Service 的 startForeground() 方法以显示新 Service 的用户可见通知。 如果应用在此时间限制内未调用 startForeground(),则系统将停止此 Service 并声明此应用为 ANR。

2.2 Android 12 :Service应用无法在后台运行时启动前台服务

  除少数特殊情况外,面向Android 12(API级别31)或更高版本的应用程序在后台运行时无法启动前台服务(startForegroundService()也不允许)。如果应用程序在后台运行时尝试启动前台服务,而前台服务不满足其中一种例外情况,则系统会抛出ForegroundServiceStartNotAllowedException。
  当您的应用在后台运行时,请考虑使用 WorkManager 来计划和启动加急工作。如需完成用户请求的紧急操作,请按照精确的闹钟启动前台服务。

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

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 {
    // ... ...
    if (fgRequired) {
        logFgsBackgroundStart(r);
        if (r.mAllowStartForeground == REASON_DENIED && isBgFgsRestrictionEnabled(r)) {
            String msg = "startForegroundService() not allowed due to "
                    + "mAllowStartForeground false: service "
                    + r.shortInstanceName;
            Slog.w(TAG, msg);
            showFgsBgRestrictedNotificationLocked(r);
            logFGSStateChangeLocked(r,
                    FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
                    0);
            if (CompatChanges.isChangeEnabled(FGS_START_EXCEPTION_CHANGE_ID, callingUid)) {
                throw new ForegroundServiceStartNotAllowedException(msg);
            }
            return null;
        }
    }
    // ... ...
    // At this point we've applied allowed-to-start policy based on whether this was
    // an ordinary startService() or a startForegroundService().  Now, only require that
    // the app follow through on the startForegroundService() -> startForeground()
    // contract if it actually targets O+.
    if (r.appInfo.targetSdkVersion < Build.VERSION_CODES.O && fgRequired) {
        if (DEBUG_BACKGROUND_CHECK || DEBUG_FOREGROUND_SERVICE) {
            Slog.i(TAG, "startForegroundService() but host targets "
                    + r.appInfo.targetSdkVersion + " - not requiring startForeground()");
        }
        fgRequired = false;
    }
    // ... ...
    return startServiceInnerLocked(r, service, callingUid, callingPid, fgRequired, callerFg,
            allowBackgroundActivityStarts, backgroundActivityStartsToken);
}

3. Service超时检查

可以查看 ANR service TimeOut 超时判断
ContextImpl.startService -> ContextImpl.startServiceCommon -> AMS.startService -> ActiveServices.startServiceLocked -> ActiveServices.startServiceInnerLocked -> ActiveServices.bringUpServiceLocked -> ActiveServices.realStartServiceLocked -> ActiveServices.bumpServiceExecutingLocked -> ActiveServices.scheduleServiceTimeoutLocked
在这里插入图片描述 在这里插入图片描述

不同电在于Build.HW_TIMEOUT_MULTIPLIER(ro.hw_timeout_multiplier默认值是1)属性值可以设置SERVICE_TIMEOUT


在这里插入图片描述

4. APP进程未启动情况

需要mAm.startProcessLocked()启动进程,和 AMS:startActivity桌面启动应用 启动进程差不多,在ActivityManagerService.attachApplicationLocked最终调用ActiveServices.realStartServiceLocked
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xhBruce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值