某学姐

Android Female Developer, Technology Fan, Reader.

sendBroadcast过程

2020-04-06 | Comments

基于Android 10.0的源码剖析, 站在Luoshengyang/Innost/Gityuan肩膀上.

本文分析广播Broadcast发送过程.

0.文件结构

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
frameworks/base/services/core/java/com/android/server/pm/ComponentResolver.java
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
frameworks/base/services/core/java/com/android/server/am/BroadcastRecord.java

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

1.时序图

TODO

2.ContextImpl.sendBroadcast

[ -> frameworks/base/core/java/android/app/ContextImpl.java ]

@Override
public void sendBroadcast(Intent intent) {
    warnIfCallingFromSystemProcess();
    String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
 
    intent.prepareToLeaveProcess(this);
    ActivityManager.getService().broadcastIntent(
            mMainThread.getApplicationThread(), intent, resolvedType, null,
            Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false, getUserId());
}

3.ActivityManagerService

[ -> frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java ]

3.1 broadcastIntent

public final int broadcastIntent(IApplicationThread caller,
        Intent intent, String resolvedType, IIntentReceiver resultTo,
        int resultCode, String resultData, Bundle resultExtras,
        String[] requiredPermissions, int appOp, Bundle bOptions,
        boolean serialized, boolean sticky, int userId) {
    enforceNotIsolatedCaller("broadcastIntent");
    synchronized(this) {
        intent = verifyBroadcastLocked(intent);
 
        final ProcessRecord callerApp = getRecordForAppLocked(caller);
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
 
        final long origId = Binder.clearCallingIdentity();
        try {
            return broadcastIntentLocked(callerApp,
                    callerApp != null ? callerApp.info.packageName : null,
                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                    requiredPermissions, appOp, bOptions, serialized, sticky,
                    callingPid, callingUid, callingUid, callingPid, userId);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }
}

3.2 broadcastIntentLocked

final int broadcastIntentLocked(ProcessRecord callerApp,
        String callerPackage, Intent intent, String resolvedType,
        IIntentReceiver resultTo, int resultCode, String resultData,
        Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
        boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
        int realCallingPid, int userId) {
    return broadcastIntentLocked(callerApp, callerPackage, intent, resolvedType, resultTo,
        resultCode, resultData, resultExtras, requiredPermissions, appOp, bOptions, ordered,
        sticky, callingPid, callingUid, realCallingUid, realCallingPid, userId,
        false /* allowBackgroundActivityStarts */);
}

具体实现细节看下面代码:

final int broadcastIntentLocked(ProcessRecord callerApp,
        String callerPackage, Intent intent, String resolvedType,
        IIntentReceiver resultTo, int resultCode, String resultData,
        Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
        boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
        int realCallingPid, int userId, boolean allowBackgroundActivityStarts) {
    intent = new Intent(intent);
 
    // 1.根据各种限制设置intent的flags: 比如Instant App不能使用FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS, 广播不会发送到杀死的进程, 系统还没启动不允许启动新进程
    // 2.检查接收广播的userId是否正在运行
    // 3.权限和限制检查: 如CHANGE_DEVICE_IDLE_TEMP_WHITELIST权限, START_ACTIVITIES_FROM_BACKGROUND权限, OP_RUN_ANY_IN_BACKGROUND操作权限
    // 4.非系统用户不允许发送ProtectedBroadcast, 系统用户指(ROOT_UID/SYSTEM_UID/PHONE_UID/BLUETOOTH_UID/NFC_UID/SE_UID/NETWORK_STACK_UID)
    ...
 
    userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_NON_FULL, "broadcast", callerPackage);
    boolean timeoutExempt = false;
    final String action = intent.getAction();
    if (action != null) {
        // 如果action所属Intent需要发送给未启动的或后台的进程, 则Intent添加flags为FLAG_RECEIVER_INCLUDE_BACKGROUND
        if (getBackgroundLaunchBroadcasts().contains(action)) {
            intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        }
 
        // 包管理器发出的和包移除相关的action的处理,如ACTION_UID_REMOVED/ACTION_PACKAGE_REMOVED/ACTION_PACKAGE_CHANGED/...
        ...
    }
    // sticky广播处理, 常规的sendBroadcast发送的都是非sticky广播, 走不到这里
    if (sticky) {
        // 权限和条件检查包括: Manifest.permission.BROADCAST_STICKY权限检查, requiredPermissions和Component为空检查, mStickyBroadcasts重复广播检查
        ...
 
        // 将发送的广播Intent替换或插入到mStickyBroadcasts队列中相应位置
        ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
        if (stickies == null) {
            stickies = new ArrayMap<>();
            mStickyBroadcasts.put(userId, stickies);
        }
        ArrayList<Intent> list = stickies.get(intent.getAction());
        if (list == null) {
            list = new ArrayList<>();
            stickies.put(intent.getAction(), list);
        }
        final int stickiesCount = list.size();
        int i;
        for (i = 0; i < stickiesCount; i++) {
            if (intent.filterEquals(list.get(i))) {
                // This sticky already exists, replace it.
                list.set(i, new Intent(intent));
                break;
            }
        }
        if (i >= stickiesCount) {
            list.add(new Intent(intent));
        }
    }
 
    // 设置广播的目标用户数组users
    int[] users;
    if (userId == UserHandle.USER_ALL) {
        // 所有启动用户
        users = mUserController.getStartedUserArray();
    } else {
        // 特定用户
        users = new int[] {userId};
    }
 
    // Figure out who all will receive this broadcast.
 
    // 收集receivers列表组件信息. 参考【第3.3节】
    List receivers = null;
    if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
        receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
    }
 
    // 通过IntentResolver收集已注册的Receiver列表registeredReceivers
    List<BroadcastFilter> registeredReceivers = null;
    if (intent.getComponent() == null) {
        if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
            for (int i = 0; i < users.length; i++) {
                // 过滤Shell限制的用户
                ...
 
                List<BroadcastFilter> registeredReceiversForUser =
                        mReceiverResolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, users[i]);
                if (registeredReceivers == null) {
                    registeredReceivers = registeredReceiversForUser;
                } else if (registeredReceiversForUser != null) {
                    registeredReceivers.addAll(registeredReceiversForUser);
                }
            }
        } else {
            registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, userId);
        }
    }
 
    final boolean replacePending = (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
 
    // 整体逻辑: 将新发送的无序广播入队列
    int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
    if (!ordered && NR > 0) {
        // If we are not serializing this broadcast, then send the
        // registered receivers separately so they don't wait for the
        // components to be launched.
        if (isCallerSystem) {
            checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid, isProtectedBroadcast, registeredReceivers);
        }
        final BroadcastQueue queue = broadcastQueueForIntent(intent);
        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                resultCode, resultData, resultExtras, ordered, sticky, false, userId,
                allowBackgroundActivityStarts, timeoutExempt);
        final boolean replaced = replacePending && (queue.replaceParallelBroadcastLocked(r) != null);
        if (!replaced) {
            queue.enqueueParallelBroadcastLocked(r);
            queue.scheduleBroadcastsLocked();
        }
        registeredReceivers = null;
        NR = 0;
    }
 
    // Merge into one list receivers.
    // 1.receivers中移除如下action对应的广播: ACTION_PACKAGE_ADDED/ACTION_PACKAGE_RESTARTED/ACTION_PACKAGE_DATA_CLEARED/ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
    // 2.将registeredReceivers列表合并到receivers列表
    ...
    if (isCallerSystem) {
        checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid, isProtectedBroadcast, receivers);
    }
 
    // 将新发送的有序广播入队列
    if ((receivers != null && receivers.size() > 0) || resultTo != null) {
        BroadcastQueue queue = broadcastQueueForIntent(intent);
        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                resultData, resultExtras, ordered, sticky, false, userId,
                allowBackgroundActivityStarts, timeoutExempt);
 
        final BroadcastRecord oldRecord = replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
        if (oldRecord != null) {
            // Replaced, fire the result-to receiver.
            if (oldRecord.resultTo != null) {
                final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
                oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
                        oldRecord.intent, Activity.RESULT_CANCELED, null, null, false, false, oldRecord.userId);
            }
        } else {
            queue.enqueueOrderedBroadcastLocked(r);
            queue.scheduleBroadcastsLocked();
        }
    } else {
        // 该广播没有广播接收器, 说明是隐式广播, 记录一下即可
        if (intent.getComponent() == null && intent.getPackage() == null
                && (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
            addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
        }
    }
 
    return ActivityManager.BROADCAST_SUCCESS;
}

