Android6.0 AMS启动Activity(六) AMS与PKMS关系(通过Intent获取ActivityInfo)

之前几篇博客分析AMS中启动Activity的时候,我们把主要流程理的差不多了。今天主要看下AMS中通过PKMS来获取ActivityInfo。


一、AMS通过PKMS获取ActivityInfo

之前我们知道startActivity流程,先是在AMS中调用startActivity然后调用startActivityMayWait函数,在这个函数中调用了resolveActivity来解析ActivityInfo信息。后面这个函数继续往后会调用startActivityLocked函数,在这个函数中会新建一个ActivityRecord对象,这个对象的processName和info.applicartionInfo.uid这两个值在后续进程启动的时候起到很关键的作用,用来判断进程是否启动,这个在之前的博客中已经分析过了。而processName是利用ActivityInfo的processName。而info.applicationInfo.uid也是ActivityInfo中的ApplicationInfo的值。

[cpp] view plain copy
  1. final int startActivityMayWait(IApplicationThread caller, int callingUid,  
  2.         String callingPackage, Intent intent, String resolvedType,  
  3.         IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,  
  4.         IBinder resultTo, String resultWho, int requestCode, int startFlags,  
  5.         ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,  
  6.         Bundle options, boolean ignoreTargetSecurity, int userId,  
  7.         IActivityContainer iContainer, TaskRecord inTask) {  
  8.     // Refuse possible leaked file descriptors  
  9.     if (intent != null && intent.hasFileDescriptors()) {  
  10.         throw new IllegalArgumentException("File descriptors passed in Intent");  
  11.     }  
  12.     boolean componentSpecified = intent.getComponent() != null;  
  13.   
  14.     // Don't modify the client's object!  
  15.     intent = new Intent(intent);  
  16.   
  17.     // Collect information about the target of the Intent.  
  18.     ActivityInfo aInfo =  
  19.             resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);  

那我们下面来看看这个resolveActivity函数,这个函数最终还是通过PKMS的resolveIntent函数来获取ResolveInfo,而ActivityInfo是其中的一个变量。

[cpp] view plain copy
  1. ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,  
  2.         ProfilerInfo profilerInfo, int userId) {  
  3.     // Collect information about the target of the Intent.  
  4.     ActivityInfo aInfo;  
  5.     try {  
  6.         ResolveInfo rInfo =  
  7.             AppGlobals.getPackageManager().resolveIntent(  
  8.                     intent, resolvedType,  
  9.                     PackageManager.MATCH_DEFAULT_ONLY  
  10.                                 | ActivityManagerService.STOCK_PM_FLAGS, userId);  
  11.         aInfo = rInfo != null ? rInfo.activityInfo : null;  
  12.     } catch (RemoteException e) {  
  13.         aInfo = null;  
  14.     }  
  15.   
  16.     if (aInfo != null) {  
  17.         // Store the found target back into the intent, because now that  
  18.         // we have it we never want to do this again.  For example, if the  
  19.         // user navigates back to this point in the history, we should  
  20.         // always restart the exact same activity.  
  21.         intent.setComponent(new ComponentName(  
  22.                 aInfo.applicationInfo.packageName, aInfo.name));  
  23.   
  24.         // Don't debug things in the system process  
  25.         if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {  
  26.             if (!aInfo.processName.equals("system")) {  
  27.                 mService.setDebugApp(aInfo.processName, truefalse);  
  28.             }  
  29.         }  
  30.   
  31.         if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {  
  32.             if (!aInfo.processName.equals("system")) {  
  33.                 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);  
  34.             }  
  35.         }  
  36.   
  37.         if (profilerInfo != null) {  
  38.             if (!aInfo.processName.equals("system")) {  
  39.                 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo);  
  40.             }  
  41.         }  
  42.     }  
  43.     return aInfo;  
  44. }  


二、PKMS获取ActivityInfo

我们来看下PKMS的resolveIntent函数,先看下是否有权限,然后调用queryIntentActivities来获取满足条件的ResolveInfo,然后调用chooseBestActivity挑选最合适的。

[cpp] view plain copy
  1. @Override  
  2. public ResolveInfo resolveIntent(Intent intent, String resolvedType,  
  3.         int flags, int userId) {  
  4.     if (!sUserManager.exists(userId)) return null;  
  5.     enforceCrossUserPermission(Binder.getCallingUid(), userId, falsefalse"resolve intent");  
  6.     List query = queryIntentActivities(intent, resolvedType, flags, userId);  
  7.     return chooseBestActivity(intent, resolvedType, flags, query, userId);  
  8. }  

所以这里我们主要看下queryIntentActivities函数,先会检查权限。然后获取ComponentName,如果不为空,那么Intent是指定了模块,只有一个匹配项。如果没有指定模块,还要区分是否指定了包名。

