分析通过 Intent 匹配启动 Activity 的过程

activity 信息存储

commitPackageSettings()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
private void commitPackageSettings(PackageParser.Package pkg,
                                   @Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting, UserHandle user,
                                   final @ScanFlags int scanFlags, boolean chatty) {
    // ......
    N = pkg.activities.size();
    r = null;
    for (i=0; i<N; i++) {
        // PackageParser.Package.activities 是解析安装包的
        // AndroidManifest.xml 文件的所有  activity 字段得到的
        PackageParser.Activity a = pkg.activities.get(i);
        // 修正进程名称,优先使用前者
        a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                                            a.info.processName);
        // 保存到  PackageManagerService.mActivities 中
        mActivities.addActivity(a, "activity");
    }
    // .....
}

ActivityIntentResolver.addActivity()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public final void addActivity(PackageParser.Activity a, String type) {
    // 已  Activity 的  ComponentName 和  PackageParser.Activity 作为键值对
    //存储与  ActivityIntentResolver.mActivities
    mActivities.put(a.getComponentName(), a);
    final int NI = a.intents.size();
    for (int j=0; j<NI; j++) {
        // 获取  intent 字段信息
        PackageParser.ActivityIntentInfo intent = a.intents.get(j);
        if ("activity".equals(type)) {
            final PackageSetting ps =
                mSettings.getDisabledSystemPkgLPr(intent.activity.info.packageName);
            final List<PackageParser.Activity> systemActivities =
                ps != null && ps.pkg != null ? ps.pkg.activities : null;
            // 根据策略调整给定  intent 的优先级;默认普通应用优先级为  0,开机向导优先级最高允许执行任何动作。
            adjustPriority(systemActivities, intent);
        }
        // 将  initen 字段中对应的  IntentFilter 加入到  PackageManagerService 中
        addFilter(intent);
    }
}

IntentResolver.addFilter()

ActivityIntentResolver 继承自 IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> ,直接调用父类的 addFilter()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public void addFilter(F f) {
    // 保存该  IntentFilter 信息
    mFilters.add(f);
    //除此之外,为了加快匹配工作的速度,PackageManagerService 还分类保存了  IntentFilter 的信息
    // mSchemeToFilter 用于保存  uri 中与  scheme 相关的  IntentFilter
    int numS = register_intent_filter(f, f.schemesIterator(),
                                      mSchemeToFilter, "      Scheme: ");
    // //按照  MIME type 存储  IntentFilter,分别定义了  mTypeToFilter、mBaseTypeToFilter 和  mWildTypeToFilter
    //与  MIME 的格式有关,代码较为简单,不深入分析
    int numT = register_mime_types(f, "      Type: ");
    if (numS == 0 && numT == 0) {
        //mActionToFilter 用于保存仅设置了  Action 条件的  IntentFilter
        register_intent_filter(f, f.actionsIterator(),
                               mActionToFilter, "      Action: ");
    }
    if (numT != 0) {
        //mTypedActionToFilter 用于保存既设置了  Action 条件,又设置了  Data 类型的  IntentFilter
        register_intent_filter(f, f.actionsIterator(),
                               mTypedActionToFilter, "      TypedAction: ");
    }
}

activity 信息查询

通过 PackageManagerService.resolveIntent() 方法查询 Intent 最佳匹配的 ResolveInfo 对象,没找到返回空。

resolveIntent()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
                                 int flags, int userId) {
    return resolveIntentInternal(intent, resolvedType, flags, userId, false,
                                 Binder.getCallingUid());
}

private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
                                          int flags, int userId, boolean resolveForStart, int filterCallingUid) {
    try {
        if (!sUserManager.exists(userId)) return null;
        final int callingUid = Binder.getCallingUid();
        flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart);
        mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                                                      false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
        // 查询  Intent 匹配项,可能有多个  ResolveInfo 对象
        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
                                                                      flags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/);
        // 选择最佳匹配项
        final ResolveInfo bestChoice =
            chooseBestActivity(intent, resolvedType, flags, query, userId);
        return bestChoice;
    } finally {
    }
}

