android10:后台应用启动服务崩溃

错误提示如上:

下面看下服务启动流程:

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

public ComponentName startService(Intent service) {
    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());
if (cn != null) {
    ...
    } else if (cn.getPackageName().equals("?")) {
        throw new IllegalStateException(
                "Not allowed to start service " + service + ": " + cn.getClassName());
    }
}
return cn;

}

通过上面代码可以看出AMS调用startService返回后组件包名为?,就会抛出IllegalStateException异常,下面重点分析AMS。

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

 public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, int userId) throws TransactionTooLargeException {

ComponentName res;
try {
    res = mServices.startServiceLocked(caller, service,
            resolvedType, callingPid, callingUid,
            requireForeground, callingPackage, userId);
} finally {
    Binder.restoreCallingIdentity(origId);
}
return res;

}

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, final int userId) throws TransactionTooLargeException {
    return startServiceLocked(caller, service, resolvedType, callingPid, callingUid,         fgRequired, callingPackage, userId, false);
} 
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId, boolean allowBackgroundActivityStarts)
        throws TransactionTooLargeException {
if (forcedStandby || (!r.startRequested && !fgRequired)) {
            // Before going further -- if this app is not allowed to start services in the
            // background, then at this point we aren't going to let it period.
            final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
                    r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby);
            if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                Slog.w(TAG, "Background start not allowed: service "
                        + service + " to " + r.shortInstanceName
                        + " from pid=" + callingPid + " uid=" + callingUid
                        + " pkg=" + callingPackage + " startFg?=" + fgRequired);
                // This app knows it is in the new model where this operation is not
                // allowed, so tell it what has happened.
                UidRecord uidRec = mAm.mProcessList.getUidRecordLocked(r.appInfo.uid);
                return new ComponentName("?", "app is in background uid " + uidRec);
            }
        }

int getAppStartModeLocked(int uid, String packageName, int packageTargetSdk,
            int callingPid, boolean alwaysRestrict, boolean disabledOnly, boolean forcedStandby) {
        UidRecord uidRec = mProcessList.getUidRecordLocked(uid);
        if (uidRec == null || alwaysRestrict || forcedStandby || uidRec.idle) {
                final int startMode = (alwaysRestrict)
                        ? appRestrictedInBackgroundLocked(uid, packageName, packageTargetSdk)
                        : appServicesRestrictedInBackgroundLocked(uid, packageName,
                                packageTargetSdk);
                return startMode;
        }
        return ActivityManager.APP_START_MODE_NORMAL;
    }

    int appServicesRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
        // Persistent app?
        if (mPackageManagerInt.isPackagePersistent(packageName)) {
            return ActivityManager.APP_START_MODE_NORMAL;
        }

        // Non-persistent but background whitelisted?
        if (uidOnBackgroundWhitelist(uid)) {
            return ActivityManager.APP_START_MODE_NORMAL;
        }

        // Is this app on the battery whitelist?
        if (isOnDeviceIdleWhitelistLocked(uid, /*allowExceptIdleToo=*/ false)) {
            return ActivityManager.APP_START_MODE_NORMAL;
        }

        // None of the service-policy criteria apply, so we apply the common criteria
        return appRestrictedInBackgroundLocked(uid, packageName, packageTargetSdk);
    }

从这里可以看出1.persist app;2.白名单;3.白名单均可以在后台启动服务,下面重点看白名单:

private boolean uidOnBackgroundWhitelist(final int uid) {
    final int appId = UserHandle.getAppId(uid);
    final int[] whitelist = mBackgroundAppIdWhitelist;
    final int N = whitelist.length;
    for (int i = 0; i < N; i++) {
        if (appId == whitelist[i]) {
            return true;
        }
    }
    return false;
}
boolean isOnDeviceIdleWhitelistLocked(int uid, boolean allowExceptIdleToo) {
    final int appId = UserHandle.getAppId(uid);

    final int[] whitelist = allowExceptIdleToo
            ? mDeviceIdleExceptIdleWhitelist
            : mDeviceIdleWhitelist;

    return Arrays.binarySearch(whitelist, appId) >= 0
            || Arrays.binarySearch(mDeviceIdleTempWhitelist, appId) >= 0
            || mPendingTempWhitelist.indexOfKey(uid) >= 0;
}

可以在相应的白名单中添加自己的app就可以在后台启动服务。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值