[start-activity]PackageManagerService
2021/7/31 23:09:58
本文主要是介绍[start-activity]PackageManagerService,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录- 概述
- 1. 调用流程
- 源码解析
- framework层
- 1. [PMS内部类]PackageManagerInternalImpl类
- 1.1 resolveIntent-解析intent-获取activity的信息-包的位置-activity的名字等-ActivityInfo信息
- 1.2 resolveIntentInternal-解析intent信息
- 2. PackageManagerService类
- 2.1 queryIntentActivitiesInternal-根据intent查询activity的信息
- 2.2 getActivityInfo-获取activityInfo信息
- 3. ComponentResolver类
- 3.1 getActivity-根据component名字获取activityinfo信息
- 4. Settings类
- 4.1 isEnabledAndMatchLPr
- 5. PackageSetting类
- 应用接口层
- 1. ResolveInfo类
- 2. PackageParser类
- 2.1 generateActivityInfo-根据PackageParser.Activity的信息构建ActivityInfo信息
- 3. ActivityInfo类
- 补充
- 1. Android分层
- 问题
- 1. 各个类有啥用?
- 2. PMS怎么找到activity的class的,然后加载起来
- 3. AndroidManifest.xml是怎么解析的?APK是怎么解析的?对应哪些类-start PMS中-或者安装应用中解析
- 参考
概述
在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中-或者安装应用中解析
参考
这篇关于[start-activity]PackageManagerService的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-24怎么切换 Git 项目的远程仓库地址?-icode9专业技术文章分享
- 2024-12-24怎么更改 Git 远程仓库的名称?-icode9专业技术文章分享
- 2024-12-24更改 Git 本地分支关联的远程分支是什么命令?-icode9专业技术文章分享
- 2024-12-24uniapp 连接之后会被立马断开是什么原因?-icode9专业技术文章分享
- 2024-12-24cdn 路径可以指定规则映射吗?-icode9专业技术文章分享
- 2024-12-24CAP:Serverless?+AI?让应用开发更简单
- 2024-12-23新能源车企如何通过CRM工具优化客户关系管理,增强客户忠诚度与品牌影响力
- 2024-12-23原创tauri2.1+vite6.0+rust+arco客户端os平台系统|tauri2+rust桌面os管理
- 2024-12-23DevExpress 怎么实现右键菜单(Context Menu)显示中文?-icode9专业技术文章分享
- 2024-12-22怎么通过控制台去看我的页面渲染的内容在哪个文件中呢-icode9专业技术文章分享