queryIntentActivitiesInternal()

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
                                                                 String resolvedType, int flags, int filterCallingUid, int userId,
                                                                 boolean resolveForStart, boolean allowDynamicSplits) {
    if (!sUserManager.exists(userId)) return Collections.emptyList();
    // 获取相应的的及时应用包名
    final String instantAppPkgName = getInstantAppPackageName(filterCallingUid);
    // 权限检查
    mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
                                                  false /* requireFullPermission */, false /* checkShell */,
                                                  "query intent activities");
    // 获取包名和  ComponentName
    final String pkgName = intent.getPackage();
    ComponentName comp = intent.getComponent();
    if (comp == null) {
        if (intent.getSelector() != null) {
            intent = intent.getSelector();
            comp = intent.getComponent();
        }
    }

    flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart,
                                  comp != null || pkgName != null /*onlyExposedExplicitly*/);
    if (comp != null) {
        // Intent 指定了  ComponentName;也就是显示的
        final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
        // 根据  ComponentName 获取相应的  ActivityInfo
        final ActivityInfo ai = getActivityInfo(comp, flags, userId);
        if (ai != null) {
            // ...... 及时应用的相关处理
            final boolean blockResolution =
                !isTargetSameInstantApp
                && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
                    || (matchVisibleToInstantAppOnly && isCallerInstantApp
                        && isTargetHiddenFromInstantApp));
            if (!blockResolution) {
                final ResolveInfo ri = new ResolveInfo();
                ri.activityInfo = ai;
                list.add(ri);
            }
        }
        // 过滤掉  list 中的及时应用并返回
        return applyPostResolutionFilter(
                                         list, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,
                                         userId, intent);
    }
    // 下面是隐式的
    boolean sortResult = false;
    boolean addInstant = false;
    List<ResolveInfo> result;
    synchronized (mPackages) {
        if (pkgName == null) {
            // Intent 未指定包名
            // * 获取目标用户可以处理  Intent 的  IntentFilter
            List<CrossProfileIntentFilter> matchingFilters =
                getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
            // Check for results that need to skip the current profile.
            // * 返回目标用户中的  ResolveInfo 匹配(如果有)
            // * 检查需要跳过当前配置文件的结果。
            ResolveInfo xpResolveInfo  = querySkipCurrentProfileIntents(matchingFilters, intent,
                                                                        resolvedType, flags, userId);
            if (xpResolveInfo != null) {
                List<ResolveInfo> xpResult = new ArrayList<ResolveInfo>(1);
                xpResult.add(xpResolveInfo);
                return applyPostResolutionFilter(
                                                 filterIfNotSystemUser(xpResult, userId), instantAppPkgName,
                                                 allowDynamicSplits, filterCallingUid, resolveForStart, userId, intent);
            }

            // Check for results in the current profile.
            // 从  PackageManagerService.mActivities 中 查询能够响应  Intent 的  Activitys
            result = filterIfNotSystemUser(mActivities.queryIntent(
                                                                   intent, resolvedType, flags, userId), userId);
            // 是否允许及时应用
            addInstant = isInstantAppResolutionAllowed(intent, result, userId,
                                                       false /*skipPackageCheck*/);
            // Check for cross profile results.
            // 结果中有非负优先级的项则返回真
            boolean hasNonNegativePriorityResult = hasNonNegativePriority(result);
            // 返回目标用户中的  ResolveInfo 匹配(如果有)
            // * 检查当前配置文件的结果。
            xpResolveInfo = queryCrossProfileIntents(
                                                     matchingFilters, intent, resolvedType, flags, userId,
                                                     hasNonNegativePriorityResult);
            // 用户合法性检查
            if (xpResolveInfo != null && isUserEnabled(xpResolveInfo.targetUserId)) {
                boolean isVisibleToUser = filterIfNotSystemUser(
                                                                Collections.singletonList(xpResolveInfo), userId).size() > 0;
                if (isVisibleToUser) {
                    result.add(xpResolveInfo);
                    sortResult = true;
                }
            }
            // Intent 含有  web uri
            if (intent.hasWebURI()) {
                CrossProfileDomainInfo xpDomainInfo = null;
                final UserInfo parent = getProfileParent(userId);
                if (parent != null) {
                    // 获取域名信息
                    xpDomainInfo = getCrossProfileDomainPreferredLpr(intent, resolvedType,
                                                                     flags, userId, parent.id);
                }
                if (xpDomainInfo != null) {
                    if (xpResolveInfo != null) {
                        // If we didn't remove it, the cross-profile ResolveInfo would be twice
                        // in the result.
                        // 前面添加过先移除,防止加入两次
                        result.remove(xpResolveInfo);
                    }
                    if (result.size() == 0 && !addInstant) {
                        // No result in current profile, but found candidate in parent user.
                        // And we are not going to add emphemeral app, so we can return the
                        // result straight away.
                        // 当前用户中没有找到匹配项,返回父用户的
                        result.add(xpDomainInfo.resolveInfo);
                        return applyPostResolutionFilter(result, instantAppPkgName,
                                                         allowDynamicSplits, filterCallingUid, resolveForStart, userId,
                                                         intent);
                    }
                } else if (result.size() <= 1 && !addInstant) {
                    // No result in parent user and <= 1 result in current profile, and we
                    // are not going to add emphemeral app, so we can return the result without
                    // further processing.
                    // 父用户中没有匹配项,而当前用户最多只有一个匹配项,直接返回结果
                    return applyPostResolutionFilter(result, instantAppPkgName,
                                                     allowDynamicSplits, filterCallingUid, resolveForStart, userId,
                                                     intent);
                }
                // We have more than one candidate (combining results from current and parent
                // profile), so we need filtering and sorting.
                // 有多个结果项过滤结果并排序
                result = filterCandidatesWithDomainPreferredActivitiesLPr(
                                                                          intent, flags, result, xpDomainInfo, userId);
                sortResult = true;
            }
        } else {
            // Intent 指定了包名,通过包名获取相应的  PackageParser.Package 对象
            final PackageParser.Package pkg = mPackages.get(pkgName);
            result = null;
            if (pkg != null) {
                // 有些  Activity 要求系统用户才能使用,如果不是系统用户则过滤掉
                result = filterIfNotSystemUser(
                                               // 通过包名获取所有的  ResolveInfo 对象
                                               mActivities.queryIntentForPackage(
                                                                                 intent, resolvedType, flags, pkg.activities, userId),
                                               userId);
            }
            // 及时应用
            if (result == null || result.size() == 0) {
                // the caller wants to resolve for a particular package; however, there
                // were no installed results, so, try to find an ephemeral result
                addInstant = isInstantAppResolutionAllowed(
                                                           intent, null /*result*/, userId, true /*skipPackageCheck*/);
                if (result == null) {
                    result = new ArrayList<>();
                }
            }
        }
    }
    // 没有找到对应的  Activity;调用及时应用安装器来安装相应的及时应用?
    if (addInstant) {
        result = maybeAddInstantAppInstaller(
                                             result, intent, resolvedType, flags, userId, resolveForStart);
    }
    // 结果排序
    if (sortResult) {
        Collections.sort(result, mResolvePrioritySorter);
    }
    // 过滤掉及时应用返回
    return applyPostResolutionFilter(
                                     result, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,
                                     userId, intent);
}