3.3 collectReceiverComponents

private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType, int callingUid, int[] users) {
    List<ResolveInfo> receivers = null;
    try {
        for (int user : users) {
            // 过滤掉有Shell限制的用户
            ...
 
            List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
                    .queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
 
            // 如果目标不是系统用户, 过滤掉newReceivers列表中所有仅系统用户可见的广播
            ...
 
            if (receivers == null) {
                receivers = newReceivers;
            } else if (newReceivers != null) {
                // 遍历receivers和newReceivers列表, 将flags为ActivityInfo.FLAG_SINGLE_USER的广播添加到singleUserReceivers和receivers列表
                ...
            }
        }
    } catch (RemoteException ex) {
        // pm is in same process, this will never happen.
    }
    return receivers;
}

AMS.collectReceiverComponents过程:
1.该过程目的是收集BroadcastReceiver目标组件列表. 具体过程如下
2.遍历目标用户数组users,过滤掉有Shell限制的用户
3.执行PMS.queryIntentReceivers, 利用组件解析器ComponentResolver解析出BroadcastReceiver组件列表
4.过滤掉上述BroadcastReceiver组件列表中, 目标用户是非系统用户但是仅系统用户可见的广播
5.将上述组件列表中flags为ActivityInfo.FLAG_SINGLE_USER的广播添加到singleUserReceivers列表和receivers列表