[cpp] view plain copy
  1. public List queryIntentActivities(Intent intent,  
  2.         String resolvedType, int flags, int userId) {  
  3.     if (!sUserManager.exists(userId)) return Collections.emptyList();  
  4.     enforceCrossUserPermission(Binder.getCallingUid(), userId, falsefalse"query intent activities");  
  5.     ComponentName comp = intent.getComponent();  
  6.     if (comp == null) {  
  7.         if (intent.getSelector() != null) {  
  8.             intent = intent.getSelector();  
  9.             comp = intent.getComponent();  
  10.         }  
  11.     }  
  12.   
  13.     if (comp != null) {//如果Intent中指定了模块,只会有一个匹配项  
  14.         final List list = new ArrayList(1);  
  15.         final ActivityInfo ai = getActivityInfo(comp, flags, userId);  
  16.         if (ai != null) {  
  17.             final ResolveInfo ri = new ResolveInfo();  
  18.             ri.activityInfo = ai;  
  19.             list.add(ri);  
  20.         }  
  21.         return list;  
  22.     }  
  23.   
  24.     // reader  
  25.     synchronized (mPackages) {  
  26.         final String pkgName = intent.getPackage();  
  27.         if (pkgName == null) {//intent没有指定包名,在系统所有包中查找  
  28.             List matchingFilters =  
  29.                     getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);//获取所有匹配的intent filter  
  30.             // Check for results that need to skip the current profile.  
  31.             ResolveInfo xpResolveInfo  = querySkipCurrentProfileIntents(matchingFilters, intent,  
  32.                     resolvedType, flags, userId);  
  33.             if (xpResolveInfo != null && isUserEnabled(xpResolveInfo.targetUserId)) {  
  34.                 List result = new ArrayList(1);  
  35.                 result.add(xpResolveInfo);  
  36.                 return filterIfNotPrimaryUser(result, userId);  
  37.             }  
  38.   
  39.             // Check for results in the current profile.  
  40.             List result = mActivities.queryIntent(  
  41.                     intent, resolvedType, flags, userId);  
  42.   
  43.             // Check for cross profile results.  
  44.             xpResolveInfo = queryCrossProfileIntents(  
  45.                     matchingFilters, intent, resolvedType, flags, userId);  
  46.             if (xpResolveInfo != null && isUserEnabled(xpResolveInfo.targetUserId)) {  
  47.                 result.add(xpResolveInfo);  
  48.                 Collections.sort(result, mResolvePrioritySorter);  
  49.             }  
  50.             result = filterIfNotPrimaryUser(result, userId);  
  51.             if (hasWebURI(intent)) {  
  52.                 CrossProfileDomainInfo xpDomainInfo = null;  
  53.                 final UserInfo parent = getProfileParent(userId);  
  54.                 if (parent != null) {  
  55.                     xpDomainInfo = getCrossProfileDomainPreferredLpr(intent, resolvedType,  
  56.                             flags, userId, parent.id);  
  57.                 }  
  58.                 if (xpDomainInfo != null) {  
  59.                     if (xpResolveInfo != null) {  
  60.                         // If we didn't remove it, the cross-profile ResolveInfo would be twice  
  61.                         // in the result.  
  62.                         result.remove(xpResolveInfo);  
  63.                     }  
  64.                     if (result.size() == 0) {  
  65.                         result.add(xpDomainInfo.resolveInfo);  
  66.                         return result;  
  67.                     }  
  68.                 } else if (result.size() <= 1) {  
  69.                     return result;  
  70.                 }  
  71.                 result = filterCandidatesWithDomainPreferredActivitiesLPr(intent, flags, result,  
  72.                         xpDomainInfo, userId);  
  73.                 Collections.sort(result, mResolvePrioritySorter);  
  74.             }  
  75.             return result;  
  76.         }  
  77.         final PackageParser.Package pkg = mPackages.get(pkgName);  
  78.         if (pkg != null) {//如果Intent中有包名,就在指定包中查找  
  79.             return filterIfNotPrimaryUser(  
  80.                     mActivities.queryIntentForPackage(  
  81.                             intent, resolvedType, flags, pkg.activities, userId),  
  82.                     userId);  
  83.         }  
  84.         return new ArrayList();  
  85.     }  
  86. }  

这个函数会根据Intent中的信息来分别处理。如果Intent有包名和Activity信息(指定了模块)直接返回ActivityInfo,这是最快的方式。如果只有包名,调用queryIntentForPackage在指定的安装包中查找Activity。如果包名也没有,只能调用queryIntent来搜索所有安装包了,这是最慢的一种查询方式了。

我们这里就看最直接的方式,我们看上面函数是直接调用了getActivityInfo方法来获取ActivityInfo的。直接通过mActivities.mActivities中的component来获取Activity,然后通过PackageParser.generateActivityInfo来产生一个ActivityInfo

[cpp] view plain copy
  1. public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {  
  2.     if (!sUserManager.exists(userId)) return null;  
  3.     enforceCrossUserPermission(Binder.getCallingUid(), userId, falsefalse"get activity info");//检查权限  
  4.     synchronized (mPackages) {  
  5.         PackageParser.Activity a = mActivities.mActivities.get(component);//获取到Activity  
  6.   
  7.         if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);  
  8.         if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {  
  9.             PackageSetting ps = mSettings.mPackages.get(component.getPackageName());  
  10.             if (ps == null) return null;  
  11.             return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),//得到ActivityInfo  
  12.                     userId);  
  13.         }  
  14.         if (mResolveComponentName.equals(component)) {  
  15.             return PackageParser.generateActivityInfo(mResolveActivity, flags,  
  16.                     new PackageUserState(), userId);  
  17.         }  
  18.     }  
  19.     return null;  
  20. }  