我们看到隐式启动优先匹配其他用户能响应 IntentActivity ;如果前者不存在才从当前用户中查询匹配项;谷歌可能认为启动相同用户下的 Activity 应该优先使用显示启动。

getMatchingCrossProfileIntentFilters()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
private List<CrossProfileIntentFilter> getMatchingCrossProfileIntentFilters(Intent intent,
                                                                            String resolvedType, int userId) {
    CrossProfileIntentResolver resolver = mSettings.mCrossProfileIntentResolvers.get(userId);
    if (resolver != null) {
        return resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, userId);
    }
    return null;
}
// CrossProfileIntentResolver.class 继承自  IntentResolver.class;
// 所以实际调用的是  IntentResolver.queryIntent() 方法
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;

    // If the intent includes a MIME type, then we want to collect all of
    // the filters that match that MIME type.
    // Intent 指定了  MIME 类型,这种格式的:<data android:mimeType="video/mpeg4"/>
    if (resolvedType != null) {
        int slashpos = resolvedType.indexOf('/');
        if (slashpos > 0) {
            // 类似这种 <data android:mimeType="video/mpeg4"/>
            final String baseType = resolvedType.substring(0, slashpos);
            if (!baseType.equals("*")) {
                if (resolvedType.length() != slashpos+2
                    || resolvedType.charAt(slashpos+1) != '*') {
                    // Not a wild card, so we can just look for all filters that
                    // completely match or wildcards whose base type matches.
                    firstTypeCut = mTypeToFilter.get(resolvedType);
                    secondTypeCut = mWildTypeToFilter.get(baseType);
                } else {
                    // 这种格式的:<data android:mimeType="video/*"/>
                    // We can match anything with our base type.
                    firstTypeCut = mBaseTypeToFilter.get(baseType);
                    secondTypeCut = mWildTypeToFilter.get(baseType);
                }
                // Any */* types always apply, but we only need to do this
                // if the intent type was not already */*.
                thirdTypeCut = mWildTypeToFilter.get("*");
            } else if (intent.getAction() != null) {
                // The intent specified any type ({@literal *}/*).  This
                // can be a whole heck of a lot of things, so as a first
                // cut let's use the action instead.
                // 这种格式的:<data android:mimeType="*/*"/>
                // 这种格式是无效的直接使用  Action 代替
                firstTypeCut = mTypedActionToFilter.get(intent.getAction());
            }
        }
    }

    // If the intent includes a data URI, then we want to collect all of
    // the filters that match its scheme (we will further refine matches
    // on the authority and path by directly matching each resulting filter).
    if (scheme != null) {
        schemeCut = mSchemeToFilter.get(scheme);
    }

    // If the intent does not specify any data -- either a MIME type or
    // a URI -- then we will only be looking for matches against empty
    // data.
    if (resolvedType == null && scheme == null && intent.getAction() != null) {
        firstTypeCut = mActionToFilter.get(intent.getAction());
    }
    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;
}

