[start-activity]PackageManagerService

概述

在launcher中点击应用来启动应用。

启动应用的过程中,用intent通过PMS来查询对应的activity信息,得到ActivityInfo信息和applicationInfo信息

1. 调用流程

PackageManagerInternalImpl类:resolveIntent
	-> PackageManagerService类:queryIntentActivitiesInternal
		-> getActivityInfo
			-> ComponentResolver类:getActivity(最主要是这个了):获得PackageParser.Activity,安装应用的时候,解析所有 Android 组件类型 [活动、服务、提供者和接收者]
			->  Settings类:mSettings.mPackages.get(component.getPackageName()):包名到packageSetting的映射,PackageSetting中有包的安装位置等信息
			-> PackageParser类:PackageParser.generateActivityInfo:根据PackageParser.Activity信息生成activityInfo
		-> ResolveInfo类:ri.activityInfo = ai;生成ResolveInfo对象并返回
	-> PackageManagerService类:chooseBestActivity:在list<ResolveInfo>中挑一个最匹配的

源码解析

framework层

1. [PMS内部类]PackageManagerInternalImpl类

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

PackageManagerInternal抽象类的实现,PackageManager的接口实现,PMS对外接口实现

1.1 resolveIntent-解析intent-获取activity的信息-包的位置-activity的名字等-ActivityInfo信息

        @Override
        public ResolveInfo resolveIntent(Intent intent, String resolvedType,
                int flags, int userId, boolean resolveForStart, int filterCallingUid) {
            return resolveIntentInternal(
                    intent, resolvedType, flags, userId, resolveForStart, filterCallingUid);
        }

1.2 resolveIntentInternal-解析intent信息

// intent:Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 pkg=com.android.gallery3d cmp=com.android.gallery3d/.app.GalleryActivity bnds=[350,426][460,552] }
// resolvedType为null;flags为66560;userId为0;resolveForStart为true;filterCallingUid为10081就是Launcher应用
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;// user 0肯定是存在的
            final int callingUid = Binder.getCallingUid();	// system用户
            // 更新flags,和instant app和direct app有关;更新后为852992
            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);

            final ResolveInfo bestChoice =
                // 选择最匹配的activity,因为query是个list;但是这里list大小为1,所以直接返回了
                    chooseBestActivity(intent, resolvedType, flags, query, userId);
            return bestChoice;
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }

2. PackageManagerService类

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

2.1 queryIntentActivitiesInternal-根据intent查询activity的信息

    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);
                }

                // Check for results in the current profile.
                result = filterIfNotSystemUser(mComponentResolver.queryActivities(
                        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;
                    }
                }
                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) {
                    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);
    }

2.2 getActivityInfo-获取activityInfo信息

    @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;
    }

3. ComponentResolver类

frameworks/base/services/core/java/com/android/server/pm/ComponentResolver.java

解析所有 Android 组件类型 [活动、服务、提供者和接收者]

3.1 getActivity-根据component名字获取activityinfo信息

    PackageParser.Activity getActivity(ComponentName component) {
        synchronized (mLock) {
            // ActivityIntentResolver类型中的mActivities
            // private final ArrayMap<ComponentName, PackageParser.Activity> mActivities = new ArrayMap<>();
            // 系统中所有的activity都在这里了
            return mActivities.mActivities.get(component);
        }
    }

4. Settings类

frameworks/base/services/core/java/com/android/server/pm/Settings.java

保存PMS有关动态设置的信息
    // 包名到packageSetting的映射,PackageSetting中有包的安装位置等信息
final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();

4.1 isEnabledAndMatchLPr

    boolean isEnabledAndMatchLPr(ComponentInfo componentInfo, int flags, int userId) {
        final PackageSetting ps = mPackages.get(componentInfo.packageName);
        if (ps == null) return false;

        final PackageUserState userState = ps.readUserState(userId);
        // 是否匹配
        return userState.isMatch(componentInfo, flags);
    }

5. PackageSetting类

./frameworks/base/services/core/java/com/android/server/pm/PackageSetting.java

特定包的设置数据,如代码路径,res路径,pkgFlags等
(1)pkg	PackageParser类,里面有activities,保存activity信息,里面有className,可以加载java class
(2)codePath,可以知道代码的路径信息

应用接口层

1. ResolveInfo类

frameworks/base/core/java/android/content/pm/ResolveInfo.java

对应AndroidManifest.xml's中intent标签中的内容,活动、服务、提供者和接收者的信息。
(1)ActivityInfo
(2)ServiceInfo

2. PackageParser类

frameworks/base/core/java/android/content/pm/PackageParser.java

hide类,应用不可见;用来解析磁盘上的APK文件的;
有很多的内部类:Activity,Service,Provider,Instrumentation,IntentInfo,ActivityIntentInfo等

2.1 generateActivityInfo-根据PackageParser.Activity的信息构建ActivityInfo信息

    @UnsupportedAppUsage
    public static final ActivityInfo generateActivityInfo(Activity a, int flags,
            PackageUserState state, int userId) {
        if (a == null) return null;
        if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
            return null;
        }
        if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
            updateApplicationInfo(a.info.applicationInfo, flags, state);
            return a.info;
        }
        // Make shallow copies so we can store the metadata safely
        ActivityInfo ai = new ActivityInfo(a.info);
        ai.metaData = a.metaData;
        ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
        return ai;
    }

3. ActivityInfo类

./frameworks/base/core/java/android/content/pm/ActivityInfo.java

对应AndroidManifest.xml的activity和receiver的标签

补充

1. Android分层

应用层
应用层接口(一般在frameworks/base/core/java/android/目录下;在developer.android.com网站中有对应手册的,都是应用层接口)
framework服务层(一般在frameworks/base/services/core/java/com/android/server/目录下)
framework层的JNI层和应用层接口的JNI层
native服务层(c/c++层)
hal层
系统调用层
kernel层

问题

1. 各个类有啥用?


PackageSetting

2. PMS怎么找到activity的class的,然后加载起来

3. AndroidManifest.xml是怎么解析的?APK是怎么解析的?对应哪些类-start PMS中-或者安装应用中解析

参考

posted @ 2021-07-31 22:15  pyjetson  阅读(385)  评论(0编辑  收藏  举报