4.PMS.queryIntentReceivers

[ -> frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java ]

调用链:queryIntentReceivers -> queryIntentReceiversInternal

@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent,
        String resolvedType, int flags, int userId) {
    return new ParceledListSlice<>(
            queryIntentReceiversInternal(intent, resolvedType, flags, userId, false /*allowDynamicSplits*/));
}

queryIntentReceiversInternal实现:

private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
        String resolvedType, int flags, int userId, boolean allowDynamicSplits) {
    // 检查userId在用户管理服务中是否能找到
    if (!sUserManager.exists(userId)) return Collections.emptyList();
 
    final int callingUid = Binder.getCallingUid();
    // 请求只能来自系统用户或具备INTERACT_ACROSS_USERS/INTERACT_ACROSS_USERS_FULL权限的用户, 否则抛异常
    mPermissionManager.enforceCrossUserPermission(callingUid, userId,
            false /*requireFullPermission*/, false /*checkShell*/, "query intent receivers");
 
    // 更新flags 
    flags = updateFlagsForResolve(flags, userId, intent, callingUid, false /*includeInstantApps*/);
    // 获取Component
    ComponentName comp = intent.getComponent();
    if (comp == null) {
        if (intent.getSelector() != null) {
            intent = intent.getSelector();
            comp = intent.getComponent();
        }
    }
 
    final String instantAppPkgName = getInstantAppPackageName(callingUid);
    if (comp != null) {
        final List<ResolveInfo> list = new ArrayList<>(1);
        final ActivityInfo ai = getReceiverInfo(comp, flags, userId);
        if (ai != null) {
            // 如下两种情况Activity不能使用. blockResolution为true
            // 1) the calling package is normal and the activity is within an instant application or
            // 2) the calling package is ephemeral and the activity is not visible to instant applications.
            ...
 
            if (!blockResolution) {
                ResolveInfo ri = new ResolveInfo();
                ri.activityInfo = ai;
                list.add(ri);
            }
        }
        // 过滤掉list中的临时的BroadcastReceiver组件
        return applyPostResolutionFilter(list, instantAppPkgName, allowDynamicSplits, callingUid, false, userId, intent);
    }
 
    synchronized (mPackages) {
        String pkgName = intent.getPackage();
        if (pkgName == null) {
            // 通过组件解析器ComponentResolver解析出符合条件的组件信息列表
            final List<ResolveInfo> result = mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
            // 过滤掉临时的Activity
            return applyPostResolutionFilter(result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId, intent);
        }
        // 获取包解析信息
        final PackageParser.Package pkg = mPackages.get(pkgName);
        if (pkg != null) {
            // 通过组件解析器ComponentResolver解析出符合条件的组件信息列表
            final List<ResolveInfo> result = mComponentResolver.queryReceivers(intent, resolvedType, flags, pkg.receivers, userId);
            // 过滤掉临时的Activity
            return applyPostResolutionFilter(result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId, intent);
        }
        return Collections.emptyList();
    }
}