我们来看下这个generateActivityInfo函数,其实就是利用Activity的成员变量info来重新构造了一个ActivityInfo,然后再赋值ApplicationInfo等。

[cpp] view plain copy
  1. public static final ActivityInfo generateActivityInfo(Activity a, int flags,  
  2.         PackageUserState state, int userId) {  
  3.     if (a == null) return null;  
  4.     if (!checkUseInstalledOrHidden(flags, state)) {  
  5.         return null;  
  6.     }  
  7.     if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {  
  8.         return a.info;  
  9.     }  
  10.     // Make shallow copies so we can store the metadata safely  
  11.     ActivityInfo ai = new ActivityInfo(a.info);  
  12.     ai.metaData = a.metaData;  
  13.     ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);  
  14.     return ai;  
  15. }  

这里最关键的就是mActivities成员变量了,它是ActivityIntentResolver对象

[cpp] view plain copy
  1. final ActivityIntentResolver mActivities =  
  2.         new ActivityIntentResolver();  

还是就是ActivityIntentResolver的成员变量mActivities是一个map key就是ComponentName,通过ComponentName来找到Activity的。

[cpp] view plain copy
  1. // Keys are String (activity class name), values are Activity.  
  2. private final ArrayMap mActivities  
  3.         = new ArrayMap();  



三、mActivities变量中的Activity添加

3.1 开机扫描和安装应用大致流程

之前的博客讲PKMS的时候分析过无论是开机扫描各个目录的apk文件,还是安装新的apk最后都会调用scanPackageDirtyLI方法。

我们来简单回顾下,开机扫描各个目录的时候是调用scanDirLI函数,然后调用scanPackageLI函数这个函数第一个参数是File,这个函数会新建一个PackageParser对象,来解析文件。最后也会调用另一个scanPackageLI方法这个参数是Packageparser.Package类。而在这个scanPackageLI方法中最后调用了scanPackageDirtyLI方法。

在安装一个新应用的时候先copy apk文件到指定目录,后面会调用installPackageLI,这个函数也会创建一个PackageParser对象来解析apk文件,后面会调用installNewPackageLI继续处理,最后会发送广播通知其他应用,比如Launcher增加图标等。在installNewPackageLI函数中也会调用scanPackageLI函数,是参数是Packageparser.Package类。而最后就会调用scanPackageDirtyLI方法。

所以其实无论开机扫描还是安装应用其实流程差不多。


3.2 scanPackageDirtyLI方法处理mActivities

我们再来看下scanPackageDirtyLI方法中的一段代码,首先从PackageParser.Package中遍历其Activity,然后制定其info.processName最后把Activity放入到mActivities中。

[cpp] view plain copy
  1. N = pkg.activities.size();  
  2. r = null;  
  3. for (i=0; i
  4.     PackageParser.Activity a = pkg.activities.get(i);  
  5.     a.info.processName = fixProcessName(pkg.applicationInfo.processName,  
  6.             a.info.processName, pkg.applicationInfo.uid);  
  7.     mActivities.addActivity(a, "activity");  
  8.     if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {  
  9.         if (r == null) {  
  10.             r = new StringBuilder(256);  
  11.         } else {  
  12.             r.append(' ');  
  13.         }  
  14.         r.append(a.info.name);  
  15.     }  
  16. }  

再来看fixProcessName函数,结合上面的参数当a.info.processName有的话processName就是这个值,没有的话才是pkg.applicationInfo.processName。

[cpp] view plain copy
  1. private static String fixProcessName(String defProcessName,  
  2.         String processName, int uid) {  
  3.     if (processName == null) {  
  4.         return defProcessName;  
  5.     }  
  6.     return processName;  
  7. }  

下面我们再来看ActivityIntentResolver类的addActivity函数,其实主要就是放入了mActivities变量中,其key就是ComponentName。

[cpp] view plain copy
  1. public final void addActivity(PackageParser.Activity a, String type) {  
  2.     final boolean systemApp = a.info.applicationInfo.isSystemApp();  
  3.     mActivities.put(a.getComponentName(), a);  
  4.     final int NI = a.intents.size();  
  5.     for (int j=0; j
  6.         PackageParser.ActivityIntentInfo intent = a.intents.get(j);  
  7.         if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {  
  8.             intent.setPriority(0);  
  9.             Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "  
  10.                     + a.className + " with priority > 0, forcing to 0");  
  11.         }  
  12.         if (DEBUG_SHOW_INFO) {  
  13.             Log.v(TAG, "    IntentFilter:");  
  14.             intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");  
  15.         }  
  16.         if (!intent.debugCheck()) {  
  17.             Log.w(TAG, "==> For Activity " + a.info.name);  
  18.         }  
  19.         addFilter(intent);  
  20.     }  
  21. }  

我们回过头来看下,其实ActivityIntentResolver中mActivities中的值也是从PackageParser.Package中遍历其Activity,稍微修改下在add到mActivities中的。所以还是主要看PackageParser.Package中的Activity的由来。


四、PackageParser.Package的activities的ComponentName & info.processName

而PackageParser.Package的值无论是开机扫描还是新安装应用都是新建一个PackageParser,然后解析文件得到的。

只是开机扫描是在scanPackageLI函数中调用:

