通过Intent查询组件

  • PMS 在系统运行过程中,很重要的一项工作就是通过 Intent 来查询组件信息。系统中响应 Intent 的组件有多个,所以返回的是列表而不是单个(比如 intent 启动的时候会让你自己选择启动哪个app,多个地图软件,多个邮箱软件等),查到的组件都是用类 ResolveInfo 来表示的,为了统一所有的组件都通过它来表示;
    PMS 中 Intent查询接口如下
    @Override
    public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivities(Intent intent,
            String resolvedType, int flags, int userId) {
        return new ParceledListSlice<>(
                    queryIntentActivitiesInternal(intent, resolvedType, flags, userId));
    }

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

    @Override
    public @NonNull ParceledListSlice<ResolveInfo> queryIntentServices(Intent intent,
            String resolvedType, int flags, int userId) {
        final int callingUid = Binder.getCallingUid();
        return new ParceledListSlice<>(queryIntentServicesInternal(
                intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/));
    }
    
    @Override
    public @NonNull ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent,
            String resolvedType, int flags, int userId) {
        return new ParceledListSlice<>(
                queryIntentContentProvidersInternal(intent, resolvedType, flags, userId));
    }

  • ResolveInfo 结构如下:
public class ResolveInfo implements Parcelable {
    private static final String TAG = "ResolveInfo";

    /**
     * The activity or broadcast receiver that corresponds to this resolution
     * match, if this resolution is for an activity or broadcast receiver.
     * Exactly one of {@link #activityInfo}, {@link #serviceInfo}, or
     * {@link #providerInfo} will be non-null.
     */
    public ActivityInfo activityInfo;

    /**
     * The service that corresponds to this resolution match, if this resolution
     * is for a service. Exactly one of {@link #activityInfo},
     * {@link #serviceInfo}, or {@link #providerInfo} will be non-null.
     */
    public ServiceInfo serviceInfo;

    /**
     * The provider that corresponds to this resolution match, if this
     * resolution is for a provider. Exactly one of {@link #activityInfo},
     * {@link #serviceInfo}, or {@link #providerInfo} will be non-null.
     */
    public ProviderInfo providerInfo;

    /**
     * An auxiliary response that may modify the resolved information. This is
     * only set under certain circumstances; such as when resolving instant apps
     * or components defined in un-installed splits.
     * @hide
     */
    public AuxiliaryResolveInfo auxiliaryInfo;
	
	// ....
	// ....
}
  • 下面以查找 queryIntentActivities 为例
    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");
        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) {
            final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
            final ActivityInfo ai = getActivityInfo(comp, flags, userId);
            if (ai != null) {
                // ...
                if (!blockResolution) {
                    final ResolveInfo ri = new ResolveInfo();
                    ri.activityInfo = ai;
                    list.add(ri);
                }
            }
            // 调用 applyPostResolutionFilter 查找
            return applyPostResolutionFilter(
                    list, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,
                    userId, intent);
        }
      // reader
        boolean sortResult = false;
        boolean addInstant = false;
        List<ResolveInfo> result;
        synchronized (mPackages) {
            // 如果 pkgName 未设置 则需要去系统的所有包中查找
            if (pkgName == null) {
                // 获取所有匹配的 intent filter
                List<CrossProfileIntentFilter> matchingFilters =
                        getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
                // Check for results that need to skip the current profile.
                // 检查带有 SKIP_CURRENT_PROFILE 标志的 filter
                ResolveInfo xpResolveInfo  = querySkipCurrentProfileIntents(matchingFilters, intent,
                        resolvedType, flags, userId);
                if (xpResolveInfo != null) {
                    // 优先匹配 SKIP_CURRENT_PROFILE 的 filter
                    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.
                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);
                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;
                    }
                }
                // 如果有webUri
                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 {
                // 如果有包名的话 在指定包中查找
                final PackageParser.Package pkg = mPackages.get(pkgName);
                result = null;
                if (pkg != null) {
                // 如果有 pkgName 查找到了 直接在通过指定包地址查找就行了
                    result = filterIfNotSystemUser(
                            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<>();
                    }
                }
            }
        }
        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);
	}

最后都是通过 applyPostResolutionFilter 返回,里面通过一些过滤掉一些不应该返回的 info

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值