PMS.queryIntentReceivers过程:
1.首先是边界条件检查:检查userId是否存在, 检查请求只能来自系统用户或具备INTERACT_ACROSS_USERS/INTERACT_ACROSS_USERS_FULL权限的用户.
2.利用组件解析器ComponentResolver解析出和BroadcastReceiver对应的组件列表List< ActivityInfo>, 过滤掉其中的临时组件并返回
(1)如果Intent.getComponent非空, 则根据Component解析
(2)否则根据MIME Type/scheme/action等信息解析(执行ComponentResolver.queryReceivers)

注意:
ComponentResolver:组件解析器. Resolves all Android component types [activities, services, providers and receivers].
PackageParser:包解析器

5.ComponentResolver.queryReceivers

[ -> frameworks/base/services/core/java/com/android/server/pm/ComponentResolver.java ]

List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags, int userId) {
    synchronized (mLock) {
        return mReceivers.queryIntent(intent, resolvedType, flags, userId);
    }
}

6.ActivityIntentResolver

[ -> frameworks/base/services/core/java/com/android/server/pm/ComponentResolver.java ]

6.1 queryIntent

private static final class ActivityIntentResolver extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
    @Override
    public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId) {
        if (!sUserManager.exists(userId)) return null;
        mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
        return super.queryIntent(intent, resolvedType, defaultOnly, userId);
    }
 
    List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags, int userId) {
        if (!sUserManager.exists(userId)) {
            return null;
        }
        mFlags = flags;
        return super.queryIntent(intent, resolvedType, (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
    }
 
    public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId) {
        String scheme = intent.getScheme();
 
        ArrayList<R> finalList = new ArrayList<R>();
 
        F[] firstTypeCut = null;
        F[] secondTypeCut = null;
        F[] thirdTypeCut = null;
        F[] schemeCut = null;
 
 
        // 找出和MIME Type匹配的所有filter
        if (resolvedType != null) {
            int slashpos = resolvedType.indexOf('/');
            if (slashpos > 0) {
                final String baseType = resolvedType.substring(0, slashpos);
                if (!baseType.equals("*")) {
                    if (resolvedType.length() != slashpos+2 || resolvedType.charAt(slashpos+1) != '*') {
                        firstTypeCut = mTypeToFilter.get(resolvedType);
                        secondTypeCut = mWildTypeToFilter.get(baseType);
                    } else {
                        firstTypeCut = mBaseTypeToFilter.get(baseType);
                        secondTypeCut = mWildTypeToFilter.get(baseType);
                    }
                    thirdTypeCut = mWildTypeToFilter.get("*");
                } else if (intent.getAction() != null) {
                    firstTypeCut = mTypedActionToFilter.get(intent.getAction());
                }
            }
        }
 
        // 找出和scheme匹配的所有filter
        if (scheme != null) {
            schemeCut = mSchemeToFilter.get(scheme);
        }
 
        // 找出和action匹配的所有filter
        if (resolvedType == null && scheme == null && intent.getAction() != null) {
            firstTypeCut = mActionToFilter.get(intent.getAction());
        }
 
        // 过滤掉以上各filter组中不符合条件的元素, 将其封装为ResolveInfo对象添加到finalList
        FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
        if (firstTypeCut != null) {
            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
                    scheme, firstTypeCut, finalList, userId);
        }
        if (secondTypeCut != null) {
            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
                    scheme, secondTypeCut, finalList, userId);
        }
        if (thirdTypeCut != null) {
            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
                    scheme, thirdTypeCut, finalList, userId);
        }
        if (schemeCut != null) {
            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
                    scheme, schemeCut, finalList, userId);
        }
        filterResults(finalList);
        // 按优先级降序排列
        sortResults(finalList);
 
        return finalList;
    }
}