[cpp] view plain copy
  1. private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,  
  2.         long currentTime, UserHandle user) throws PackageManagerException {  
  3.     if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);  
  4.     parseFlags |= mDefParseFlags;  
  5.     PackageParser pp = new PackageParser();  
  6.     pp.setSeparateProcesses(mSeparateProcesses);  
  7.     pp.setOnlyCoreApps(mOnlyCore);  
  8.     pp.setDisplayMetrics(mMetrics);  
  9.   
  10.     if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {  
  11.         parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;  
  12.     }  
  13.   
  14.     final PackageParser.Package pkg;  
  15.     try {  
  16.         pkg = pp.parsePackage(scanFile, parseFlags);  
  17.     } catch (PackageParserException e) {  
  18.         throw PackageManagerException.from(e);  
  19.     }  
  20. ..  

而安装应用是在installPackageLI函数中调用:

[cpp] view plain copy
  1. private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {  
  2.     final int installFlags = args.installFlags;  
  3.     final String installerPackageName = args.installerPackageName;  
  4.     final String volumeUuid = args.volumeUuid;  
  5.     final File tmpPackageFile = new File(args.getCodePath());  
  6.     final boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);  
  7.     final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0)  
  8.             || (args.volumeUuid != null));  
  9.     boolean replace = false;  
  10.     int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;  
  11.     if (args.move != null) {  
  12.         // moving a complete application; perfom an initial scan on the new install location  
  13.         scanFlags |= SCAN_INITIAL;  
  14.     }  
  15.     // Result object to be returned  
  16.     res.returnCode = PackageManager.INSTALL_SUCCEEDED;  
  17.   
  18.     if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);  
  19.     // Retrieve PackageSettings and parse package  
  20.     final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY  
  21.             | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)  
  22.             | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);  
  23.     PackageParser pp = new PackageParser();  
  24.     pp.setSeparateProcesses(mSeparateProcesses);  
  25.     pp.setDisplayMetrics(mMetrics);  
  26.   
  27.     final PackageParser.Package pkg;  
  28.     try {  
  29.         pkg = pp.parsePackage(tmpPackageFile, parseFlags);  
  30.     } catch (PackageParserException e) {  
  31.         res.setError("Failed parse during installPackageLI", e);  
  32.         return;  
  33.     }  
  34. ..  

我们来看PackageParser的parsePackage函数,这里是否是目录的话调用的函数不一样。

[cpp] view plain copy
  1. public Package parsePackage(File packageFile, int flags) throws PackageParserException {  
  2.     if (packageFile.isDirectory()) {  
  3.         return parseClusterPackage(packageFile, flags);  
  4.     } else {  
  5.         return parseMonolithicPackage(packageFile, flags);  
  6.     }  
  7. }  

我们先来看下如果是目录的话调用parseClusterPackage函数,而在这个函数先调用parseBaseApk,然后遍历所有的split,调用函数parseSplitApk函数。

[cpp] view plain copy
  1. private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {  
  2.     final PackageLite lite = parseClusterPackageLite(packageDir, 0);  
  3.   
  4.     if (mOnlyCoreApps && !lite.coreApp) {  
  5.         throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,  
  6.                 "Not a coreApp: " + packageDir);  
  7.     }  
  8.   
  9.     final AssetManager assets = new AssetManager();  
  10.     try {  
  11.         // Load the base and all splits into the AssetManager  
  12.         // so that resources can be overriden when parsing the manifests.  
  13.         loadApkIntoAssetManager(assets, lite.baseCodePath, flags);  
  14.   
  15.         if (!ArrayUtils.isEmpty(lite.splitCodePaths)) {  
  16.             for (String path : lite.splitCodePaths) {  
  17.                 loadApkIntoAssetManager(assets, path, flags);  
  18.             }  
  19.         }  
  20.   
  21.         final File baseApk = new File(lite.baseCodePath);  
  22.         final Package pkg = parseBaseApk(baseApk, assets, flags);  
  23.         if (pkg == null) {  
  24.             throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,  
  25.                     "Failed to parse base APK: " + baseApk);  
  26.         }  
  27.   
  28.         if (!ArrayUtils.isEmpty(lite.splitNames)) {  
  29.             final int num = lite.splitNames.length;  
  30.             pkg.splitNames = lite.splitNames;  
  31.             pkg.splitCodePaths = lite.splitCodePaths;  
  32.             pkg.splitRevisionCodes = lite.splitRevisionCodes;  
  33.             pkg.splitFlags = new int[num];  
  34.             pkg.splitPrivateFlags = new int[num];  
  35.   
  36.             for (int i = 0; i < num; i++) {  
  37.                 parseSplitApk(pkg, i, assets, flags);  
  38.             }  
  39.         }  
  40.   
  41.         pkg.codePath = packageDir.getAbsolutePath();  
  42.         return pkg;  
  43.     } finally {  
  44.         IoUtils.closeQuietly(assets);  
  45.     }  
  46. }  

而我们再看下parseMonolithicPackage函数,因为不是目录,所以只有一个apk,直接调用了parseBaseApk。