querySkipCurrentProfileIntents() & queryCrossProfileIntents()

这两个方法差别多,只是针对 PackageManager.SKIP_CURRENT_PROFILE flag 分别处理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
private ResolveInfo querySkipCurrentProfileIntents(
                                                   List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
                                                   int flags, int sourceUserId) {
    if (matchingFilters != null) {
        int size = matchingFilters.size();
        for (int i = 0; i < size; i ++) {
            CrossProfileIntentFilter filter = matchingFilters.get(i);
            if ((filter.getFlags() & PackageManager.SKIP_CURRENT_PROFILE) != 0) {
                // Checking if there are activities in the target user that can handle the
                // intent.
                ResolveInfo resolveInfo = createForwardingResolveInfo(filter, intent,
                                                                      resolvedType, flags, sourceUserId);
                if (resolveInfo != null) {
                    return resolveInfo;
                }
            }
        }
    }
    return null;
}

// Return matching ResolveInfo in target user if any.
private ResolveInfo queryCrossProfileIntents(
                                             List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
                                             int flags, int sourceUserId, boolean matchInCurrentProfile) {
    if (matchingFilters != null) {
        // Two {@link CrossProfileIntentFilter}s can have the same targetUserId and
        // match the same intent. For performance reasons, it is better not to
        // run queryIntent twice for the same userId
        SparseBooleanArray alreadyTriedUserIds = new SparseBooleanArray();
        int size = matchingFilters.size();
        for (int i = 0; i < size; i++) {
            CrossProfileIntentFilter filter = matchingFilters.get(i);
            int targetUserId = filter.getTargetUserId();
            boolean skipCurrentProfile =
                (filter.getFlags() & PackageManager.SKIP_CURRENT_PROFILE) != 0;
            boolean skipCurrentProfileIfNoMatchFound =
                (filter.getFlags() & PackageManager.ONLY_IF_NO_MATCH_FOUND) != 0;
            if (!skipCurrentProfile && !alreadyTriedUserIds.get(targetUserId)
                && (!skipCurrentProfileIfNoMatchFound || !matchInCurrentProfile)) {
                // Checking if there are activities in the target user that can handle the
                // intent.
                ResolveInfo resolveInfo = createForwardingResolveInfo(filter, intent,
                                                                      resolvedType, flags, sourceUserId);
                if (resolveInfo != null) return resolveInfo;
                alreadyTriedUserIds.put(targetUserId, true);
            }
        }
    }
    return null;
}

createForwardingResolveInfo()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
private ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter, Intent intent,
                                                String resolvedType, int flags, int sourceUserId) {
    int targetUserId = filter.getTargetUserId();
    List<ResolveInfo> resultTargetUser = mActivities.queryIntent(intent,
                                                                 resolvedType, flags, targetUserId);
    if (resultTargetUser != null && isUserEnabled(targetUserId)) {
        // If all the matches in the target profile are suspended, return null.
        for (int i = resultTargetUser.size() - 1; i >= 0; i--) {
            if ((resultTargetUser.get(i).activityInfo.applicationInfo.flags
                 & ApplicationInfo.FLAG_SUSPENDED) == 0) {
                return createForwardingResolveInfoUnchecked(filter, sourceUserId,
                                                            targetUserId);
            }
        }
    }
    return null;
}

