Android 11.0 pms中关于启动app时获取app的ActivityInfo信息相关源码分析

1.前言

在11.0的系统rom定制化开发中,在对于app启动时,通过Launcher调用pms来查询app的相关ActivityInfo的相关信息,然后调用
ams来启动activity,这篇来分析pms中获取app的ActivityInfo的相关信息的相关源码分析

2.pms中关于启动app时获取app的ActivityInfo信息相关源码分析的核心类

frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java

3.pms中关于启动app时获取app的ActivityInfo信息相关源码分析的核心功能分析和实现


       private class PackageManagerInternalImpl extends PackageManagerInternal {
            @Override
            public ResolveInfo resolveIntent(Intent intent, String resolvedType,
                    int flags, int userId, boolean resolveForStart, int filterCallingUid) {
                return resolveIntentInternal(
                        intent, resolvedType, flags, userId, resolveForStart, filterCallingUid);
            }
     
            @Override
            public ResolveInfo resolveService(Intent intent, String resolvedType,
                    int flags, int userId, int callingUid) {
                return resolveServiceInternal(intent, resolvedType, flags, userId, callingUid);
            }
    ...
    }

在PackageManagerService的内部私有类PackageManagerInternalImpl中的相关源码中可以看出,在对
PackageManagerInternal抽象类的实现,PackageManager的接口实现,PMS对外接口实现
resolveIntent(Intent intent, String resolvedType,
                int flags, int userId, boolean resolveForStart, int filterCallingUid)
是具体调用pms的resolveIntentInternal(Intent intent, String resolvedType,
            int flags, int userId, boolean resolveForStart, int filterCallingUid)
来实现对app详细信息的查询

      @Override
        public ResolveInfo resolveIntent(Intent intent, String resolvedType,
                int flags, int userId) {
            return resolveIntentInternal(intent, resolvedType, flags, userId, false,
                    Binder.getCallingUid());
        }
     
        /**
         * Normally instant apps can only be resolved when they're visible to the caller.
         * However, if {@code resolveForStart} is {@code true}, all instant apps are visible
         * since we need to allow the system to start any installed application.
         */
        private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
                int flags, int userId, boolean resolveForStart, int filterCallingUid) {
            try {
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
     
                if (!sUserManager.exists(userId)) return null;
                final int callingUid = Binder.getCallingUid(); system用户
    // 更新flags,和instant app和direct app有关;
                flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart);
                mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                        false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
     
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
    // 1. 查询安装的应用,看是否有匹配的intent
                final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
                        flags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/);
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    // 选择最匹配的activity,因为query是个list;但是这里list大小为1,所以直接返回了
                final ResolveInfo bestChoice =
                        chooseBestActivity(intent, resolvedType, flags, query, userId);
                return bestChoice;
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
        }

通过上述在PackageManagerService.java中的相关源码的分析得知,在
 resolveIntentInternal(Intent intent, String resolvedType,
            int flags, int userId, boolean resolveForStart, int filterCallingUid)