[cpp] view plain copy
  1. public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {  
  2.     if (mOnlyCoreApps) {  
  3.         final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);  
  4.         if (!lite.coreApp) {  
  5.             throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,  
  6.                     "Not a coreApp: " + apkFile);  
  7.         }  
  8.     }  
  9.   
  10.     final AssetManager assets = new AssetManager();  
  11.     try {  
  12.         final Package pkg = parseBaseApk(apkFile, assets, flags);  
  13.         pkg.codePath = apkFile.getAbsolutePath();  
  14.         return pkg;  
  15.     } finally {  
  16.         IoUtils.closeQuietly(assets);  
  17.     }  
  18. }  

那我们来看下这个parseBaseApk函数,在这个函数中调用了另一个parseBaseApk函数,在这个函数新建了一个Package对象。然后遍历xml中各个节点,这里我们只关心application。在这个节点解析的时候直接调用了parseBaseApplication函数。

[cpp] view plain copy
  1. private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,  
  2.         String[] outError) throws XmlPullParserException, IOException {  
  3.     ......  
  4.     final Package pkg = new Package(pkgName);  
  5.     boolean foundApp = false;  
  6.   
  7.     TypedArray sa = res.obtainAttributes(attrs,  
  8.             com.android.internal.R.styleable.AndroidManifest);  
  9.     pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(  
  10.             com.android.internal.R.styleable.AndroidManifest_versionCode, 0);  
  11.     pkg.baseRevisionCode = sa.getInteger(  
  12.             com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);  
  13.     pkg.mVersionName = sa.getNonConfigurationString(  
  14.             com.android.internal.R.styleable.AndroidManifest_versionName, 0);  
  15.     if (pkg.mVersionName != null) {  
  16.         pkg.mVersionName = pkg.mVersionName.intern();  
  17.     }  
  18.     ......  
  19.       
  20.     int outerDepth = parser.getDepth();  
  21.     while ((type = parser.next()) != XmlPullParser.END_DOCUMENT  
  22.             && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {  
  23.         if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {  
  24.             continue;  
  25.         }  
  26.   
  27.         String tagName = parser.getName();  
  28.         if (tagName.equals("application")) {  
  29.             if (foundApp) {  
  30.                 if (RIGID_PARSER) {  
  31.                     outError[0] = " has more than one ";  
  32.                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;  
  33.                     return null;  
  34.                 } else {  
  35.                     Slog.w(TAG, " has more than one ");  
  36.                     XmlUtils.skipCurrentTag(parser);  
  37.                     continue;  
  38.                 }  
  39.             }  
  40.   
  41.             foundApp = true;  
  42.             if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) {  
  43.                 return null;  
  44.             }  
  45.         }   

我们再来看下parseBaseApplication函数,先获取了ApplicationInfo后面会修改器processName,再后面就开始就是xml中的application下的各个节点了。我们主要看下关于Activities的。是调用了parseActivity,然后保存在activities变量中。

[cpp] view plain copy
  1. private boolean parseBaseApplication(Package owner, Resources res,  
  2.         XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)  
  3.     throws XmlPullParserException, IOException {  
  4.     final ApplicationInfo ai = owner.applicationInfo;  
  5.     final String pkgName = owner.applicationInfo.packageName;  
  6.     ......  
  7.       
  8.                 ai.processName = buildProcessName(ai.packageName, null, pname,  
  9.                 flags, mSeparateProcesses, outError);  
  10.     ......  
  11.     while ((type = parser.next()) != XmlPullParser.END_DOCUMENT  
  12.             && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {  
  13.         if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {  
  14.             continue;  
  15.         }  
  16.   
  17.         String tagName = parser.getName();  
  18.         if (tagName.equals("activity")) {  
  19.             Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,  
  20.                     owner.baseHardwareAccelerated);  
  21.             if (a == null) {  
  22.                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;  
  23.                 return false;  
  24.             }  
  25.   
  26.             owner.activities.add(a);  
  27.   
  28.         }  

parseActivity新建了一个Activity对象,然后解析各种数据保存在info等变量中。但是仔细看没有我们想要的东西。

1.没有看到Activity的info.processName

2.没有看到Activity的ComponentName

[cpp] view plain copy
  1. private Activity parseActivity(Package owner, Resources res,  
  2.         XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,  
  3.         boolean receiver, boolean hardwareAccelerated)  
  4.         throws XmlPullParserException, IOException {  
  5.     TypedArray sa = res.obtainAttributes(attrs, R.styleable.AndroidManifestActivity);  
  6.   
  7.     if (mParseActivityArgs == null) {  
  8.         mParseActivityArgs = new ParseComponentArgs(owner, outError,  
  9.                 R.styleable.AndroidManifestActivity_name,  
  10.                 R.styleable.AndroidManifestActivity_label,  
  11.                 R.styleable.AndroidManifestActivity_icon,  
  12.                 R.styleable.AndroidManifestActivity_logo,  
  13.                 R.styleable.AndroidManifestActivity_banner,  
  14.                 mSeparateProcesses,  
  15.                 R.styleable.AndroidManifestActivity_process,  
  16.                 R.styleable.AndroidManifestActivity_description,  
  17.                 R.styleable.AndroidManifestActivity_enabled);  
  18.     }  
  19.       
  20.     mParseActivityArgs.tag = receiver ? "" : "";  
  21.     mParseActivityArgs.sa = sa;  
  22.     mParseActivityArgs.flags = flags;  
  23.       
  24.     Activity a = new Activity(mParseActivityArgs, new ActivityInfo());  
我们先看下Activity的构造函数,其父类是public static class Component
[cpp] view plain copy
  1. public Activity(final ParseComponentArgs args, final ActivityInfo _info) {  
  2.     super(args, _info);  
  3.     info = _info;  
  4.     info.applicationInfo = args.owner.applicationInfo;  
  5. }  

我们看其父类的函数,也没有看到起关于ComponentName的设置,但是会对outInfo的processName进行设置,也就是Activity的info的processName。那这里解了我们第一个疑惑info的processName。

[cpp] view plain copy
  1. public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {  
  2.     this(args, (PackageItemInfo)outInfo);  
  3.     if (args.outError[0] != null) {  
  4.         return;  
  5.     }  
  6.   
  7.     if (args.processRes != 0) {  
  8.         CharSequence pname;  
  9.         if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {  
  10.             pname = args.sa.getNonConfigurationString(args.processRes,  
  11.                     Configuration.NATIVE_CONFIG_VERSION);  
  12.         } else {  
  13.             // Some older apps have been seen to use a resource reference  
  14.             // here that on older builds was ignored (with a warning).  We  
  15.             // need to continue to do this for them so they don't break.  
  16.             pname = args.sa.getNonResourceString(args.processRes);  
  17.         }  
  18.         outInfo.processName = buildProcessName(owner.applicationInfo.packageName,  
  19.                 owner.applicationInfo.processName, pname,  
  20.                 args.flags, args.sepProcesses, args.outError);  
  21.     }  
  22.       
  23.     if (args.descriptionRes != 0) {  
  24.         outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);  
  25.     }  
  26.       
  27.     outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);  
  28. }  

那么第二个ComponentName呢,我再来看上面这个函数第一句话是调用了另一个构造函数,在这里我们构造了className。当然这里获取className的方式有点复杂,和一些资源相关。

[cpp] view plain copy
  1. public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {  
  2.     owner = args.owner;  
  3.     intents = new ArrayList(0);  
  4.     String name = args.sa.getNonConfigurationString(args.nameRes, 0);  
  5.     if (name == null) {  
  6.         className = null;  
  7.         args.outError[0] = args.tag + " does not specify android:name";  
  8.         return;  
  9.     }  
  10.   
  11.     outInfo.name  
  12.         = buildClassName(owner.applicationInfo.packageName, name, args.outError);  
  13.     if (outInfo.name == null) {  
  14.         className = null;  
  15.         args.outError[0] = args.tag + " does not have valid android:name";  
  16.         return;  
  17.     }  
  18.   
  19.     className = outInfo.name;  

而我们再看下Activity的getComponentName函数,只要有className就会新建一个ComponentName对象。

[cpp] view plain copy
  1. public ComponentName getComponentName() {  
  2.     if (componentName != null) {  
  3.         return componentName;  
  4.     }  
  5.     if (className != null) {  
  6.         componentName = new ComponentName(owner.applicationInfo.packageName,  
  7.                 className);  
  8.     }  
  9.     return componentName;  
  10. }  

ComponentName的构造函数也就是保存两个变量。

[cpp] view plain copy
  1. public ComponentName(String pkg, String cls) {  
  2.     if (pkg == null) throw new NullPointerException("package name is null");  
  3.     if (cls == null) throw new NullPointerException("class name is null");  
  4.     mPackage = pkg;  
  5.     mClass = cls;  
  6. }  

那么这样ComponentName和processName的问题都解决了。


五、uid值由来

给AMS传递的ActivityInfo,还有一个重要的信息就是uid,是在ApplicationInfo中的。我们来看下在哪里赋值的。

在scanPackageDirtyLI函数中有一句

[cpp] view plain copy
  1. pkg.applicationInfo.uid = pkgSetting.appId;  

我们再看下Activity的构造函数,info.applicationInfo就是Package的applicationinfo。因此上面给uid赋值,就是ActivityInfo的applicationInfo的uid赋值。

[cpp] view plain copy
  1. public Activity(final ParseComponentArgs args, final ActivityInfo _info) {  
  2.     super(args, _info);  
  3.     info = _info;  
  4.     info.applicationInfo = args.owner.applicationInfo;  
  5. }  

那我们再看看pkgSetting.appId的由来,同样在scanPackageDirtyLI函数中有如下代码,创建一个pkgSetting。

[cpp] view plain copy
  1. pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,  
  2.         destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,  
  3.         pkg.applicationInfo.primaryCpuAbi,  
  4.         pkg.applicationInfo.secondaryCpuAbi,  
  5.         pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags,  
  6.         user, false);  

我们来看下这个函数,它调用了另一个getPackageLPw函数

[cpp] view plain copy
  1. PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,  
  2.         String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,  
  3.         String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi,  
  4.         int pkgFlags, int pkgPrivateFlags, UserHandle user, boolean add) {  
  5.     final String name = pkg.packageName;  
  6.     PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,  
  7.             resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, secondaryCpuAbi,  
  8.             pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user, add, true /* allowInstall */);  
  9.     return p;  
  10. }  

我们来看下这个函数,首先我们现在在mPackages没有值,所以直接从p==null分支看,然后也没有origPackage,没有sharedUser,我们就直接看newUserIdLPw函数产生一个新的uid。

[cpp] view plain copy
  1. private PackageSetting getPackageLPw(String name, PackageSetting origPackage,  
  2.         String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,  
  3.         String legacyNativeLibraryPathString, String primaryCpuAbiString,  
  4.         String secondaryCpuAbiString, int vc, int pkgFlags, int pkgPrivateFlags,  
  5.         UserHandle installUser, boolean add, boolean allowInstall) {  
  6.     PackageSetting p = mPackages.get(name);  
  7.     UserManagerService userManager = UserManagerService.getInstance();  
  8.     if (p != null) {  
  9.         ......  
  10.     }  
  11.     if (p == null) {  
  12.         if (origPackage != null) {  
  13.             ......  
  14.         } else {  
  15.             p = new PackageSetting(name, realName, codePath, resourcePath,  
  16.                     legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,  
  17.                     null /* cpuAbiOverrideString */, vc, pkgFlags, pkgPrivateFlags);  
  18.             p.setTimeStamp(codePath.lastModified());  
  19.             p.sharedUser = sharedUser;  
  20.             // If this is not a system app, it starts out stopped.  
  21.             if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {  
  22.                 if (DEBUG_STOPPED) {  
  23.                     RuntimeException e = new RuntimeException("here");  
  24.                     e.fillInStackTrace();  
  25.                     Slog.i(PackageManagerService.TAG, "Stopping package " + name, e);  
  26.                 }  
  27.                 List users = getAllUsers();  
  28.                 final int installUserId = installUser != null ? installUser.getIdentifier() : 0;  
  29.                 if (users != null && allowInstall) {  
  30.                     for (UserInfo user : users) {  
  31.                         // By default we consider this app to be installed  
  32.                         // for the user if no user has been specified (which  
  33.                         // means to leave it at its original value, and the  
  34.                         // original default value is true), or we are being  
  35.                         // asked to install for all users, or this is the  
  36.                         // user we are installing for.  
  37.                         final boolean installed = installUser == null  
  38.                                 || (installUserId == UserHandle.USER_ALL  
  39.                                     && !isAdbInstallDisallowed(userManager, user.id))  
  40.                                 || installUserId == user.id;  
  41.                         p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT,  
  42.                                 installed,  
  43.                                 true// stopped,  
  44.                                 true// notLaunched  
  45.                                 false// hidden  
  46.                                 null, null, null,  
  47.                                 false// blockUninstall  
  48.                                 INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0);  
  49.                         writePackageRestrictionsLPr(user.id);  
  50.                     }  
  51.                 }  
  52.             }  
  53.             if (sharedUser != null) {//是否有sharedUser,这样就是在相同的uid下  
  54.                 p.appId = sharedUser.userId;  
  55.             } else {  
  56.                 // Clone the setting here for disabled system packages  
  57.                 PackageSetting dis = mDisabledSysPackages.get(name);//这里我们也不关注  
  58.                 if (dis != null) {  
  59.                     // For disabled packages a new setting is created  
  60.                     // from the existing user id. This still has to be  
  61.                     // added to list of user id's  
  62.                     // Copy signatures from previous setting  
  63.                     if (dis.signatures.mSignatures != null) {  
  64.                         p.signatures.mSignatures = dis.signatures.mSignatures.clone();  
  65.                     }  
  66.                     p.appId = dis.appId;  
  67.                     // Clone permissions  
  68.                     p.getPermissionsState().copyFrom(dis.getPermissionsState());  
  69.                     // Clone component info  
  70.                     List users = getAllUsers();  
  71.                     if (users != null) {  
  72.                         for (UserInfo user : users) {  
  73.                             int userId = user.id;  
  74.                             p.setDisabledComponentsCopy(  
  75.                                     dis.getDisabledComponents(userId), userId);  
  76.                             p.setEnabledComponentsCopy(  
  77.                                     dis.getEnabledComponents(userId), userId);  
  78.                         }  
  79.                     }  
  80.                     // Add new setting to list of user ids  
  81.                     addUserIdLPw(p.appId, p, name);  
  82.                 } else {  
  83.                     // Assign new user id  
  84.                     p.appId = newUserIdLPw(p);//分配一个新的uid  
  85.                 }  
  86.             }  
  87.         }  
  88.         if (p.appId < 0) {  
  89.             PackageManagerService.reportSettingsProblem(Log.WARN,  
  90.                     "Package " + name + " could not be assigned a valid uid");  
  91.             return null;  
  92.         }  
  93.         if (add) {  
  94.             // Finish adding new package by adding it and updating shared  
  95.             // user preferences  
  96.             addPackageSettingLPw(p, name, sharedUser);  
  97.         }  
  98.     } else {  
  99.         .....  
  100.     }  
  101.     return p;  
  102. }  