ComponentResolver.queryReceivers -> ActivityIntentResolver.queryIntent过程:
1.找出符合条件的IntentFilter数组:
(1)找出MIME Type匹配的IntentFilter数组
(2)找出scheme匹配的IntentFilter数组
(3)找出action匹配的IntentFilter数组
2.以Intent和上述IntentFilter数组作为入参,调用ComponentResolver.buildResolveList获取符合条件的BroadcastReceiver组件信息列表List< ActivityResolveInfo>
3.将List< ActivityResolveInfo>按优先级降序排序并返回

6.2 queryIntentForPackage

调用链:queryIntentForPackage -> queryIntentFromList

List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
        int flags, List<PackageParser.Activity> packageActivities, int userId) {
    if (!sUserManager.exists(userId)) {
        return null;
    }
    if (packageActivities == null) {
        return null;
    }
    mFlags = flags;
    final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
    final int activitiesSize = packageActivities.size();
    ArrayList<PackageParser.ActivityIntentInfo[]> listCut = new ArrayList<>(activitiesSize);
 
    ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
    for (int i = 0; i < activitiesSize; ++i) {
        intentFilters = packageActivities.get(i).intents;
        if (intentFilters != null && intentFilters.size() > 0) {
            PackageParser.ActivityIntentInfo[] array = new PackageParser.ActivityIntentInfo[intentFilters.size()];
            intentFilters.toArray(array);
            listCut.add(array);
        }
    }
    return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
}

queryIntentFromList实现:

public List<R> queryIntentFromList(Intent intent, String resolvedType, boolean defaultOnly,
        ArrayList<F[]> listCut, int userId) {
    ArrayList<R> resultList = new ArrayList<R>();
 
    final boolean debug = localLOGV || ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
 
    FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
    final String scheme = intent.getScheme();
    int N = listCut.size();
    for (int i = 0; i < N; ++i) {
        buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, listCut.get(i), resultList, userId);
    }
    filterResults(resultList);
    sortResults(resultList);
    return resultList;
}

6.3 buildResolveList

private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
        boolean debug, boolean defaultOnly, String resolvedType, String scheme,
        F[] src, List<R> dest, int userId) {
    final String action = intent.getAction();
    final Uri data = intent.getData();
    final String packageName = intent.getPackage();
 
    final boolean excludingStopped = intent.isExcludingStopped();
 
    final int N = src != null ? src.length : 0;
    boolean hasNonDefaults = false;
    F filter;
    for (int i=0; i<N && (filter=src[i]) != null; i++) {
        int match;
 
        // 过滤掉target为stopped状态的filter
        if (excludingStopped && isFilterStopped(filter, userId)) {
            continue;
        }
 
        // 过滤掉packageName不匹配的filter
        if (packageName != null && !isPackageForFilter(packageName, filter)) {
            continue;
        }
 
        // 过滤掉重复filter
        if (!allowFilterResult(filter, dest)) {
            continue;
        }
 
        // filter各属性匹配
        match = filter.match(action, resolvedType, scheme, data, categories, TAG);
        if (match >= 0) {
            if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
                // 匹配成功, 将filter信息封装成ResolveInfo并添加到dest列表
                final R oneResult = newResult(filter, match, userId);
                if (oneResult != null) {
                    dest.add(oneResult);
                }
            } else {
                hasNonDefaults = true;
            }
        }
    }
}
 
 
@Override
protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info, int match, int userId) {
    // 各种边界条件检查包括: userId是否存在, Component和flag是否可用和匹配, PackageSetting是否为空, instant app和ephemeral app相关检查
    ...
     
    // 创建ResolveInfo对象并设置各属性
    final ResolveInfo res = new ResolveInfo();
    res.activityInfo = ai;
    if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
        res.filter = info;
    }
    res.handleAllWebDataURI = info.handleAllWebDataURI();
    res.priority = info.getPriority();
    res.preferredOrder = activity.owner.mPreferredOrder;
    res.match = match;
    res.isDefault = info.hasDefault;
    res.labelRes = info.labelRes;
    res.nonLocalizedLabel = info.nonLocalizedLabel;
    if (sPackageManagerInternal.userNeedsBadging(userId)) {
        res.noResourceId = true;
    } else {
        res.icon = info.icon;
    }
    res.iconResourceId = info.icon;
    res.system = res.activityInfo.applicationInfo.isSystemApp();
    res.isInstantAppAvailable = userState.instantApp;
    return res;
}