中来查询app的相关详细信息,在chooseBestActivity(intent, resolvedType, flags, query, userId);中来选择最合适的app详细返回,在queryIntentActivitiesInternal中,具体查询app的详细信息

       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);    //为null
            mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
                    false /* requireFullPermission */, false /* checkShell */,
                    "query intent activities");
            final String pkgName = intent.getPackage();// com.android.gallery3d
            ComponentName comp = intent.getComponent();// ComponentInfo{com.android.gallery3d/com.android.gallery3d.app.GalleryActivity}
            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*/);// 852992
            if (comp != null) {
                final List<ResolveInfo> list = new ArrayList<>(1);
                // 1. 这里获取activityInfo信息
                final ActivityInfo ai = getActivityInfo(comp, flags, userId);
                if (ai != null) {
                    // When specifying an explicit component, we prevent the activity from being
                    // used when either 1) the calling package is normal and the activity is within
                    // an ephemeral application or 2) the calling package is ephemeral and the
                    // activity is not visible to ephemeral applications.
                    final boolean matchInstantApp =
                            (flags & PackageManager.MATCH_INSTANT) != 0;
                    final boolean matchVisibleToInstantAppOnly =
                            (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
                    final boolean matchExplicitlyVisibleOnly =
                            (flags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
                    final boolean isCallerInstantApp =
                            instantAppPkgName != null;
                    final boolean isTargetSameInstantApp =
                            comp.getPackageName().equals(instantAppPkgName);
                    final boolean isTargetInstantApp =
                            (ai.applicationInfo.privateFlags
                                    & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
                    final boolean isTargetVisibleToInstantApp =
                            (ai.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
                    final boolean isTargetExplicitlyVisibleToInstantApp =
                            isTargetVisibleToInstantApp
                            && (ai.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
                    final boolean isTargetHiddenFromInstantApp =
                            !isTargetVisibleToInstantApp
                            || (matchExplicitlyVisibleOnly && !isTargetExplicitlyVisibleToInstantApp);
                    final boolean blockResolution =
                            !isTargetSameInstantApp
                            && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
                                    || (matchVisibleToInstantAppOnly && isCallerInstantApp
                                            && isTargetHiddenFromInstantApp));
                    if (!blockResolution) {
                        final ResolveInfo ri = new ResolveInfo();
                        // 根据activityInfo信息,新建了ResolveInfo信息
                        ri.activityInfo = ai;
                        list.add(ri);
                    }
                }// 过滤resolveInfo信息,在这里直接返回了
                return applyPostResolutionFilter(
                        list, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,
                        userId, intent);
            }
    // 当cmp不为null的时候,不走下面
            // reader
            boolean sortResult = false;
            boolean addInstant = false;
            List<ResolveInfo> result;
            synchronized (mPackages) {
                if (pkgName == null) {
                    List<CrossProfileIntentFilter> matchingFilters =
                            getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
                    // Check for results that need to skip the current profile.
                    ResolveInfo xpResolveInfo  = querySkipCurrentProfileIntents(matchingFilters, intent,
                            resolvedType, flags, userId);
                    if (xpResolveInfo != null) {
                        List<ResolveInfo> xpResult = new ArrayList<>(1);
                        xpResult.add(xpResolveInfo);
                        return applyPostResolutionFilter(
                                filterIfNotSystemUser(xpResult, userId), 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) {
                        result = filterIfNotSystemUser(mComponentResolver.queryActivities(
                                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, RESOLVE_PRIORITY_SORTER);
            }
            return applyPostResolutionFilter(
                    result, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,
                    userId, intent);
        }

在PackageManagerService.java中的相关源码的分析得知,在queryIntentActivitiesInternal()中查询某个app的信息
会在comp != null的时候,调用getActivityInfo(comp, flags, userId);来查询具体信息,
接下来看下getActivityInfo(comp, flags, userId);的相关方法

     @Override
        public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
            return getActivityInfoInternal(component, flags, Binder.getCallingUid(), userId);
        }
        private ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
                int filterCallingUid, int userId) {
            if (!sUserManager.exists(userId)) return null;
            flags = updateFlagsForComponent(flags, userId, component);
     
            if (!isRecentsAccessingChildProfiles(Binder.getCallingUid(), userId)) {
                mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
                        false /* requireFullPermission */, false /* checkShell */, "get activity info");
            }
     
            synchronized (mPackages) {
                // 所有的安装包信息都解析到mComponentResolver中了,只要获取下就好了
                // 1. Activity{e6ed46 com.android.gallery3d/.app.GalleryActivity}
                PackageParser.Activity a = mComponentResolver.getActivity(component);
     
                if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
                // 2. 看是否匹配
                if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
                    // 3. PackageSetting很重要,包的位置信息;
                    PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                    if (ps == null) return null;
                    if (filterAppAccessLPr(ps, filterCallingUid, component, TYPE_ACTIVITY, userId)) {
                        return null;
                    }// 4. 根据PackageParser.Activity的信息构建ActivityInfo信息,这里返回
                    return PackageParser.generateActivityInfo(
                            a, flags, ps.readUserState(userId), userId);
                }
                if (mResolveComponentName.equals(component)) {
                    return PackageParser.generateActivityInfo(
                            mResolveActivity, flags, new PackageUserState(), userId);
                }
            }
            return null;
        }

在PackageManagerService.java中的相关源码的分析得知,在getActivityInfoInternal(ComponentName component, int flags,
            int filterCallingUid, int userId)中,获取当前的app的相关信息,然后返回一个ActivityInfo对象,就可以在
这里获取app启动的相关详细信息了

猜你喜欢

转载自blog.csdn.net/baidu_41666295/article/details/131403529