newUserIdLPw函数先遍历所有的uid。看哪个uid对应的对象空了,就重新用这个uid。如果都不为空,而且不超过最大uid值,用当前最大值的uid+1,作为新的uid。

[cpp] view plain copy
  1. private int newUserIdLPw(Object obj) {  
  2.     // Let's be stupidly inefficient for now...  
  3.     final int N = mUserIds.size();  
  4.     for (int i = mFirstAvailableUid; i < N; i++) {  
  5.         if (mUserIds.get(i) == null) {  
  6.             mUserIds.set(i, obj);  
  7.             return Process.FIRST_APPLICATION_UID + i;  
  8.         }  
  9.     }  
  10.   
  11.     // None left?  
  12.     if (N > (Process.LAST_APPLICATION_UID-Process.FIRST_APPLICATION_UID)) {  
  13.         return -1;  
  14.     }  
  15.   
  16.     mUserIds.add(obj);  
  17.     return Process.FIRST_APPLICATION_UID + N;  
  18. }  


六、成员变量mSettings mPackages保存数据

在scanPackageDirtyLI函数后面会保存mSettings和mPackages,主要是把PackageSetting保存在mSetting中,把Package保存在mPackages中。mPackages直接put了,我们就不分析了。我们看下mSettings保存PackageSetting。

