- 概述
- 源码解析
- 补充
- 问题
- 参考
概述
在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