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 {@Overridepublic ResolveInfo resolveIntent(Intent intent, String resolvedType,int flags, int userId, boolean resolveForStart, int filterCallingUid) {return resolveIntentInternal(intent, resolvedType, flags, userId, resolveForStart, filterCallingUid);}@Overridepublic 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详细信息的查询
@Overridepublic 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. 查询安装的应用,看是否有匹配的intentfinal 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); //为nullmPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,false /* requireFullPermission */, false /* checkShell */,"query intent activities");final String pkgName = intent.getPackage();// com.android.gallery3dComponentName 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*/);// 852992if (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的时候,不走下面// readerboolean 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 resultaddInstant = 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);的相关方法
@Overridepublic 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启动的相关详细信息了