我们知道系统在启动的时候会加载系统Service,比如ActivityManagerService,PackageManagerService等, PMS启动以后,会扫描系统中所有已安装apk的目录,比如系统应用”/system/app”,第三方应用”/data/app”,PMS会解析该包下的所有AndroidManifest.xml文件,将解析出的activity,service,broadcastreceiver等信息保存到系统中。
其实在android系统开机以后加载PackageManagerService时候,从其构造方法就开始了。
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { ....... synchronized (mInstallLock) { // writer synchronized (mPackages) { mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/); mHandlerThread.start(); mHandler = new PackageHandler(mHandlerThread.getLooper()); // 获取/data目录 File dataDir = Environment.getDataDirectory(); // /data/data mAppDataDir = new File(dataDir, "data"); // /data/app mAppInstallDir = new File(dataDir, "app"); mAppLib32InstallDir = new File(dataDir, "app-lib"); mAsecInternalPath = new File(dataDir, "app-asec").getPath(); mUserAppDataDir = new File(dataDir, "user"); mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); mRegionalizationAppInstallDir = new File(dataDir, "app-regional"); ..... File frameworkDir = new File(Environment.getRootDirectory(), "framework"); // 加载framework资源 alreadyDexOpted.add(frameworkDir.getPath() + "/framework-res.apk"); // 加载核心库文件 alreadyDexOpted.add(frameworkDir.getPath() + "/core-libart.jar"); populateBlacklist(); ..... // 获取系统app的安装路径 final File systemAppDir = new File(Environment.getRootDirectory(), "app"); // 扫描系统app的安装路径 scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_RUNTIME_SKIN, 0); // Collect all vendor packages. File vendorAppDir = new File("/vendor/app"); try { vendorAppDir = vendorAppDir.getCanonicalFile(); } catch (IOException e) { // failed to look up canonical path, continue with original one } scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_RUNTIME_SKIN, 0); // Collect all OEM packages. final File oemAppDir = new File(Environment.getOemDirectory(), "app"); scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_RUNTIME_SKIN, 0); File oemPrivAppDir = new File(Environment.getOemDirectory(), "priv-app"); if (oemPrivAppDir.exists()) { scanDirLI(oemPrivAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED, scanFlags | SCAN_TRUSTED_RUNTIME_SKIN, 0); } // Collect all Regionalization packages form Carrier's res packages. if (RegionalizationEnvironment.isSupported()) { Log.d(TAG, "Load Regionalization vendor apks"); final ListRegionalizationDirs = RegionalizationEnvironment.getAllPackageDirectories(); for (File f : RegionalizationDirs) { File RegionalizationSystemDir = new File(f, "system"); // Collect packages in /system/priv-app scanDirLI(new File(RegionalizationSystemDir, "priv-app"), PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0); // Collect packages in /system/app scanDirLI(new File(RegionalizationSystemDir, "app"), PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0); // Collect overlay in /system/vendor scanDirLI(new File(RegionalizationSystemDir, "vendor/overlay"), PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0); } } if (!mOnlyCore) { // 扫描第三方app的安装路径 scanDirLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0); scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanFlags | SCAN_REQUIRE_KNOWN, 0); } ..... } // synchronized (mPackages) } // synchronized (mInstallLock) Runtime.getRuntime().gc(); // Expose private service for system components to use. LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl()); LocalServices.addService(PackageManagerServiceExtend.class, new ServiceExtendImpl()); }
从上面的构造方法,可以看出,PMS需要加载系统已安装的各类apk,包括系统apk第三方apk等等,在此之前,还要加载Framework资源与核心库文件,并且具体的扫描加载功能由scanDirLI方法实现,我们看看scanDirLI方法的内部实现:
private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) { // 获取目录下的所有文件 final File[] files = dir.listFiles(); if (ArrayUtils.isEmpty(files)) { Log.d(TAG, "No files in app dir " + dir); return; } // 遍历所有文件 for (File file : files) { final boolean isPackage = (isApkFile(file) || file.isDirectory()) && !PackageInstallerService.isStageName(file.getName()); // 如果不是apk文件,则直接忽略 if (!isPackage) { continue; } ...... try { // 解析apk scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK, scanFlags, currentTime, null); } catch (PackageManagerException e) { ..... } } }
scanDirLI方法比较简单:
1. 遍历当前目录下所有文件,如果没有文件,直接返回
2. 判断当前文件是否是apk文件,如果不是直接返回
3. 通过scanPackageLI解析当前apk文件
可以看到重点解析当前apk文件的工作,转移到了scanPackageLI方法,我们继续scanPackageLI:
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { // 创建一个包解析器 PackageParser pp = new PackageParser(); pp.setSeparateProcesses(mSeparateProcesses); pp.setOnlyCoreApps(mOnlyCore); pp.setDisplayMetrics(mMetrics); pp.setRuntimeSkinBlacklist(mRuntimeSkinManager.getBlacklistedPackages()); final PackageParser.Package pkg; try { // 解析apk包 pkg = pp.parsePackage(scanFile, parseFlags); } catch (PackageParser.PackageParserException e) { throw PackageManagerException.from(e); } .... // 解析apk中的activity,service等组件, 在(pkg, parseFlags, scanFlags // | SCAN_UPDATE_SIGNATURE, currentTime, user)方法中会将当前解析出的activity,service等组件添加到PackageManagerService的集合里 PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user); .... return scannedPkg; }
在scanPackageLI方法中:
1.首先创建一个包解析器
2.通过parsePackage解析apk包,封装成PackageParser.Package类型
3.通过步骤二中的PackageParser.Package对象,解析apk中的activity,service等组件
下面我们看下parsePackage方法,具体解析单个apk文件的流程:
public Package parsePackage(File packageFile, int flags) throws PackageParserException { // 是否是文件夹类型 if (packageFile.isDirectory()) { return parseClusterPackage(packageFile, flags); } else { // 解析单个apk文件 return parseMonolithicPackage(packageFile, flags); } }
在parsePackage中,会判断当前文件类型选择不同的解析,如果是一个文件夹,则匹配该文件夹下的所有apk文件,如果是一个文件,则调用PackageParser#parseMonolithicPackage解析单个文件。
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException { ... final AssetManager assets = new AssetManager(); try { // 具体解析apk文件操作的封装 final Package pkg = parseBaseApk(apkFile, assets, flags); pkg.codePath = apkFile.getAbsolutePath(); return pkg; } finally { IoUtils.closeQuietly(assets); } } private Package parseBaseApk(File apkFile, AssetManager assets, int flags) throws PackageParserException { final String apkPath = apkFile.getAbsolutePath(); // 代码省略 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags); Resources res = null; XmlResourceParser parser = null; try { // 根据AssetManager实例构建资源实例 res = new 构建(assets, mMetrics, null); assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Build.VERSION.RESOURCES_SDK_INT); // 获取AndroidManifest.xml的解析器 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); final String[] outError = new String[1]; // 解析获取到的AndroidManifest.xml final Package pkg = parseBaseApk(res, parser, flags, outError); pkg.volumeUuid = volumeUuid; pkg.applicationInfo.volumeUuid = volumeUuid; pkg.baseCodePath = apkPath; pkg.mSignatures = null; return pkg; } // 省略catch代码块 }
在上述方法中主要调用了parseBaseApk(res, parser, flags, outError)解析AndroidManifest.xml文件
private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { AttributeSet attrs = parser; // 1.构建Package对象 final Package pkg = new Package(pkgName); boolean foundApp = false; // 2.通过TypedArray获取AndroidManifest.xml文件中的属性值,并赋值给pkg对象 TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifest); pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_versionCode, 0); pkg.baseRevisionCode = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_revisionCode, 0); pkg.mVersionName = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifest_versionName, 0); if (pkg.mVersionName != null) { pkg.mVersionName = pkg.mVersionName.intern(); } String str = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0); if (str != null && str.length() > 0) { String nameError = validateName(str, true, false); if (nameError != null && !"android".equals(pkgName)) { outError[0] = "specifies bad sharedUserId name \"" + str + "\": " + nameError; mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID; return null; } pkg.mSharedUserId = str.intern(); pkg.mSharedUserLabel = sa.getResourceId( com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0); } pkg.installLocation = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_installLocation, PARSE_DEFAULT_INSTALL_LOCATION); pkg.applicationInfo.installLocation = pkg.installLocation; pkg.coreApp = attrs.getAttributeBooleanValue(null, "coreApp", false); sa.recycle(); // 3.解析AndroidManifest.xml文件 int outerDepth = parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } String tagName = parser.getName(); if (tagName.equals("application")) { if (foundApp) { // 4.解析application标签,activity,service,broadcastreceiver都在这个标签中 if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) { return null; } } else if (tagName.equals("overlay")) { .... } else if (tagName.equals("key-sets")) { if (!parseKeySets(pkg, res, parser, attrs, outError)) { return null; } } else if (tagName.equals("permission-group")) { if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) { return null; } } else if (tagName.equals("permission")) { if (parsePermission(pkg, res, parser, attrs, outError) == null) { return null; } } else if (tagName.equals("permission-tree")) { if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) { return null; } } else if (tagName.equals("uses-permission")) { if (!parseUsesPermission(pkg, res, parser, attrs)) { return null; } } else if (tagName.equals("uses-permission-sdk-m") || tagName.equals("uses-permission-sdk-23")) { if (!parseUsesPermission(pkg, res, parser, attrs)) { return null; } } else if (tagName.equals("uses-configuration")) { .... } else if (tagName.equals("uses-feature")) { .... } else if (tagName.equals("feature-group")) { .... } else if (tagName.equals("uses-sdk")) { .... } else if (tagName.equals("supports-screens")) { .... } else if (tagName.equals("protected-broadcast")) { .... } else if (tagName.equals("adopt-permissions")) { .... } } .... return pkg; }
在PackageParser#parseBaseApk(res, parser, flags, outError)方法主要做了下面的事情:
构建Package对象 通过TypedArray获取AndroidManifest.xml文件中的属性值,并赋值给pkg对象 解析AndroidManifest.xml文件 通过parseBaseApplication解析application标签,activity,service,broadcastreceiver都在这个标签中接着分析parseBaseApplication方法:
private boolean parseBaseApplication(Package owner, Resources res, XmlPullParser parser, AttributeSet attrs, int flags, String[] outError) throws XmlPullParserException, IOException { final ApplicationInfo ai = owner.applicationInfo; final String pkgName = owner.applicationInfo.packageName; // 根据TypedArray获取到在AndroidManifest.xml文件中配置的属性值. TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestApplication); // 省略代码 ai.icon = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestApplication_icon, 0); ai.logo = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestApplication_logo, 0); ai.banner = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestApplication_banner, 0); ai.theme = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestApplication_theme, 0); ai.descriptionRes = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestApplication_description, 0); // 省略代码 sa.recycle(); // 2.解析AndroidManifest.xml中的四大组件,并且将解析结果,添加到Package中对应的集合里 final int innerDepth = parser.getDepth(); int type; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue; } String tagName = parser.getName(); if (tagName.equals("activity")) { Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false, owner.baseHardwareAccelerated); if (a == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } owner.activities.add(a); } else if (tagName.equals("receiver")) { Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false); if (a == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } owner.receivers.add(a); } else if (tagName.equals("service")) { Service s = parseService(owner, res, parser, attrs, flags, outError); if (s == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } owner.services.add(s); } else if (tagName.equals("provider")) { Provider p = parseProvider(owner, res, parser, attrs, flags, outError); if (p == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } owner.providers.add(p); } else if (tagName.equals("activity-alias")) { Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError); if (a == null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } owner.activities.add(a); } return true; }
在parseBaseApplication主要做了下面操作:
1. 根据TypedArray获取到在AndroidManifest.xml文件中配置的属性值.
2. 解析AndroidManifest.xml中的四大组件,并且将解析结果,添加到Package中对应的集合里,这些集合是声明在PackageParser$Package中的
public final static class Package { .... public final ArrayListactivities = new ArrayList (0); public final ArrayList receivers = new ArrayList (0); public final ArrayList providers = new ArrayList (0); public final ArrayList services = new ArrayList (0); }
到此位置解析单个apk的工作都已经完成,并且将解析结果封装到Package对象中
回到上面的scanPackageLI(File scanFile, int parseFlags, int scanFlags,long currentTime, UserHandle user)方法,
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { // 创建一个包解析器 PackageParser pp = new PackageParser(); pp.setSeparateProcesses(mSeparateProcesses); pp.setOnlyCoreApps(mOnlyCore); pp.setDisplayMetrics(mMetrics); pp.setRuntimeSkinBlacklist(mRuntimeSkinManager.getBlacklistedPackages()); final PackageParser.Package pkg; try { // 解析apk包 pkg = pp.parsePackage(scanFile, parseFlags); } catch (PackageParser.PackageParserException e) { throw PackageManagerException.from(e); } .... // 解析apk中的activity,service等组件, 在(pkg, parseFlags, scanFlags // | SCAN_UPDATE_SIGNATURE, currentTime, user)方法中会将当前解析出的activity,service等组件添加到PackageManagerService的集合里 PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user); .... return scannedPkg; }
在该方法,最后调用了scanPackageLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user)方法:
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { ..... N = pkg.services.size(); r = null; for (i=0; i<n; i++)="" {="" packageparser.service="" s="pkg.services.get(i);" s.info.processname="fixProcessName(pkg.applicationInfo.processName," s.info.processname,="" pkg.applicationinfo.uid);="" 添加到对应的mservices集合中="" mservices.addservice(s);="" if="" ((parseflags&packageparser.parse_chatty)="" !="0)" (r="=" null)="" r="new" stringbuilder(256);="" }="" else="" r.append('="" ');="" r.append(s.info.name);="" (debug_package_scanning)="" log.d(tag,="" "="" services:="" +="" r);="" n="pkg.receivers.size();" for="" (i="0;" i="" <="" pre="">
将之前保存在PackageParser.Package中的apk信息重新放到PackageManagerService中
final ActivityIntentResolver mActivities = new ActivityIntentResolver(); // All available receivers, for your resolving pleasure. final ActivityIntentResolver mReceivers = new ActivityIntentResolver(); // All available services, for your resolving pleasure. final ServiceIntentResolver mServices = new ServiceIntentResolver(); // All available providers, for your resolving pleasure. final ProviderIntentResolver mProviders = new ProviderIntentResolver();
到现在为止所有apk信息的构建就完成了。
这里我们用”startActivity”来说明,在activity启动流程一文中,我们详细的讨论过activity的启动流程 ActivityStackSupervisor#startActivityMayWait方法
final int startActivityMayWait(参数省略.....) { try { ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent( intent, null, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS, userId); aInfo = rInfo != null ? rInfo.activityInfo : null; aInfo = mService.getActivityInfoForUser(aInfo, userId); } catch (RemoteException e) { aInfo = null; } int res = startActivityLocked(caller, intent, resolvedType, aInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, null, container, inTask); return res; }
可以看到通过PMS中的resolveIntent方法来查找匹配当前intent的activity
@Override public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId) { if (!sUserManager.exists(userId)) return null; enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "resolve intent"); Listquery = queryIntentActivities(intent, resolvedType, flags, userId); return chooseBestActivity(intent, resolvedType, flags, query, userId); } @Override public List queryIntentActivities(Intent intent, String resolvedType, int flags, int userId) { // 获取ComponentName对象,如果该对象不为null,则表明intent指明了ComponentName ComponentName comp = intent.getComponent(); if (comp == null) { if (intent.getSelector() != null) { intent = intent.getSelector(); comp = intent.getComponent(); } } if (comp != null) { final List list = new ArrayList (1); // 根据comp获取精确的ActivityInfo final ActivityInfo ai = getActivityInfo(comp, flags, userId); if (ai != null) { final ResolveInfo ri = new ResolveInfo(); ri.activityInfo = ai; list.add(ri); } if (homeIntentRestrictedByDPM) { return getCurrentDefaultHome(list, userId); } return list; } // reader synchronized (mPackages) { final String pkgName = intent.getPackage(); if (pkgName == null) { // Check for results in the current profile. List result = mActivities.queryIntent( intent, resolvedType, flags, userId); .... return result; } // 通过包名获取Package对象 final PackageParser.Package pkg = mPackages.get(pkgName); if (pkg != null) { // 通过Package对象获取ActivityInfo List result = mActivities.queryIntentForPackage( intent, resolvedType, flags, pkg.activities, userId); if (homeIntentRestrictedByDPM) { return getCurrentDefaultHome(result, userId); } return filterIfNotPrimaryUser(result, userId); } return new ArrayList (); } }
上面方法中,当intent指明了Componet,那么直接通过ComponentName就可以找到一个ActivityInfo列表,并且该列表只有一个,如果没有指定,那么先查看Intent是否制定了需要跳转到对应的包,如果有包名,则通过包名获取对应的ActivityInfo.
到此为止,apk信息的构建以及intent的匹配就完成了。