AMS-Service-startService流程(android P)

本文深入解析Android P系统中AMS(ActivityManagerService)如何启动Service的过程,从ContextImpl的startService开始,经过ActivityManagerService、ActiveServices等步骤,详细阐述每个阶段的功能和关键方法,如startServiceLocked、bringUpServiceLocked、realStartServiceLocked等,并涉及Service生命周期的重要回调,如onCreate和onStartCommand。
摘要由CSDN通过智能技术生成

AMS - Service - startService流程

[文章基于android P]

先上时序图:

在这里插入图片描述

1 ContextImpl

frameworks/base/core/java/android/app/ContextImpl.java

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

我们在Activity中调用startService其实是调用ContextImpl的startService方法,因为ContextImpl和Activity都是Context的子类。接下来直接调用当前类的startServiceCommon方法。

1.2 startServiceCommon()
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
        //调用AMS的startService方法
        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();
    }
}

这个方法主要是binder调用AMS的startService方法,然后根据返回结果,这里有三个throw exception,这也是我们平时开发APP Service时候经常遇到的报错。这里会根据返回packageName是“!”、“!!”、“?”来抛出不同的异常,那什么情况下才会抛这些异常呢?我们继续往下看。

2 ActivityManagerService

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

2.1 startService()
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage, int userId)
        throws TransactionTooLargeException {
    enforceNotIsolatedCaller("startService");
    ......
    synchronized(this) {
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        ComponentName res;
        try {
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, userId);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return res;
    }
}

这个方法主要获取当前启动要service的pid和uid,然后调用ActiveServices的startServiceLocked去做一些启动service的准备工作。

3 ActiveServices

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

3.1 startServiceLocked()
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
        int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
        throws TransactionTooLargeException {

    final boolean callerFg;
    if (caller != null) {
        //【3.1.1】 getRecordForAppLocked获取client端caller进程record,就是调用startService的app进程,如果对端进程已经被kill则直接抛出异常。
        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;
    }
    //【3.1.2】 retrieveServiceLocked
    ServiceLookupResult res =
        retrieveServiceLocked(service, resolvedType, callingPackage,
                callingPid, callingUid, userId, true, callerFg, false, false);
    if (res == null) {
        return null;
    }
    //"!"这里return packageName=! ①
    if (res.record == null) {
        return new ComponentName("!", res.permission != null
                ? res.permission : "private to package");
    }

    ServiceRecord r = res.record;

    if (!mAm.mUserController.exists(r.userId)) {
        Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);
        return null;
    }

    final boolean bgLaunch = !mAm.isUidActiveLocked(r.appInfo.uid);
    boolean forcedStandby = false;
    if (bgLaunch && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
        forcedStandby = true;
    }
    boolean forceSilentAbort = false;
	//fgRequired,startService时候这个值为false,如果是startForegroundService时候为true
    if (fgRequired) {
        final int mode = mAm.mAppOpsService.checkOperation(
                AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
        switch (mode) {
            case AppOpsManager.MODE_ALLOWED:
            case AppOpsManager.MODE_DEFAULT:
                // All okay.
                break;
            case AppOpsManager.MODE_IGNORED:
                Slog.w(TAG, "startForegroundService not allowed due to app op: service "
                        + service + " to " + r.name.flattenToShortString()
                        + " from pid=" + callingPid + " uid=" + callingUid
                        + " pkg=" &#
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值