[cpp] view plain copy
  1. synchronized (mPackages) {  
  2.     // We don't expect installation to fail beyond this point  
  3.   
  4.     // Add the new setting to mSettings  
  5.     mSettings.insertPackageSettingLPw(pkgSetting, pkg);  
  6.     // Add the new setting to mPackages  
  7.     mPackages.put(pkg.applicationInfo.packageName, pkg);  

insertPackageSettingLPw函数先把pkg赋给了PackageSetting 的pkg,最后调用了addPackageSettingLPw函数保存PackageSetting 对象。

[cpp] view plain copy
  1. void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {  
  2.     p.pkg = pkg;  
  3.     // pkg.mSetEnabled = p.getEnabled(userId);  
  4.     // pkg.mSetStopped = p.getStopped(userId);  
  5.     final String volumeUuid = pkg.applicationInfo.volumeUuid;  
  6.     final String codePath = pkg.applicationInfo.getCodePath();  
  7.     final String resourcePath = pkg.applicationInfo.getResourcePath();  
  8.     final String legacyNativeLibraryPath = pkg.applicationInfo.nativeLibraryRootDir;  
  9.     // Update volume if needed  
  10.     if (!Objects.equals(volumeUuid, p.volumeUuid)) {  
  11.         Slog.w(PackageManagerService.TAG, "Volume for " + p.pkg.packageName +  
  12.                 " changing from " + p.volumeUuid + " to " + volumeUuid);  
  13.         p.volumeUuid = volumeUuid;  
  14.     }  
  15.     // Update code path if needed  
  16.     if (!Objects.equals(codePath, p.codePathString)) {  
  17.         Slog.w(PackageManagerService.TAG, "Code path for " + p.pkg.packageName +  
  18.                 " changing from " + p.codePathString + " to " + codePath);  
  19.         p.codePath = new File(codePath);  
  20.         p.codePathString = codePath;  
  21.     }  
  22.     //Update resource path if needed  
  23.     if (!Objects.equals(resourcePath, p.resourcePathString)) {  
  24.         Slog.w(PackageManagerService.TAG, "Resource path for " + p.pkg.packageName +  
  25.                 " changing from " + p.resourcePathString + " to " + resourcePath);  
  26.         p.resourcePath = new File(resourcePath);  
  27.         p.resourcePathString = resourcePath;  
  28.     }  
  29.     // Update the native library paths if needed  
  30.     if (!Objects.equals(legacyNativeLibraryPath, p.legacyNativeLibraryPathString)) {  
  31.         p.legacyNativeLibraryPathString = legacyNativeLibraryPath;  
  32.     }  
  33.   
  34.     // Update the required Cpu Abi  
  35.     p.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;  
  36.     p.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;  
  37.     p.cpuAbiOverrideString = pkg.cpuAbiOverride;  
  38.     // Update version code if needed  
  39.     if (pkg.mVersionCode != p.versionCode) {  
  40.         p.versionCode = pkg.mVersionCode;  
  41.     }  
  42.     // Update signatures if needed.  
  43.     if (p.signatures.mSignatures == null) {  
  44.         p.signatures.assignSignatures(pkg.mSignatures);  
  45.     }  
  46.     // Update flags if needed.  
  47.     if (pkg.applicationInfo.flags != p.pkgFlags) {  
  48.         p.pkgFlags = pkg.applicationInfo.flags;  
  49.     }  
  50.     // If this app defines a shared user id initialize  
  51.     // the shared user signatures as well.  
  52.     if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {  
  53.         p.sharedUser.signatures.assignSignatures(pkg.mSignatures);  
  54.     }  
  55.     addPackageSettingLPw(p, pkg.packageName, p.sharedUser);  
  56. }  
addPackageSettingLPw主要把PackageSetting 放在了mSettings的成员变量mPackages中。
[cpp] view plain copy
  1. private void addPackageSettingLPw(PackageSetting p, String name,  
  2.         SharedUserSetting sharedUser) {  
  3.     mPackages.put(name, p);  
  4. ..  
这里只是保存了这两个成员变量,而在每次开机的时候都会重新扫描各个目录的apk,然后重新把各个PackageSetting放入mSettings中,最后也会把mSettings中的数据写入packages.xml文件中。


七、总结

在AMS中我们从PKMS中通过Intent参数获取ActivityInfo对象,并且其processName和uid这两个变量在后续启动进程的时候很重要。而PKMS通过Intent查询Activity,如果Intent有ComponentName我们可以直接找到对应的Activity,并且把ActivityInfo传给AMS。如果没有ComponentName,就要通过包名或者全局查找了。

你可能感兴趣的:(Android,基础业务分析)