ComponentResolver.buildResolveList过程:
1.该方法主要做的事情:根据IntentFilter[]条件, 利用组件解析器ComponentResolver查找符合条件的BroadcastReceiver组件信息列表. 入参为Intent和数组IntentFilter[], 出参为List< ActivityResolveInfo>.
2.遍历IntentFilter数组, 过滤掉如下IntentFilter: target为stopped状态、packageName不匹配或者重复的filter
3.IntentFilter和Intent进行匹配, 如匹配成功, 则进行边界条件检查后将IntentFilter信息封装成ResolveInfo对象, 添加到dest列表返回
4.IntentFilter边界条件检查包括: userId是否存在, Component和flag是否可用和匹配, PackageSetting是否为空, instant app和ephemeral app相关检查

7.AMS.broadcastQueueForIntent

[ -> frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java ]

BroadcastQueue broadcastQueueForIntent(Intent intent) {
    if (isOnOffloadQueue(intent.getFlags())) {
        return mOffloadBroadcastQueue;
    }
 
    final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
    return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
}

8.BroadcastQueue

[ -> frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java ]

8.1 enqueueParallelBroadcastLocked

8.2 scheduleBroadcastsLocked

这小节参考文章 registerReceiver过程 第6节.

9.总结

ContextImpl.sendBroadcast过程:
1.边界和限制条件检查:
(1)根据各种限制设置intent的flags: 比如Instant App不能使用FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS, 广播不会发送到杀死的进程, 系统还没启动不允许启动新进程
(2)检查接收广播的userId是否正在运行
(3)权限和限制检查: 如CHANGE_DEVICE_IDLE_TEMP_WHITELIST权限, START_ACTIVITIES_FROM_BACKGROUND权限, OP_RUN_ANY_IN_BACKGROUND操作权限
(4)非系统用户不允许发送ProtectedBroadcast, 系统用户指(ROOT_UID/SYSTEM_UID/PHONE_UID/BLUETOOTH_UID/NFC_UID/SE_UID/NETWORK_STACK_UID)

2.特殊action处理:
(1)若action目标为发送给未启动的或后台的进程, 则Intent添加flags为FLAG_RECEIVER_INCLUDE_BACKGROUND
(2)若action为包管理器发出的和包移除相关的action, 则做相应逻辑处理. 如ACTION_UID_REMOVED/ACTION_PACKAGE_REMOVED/ACTION_PACKAGE_CHANGED/…

3.Sticky广播处理(仅针对sendStickyBroadcast):
(1)权限和条件检查包括: Manifest.permission.BROADCAST_STICKY权限检查, requiredPermissions和Component为空检查, mStickyBroadcasts重复广播检查
(2)将发送的广播Intent替换或插入到mStickyBroadcasts队列中相应位置

4.设置广播的目标用户数组users, 如果userId为USER_ALL则users为所有启动用户, 否则users为userId
5.执行AMS.collectReceiverComponents, 利用组件解析器ComponentResolver收集符合条件的BroadcastReceiver组件列表信息
6.若Intent.getComponent为空, 则执行ActivityIntentResolver.queryIntent, 解析出所有已注册的BroadcastReceiver组件列表
7.无序广播处理:将步骤6的广播入队到无序广播队列, 并执行广播接收器处理逻辑BroadcastQueue.scheduleBroadcastsLocked

8.有序广播处理(仅针对sendOrderedBroadcast):
(1)集合步骤5和6的BroadcastReceiver列表, 移除Package操作相关的广播ACTION_PACKAGE_ADDED/ACTION_PACKAGE_RESTARTED/ACTION_PACKAGE_DATA_CLEARED/ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
(2)若BroadcastReceiver列表非空. 如果原来广播队列就有相同Intent的广播且Intent.flags为FLAG_RECEIVER_REPLACE_PENDING, 则先把老的广播替换掉,并调用BroadcastQueue.performReceiveLocked对老广播执行广播接收操作;
否则将广播插入有序广播队列, 并调用BroadQueue.scheduleBroadcastsLocked处理下一个广播接收操作

广播发送过程总结:
1.先将广播添加到无序广播列表
2.找出该广播对应的所有接收器, 并执行广播接收器操作

本文原文发自 某学姐, 转载请保留出处, 谢谢.

Comments