private ResolveInfo createForwardingResolveInfoUnchecked(IntentFilter filter,
                                                         int sourceUserId, int targetUserId) {
    ResolveInfo forwardingResolveInfo = new ResolveInfo();
    long ident = Binder.clearCallingIdentity();
    boolean targetIsProfile;
    try {
        targetIsProfile = sUserManager.getUserInfo(targetUserId).isManagedProfile();
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
    String className;
    if (targetIsProfile) {
        className = FORWARD_INTENT_TO_MANAGED_PROFILE;
    } else {
        className = FORWARD_INTENT_TO_PARENT;
    }
    ComponentName forwardingActivityComponentName = new ComponentName(
                                                                      mAndroidApplication.packageName, className);
    ActivityInfo forwardingActivityInfo = getActivityInfo(forwardingActivityComponentName, 0,
                                                          sourceUserId);
    if (!targetIsProfile) {
        forwardingActivityInfo.showUserIcon = targetUserId;
        forwardingResolveInfo.noResourceId = true;
    }
    forwardingResolveInfo.activityInfo = forwardingActivityInfo;
    forwardingResolveInfo.priority = 0;
    forwardingResolveInfo.preferredOrder = 0;
    forwardingResolveInfo.match = 0;
    forwardingResolveInfo.isDefault = true;
    forwardingResolveInfo.filter = filter;
    forwardingResolveInfo.targetUserId = targetUserId;
    return forwardingResolveInfo;
}

chooseBestActivity()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
                                       int flags, List<ResolveInfo> query, int userId) {
    if (query != null) {
        final int N = query.size();
        if (N == 1) {
            // 唯一的  Activity 能处理该  Intent 直接返回
            return query.get(0);
        } else if (N > 1) {
            final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
            // If there is more than one activity with the same priority,
            // then let the user decide between them.
            // 如果有多个优先级相同的  Activity 能处理该  Intent,则让用户决定使用哪一个
            ResolveInfo r0 = query.get(0);
            ResolveInfo r1 = query.get(1);
            // If the first activity has a higher priority, or a different
            // default, then it is always desirable to pick it.
            // 首个优先级更高选择首个,结果列表是按优先级降序排列的
            if (r0.priority != r1.priority
                || r0.preferredOrder != r1.preferredOrder
                || r0.isDefault != r1.isDefault) {
                return query.get(0);
            }
            // If we have saved a preference for a preferred activity for
            // this Intent, use that.
            // 如果我们有保存处理该  Intent 的  Activity,则直接返回
            ResolveInfo ri = findPreferredActivity(intent, resolvedType,
                                                   flags, query, r0.priority, true, false, debug, userId);
            if (ri != null) {
                return ri;
            }
            // If we have an ephemeral app, use it
            // 如果有及时应用匹配使用及时应用
            for (int i = 0; i < N; i++) {
                ri = query.get(i);
                if (ri.activityInfo.applicationInfo.isInstantApp()) {
                    final String packageName = ri.activityInfo.packageName;
                    final PackageSetting ps = mSettings.mPackages.get(packageName);
                    final long packedStatus = getDomainVerificationStatusLPr(ps, userId);
                    final int status = (int)(packedStatus >> 32);
                    if (status != INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) {
                        return ri;
                    }
                }
            }
            // 无法确认具体使用哪个结果,ResolverActivity 显示所有结果供用户选择
            ri = new ResolveInfo(mResolveInfo);
            ri.activityInfo = new ActivityInfo(ri.activityInfo);
            ri.activityInfo.labelRes = ResolverActivity.getLabelRes(intent.getAction());
            // If all of the options come from the same package, show the application's
            // label and icon instead of the generic resolver's.
            // Some calls like Intent.resolveActivityInfo query the ResolveInfo from here
            // and then throw away the ResolveInfo itself, meaning that the caller loses
            // the resolvePackageName. Therefore the activityInfo.labelRes above provides
            // a fallback for this case; we only set the target package's resources on
            // the ResolveInfo, not the ActivityInfo.
            final String intentPackage = intent.getPackage();
            if (!TextUtils.isEmpty(intentPackage) && allHavePackage(query, intentPackage)) {
                final ApplicationInfo appi = query.get(0).activityInfo.applicationInfo;
                ri.resolvePackageName = intentPackage;
                if (userNeedsBadging(userId)) {
                    ri.noResourceId = true;
                } else {
                    ri.icon = appi.icon;
                }
                ri.iconResourceId = appi.icon;
                ri.labelRes = appi.labelRes;
            }
            ri.activityInfo.applicationInfo = new ApplicationInfo(
                                                                  ri.activityInfo.applicationInfo);
            if (userId != 0) {
                ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId,
                                                                        UserHandle.getAppId(ri.activityInfo.applicationInfo.uid));
            }
            // Make sure that the resolver is displayable in car mode
            if (ri.activityInfo.metaData == null) ri.activityInfo.metaData = new Bundle();
            ri.activityInfo.metaData.putBoolean(Intent.METADATA_DOCK_HOME, true);
            return ri;
        }
    }
    // 列表为空,表明没有  Activity 能处理该 Intent,直接返回空
    return null;
}