作为Android开发者,或多或少的都接触过Android的framework层架构,这也是开发者从使用Android到了解安卓的过程,framework层的核心功能有AMS、PMS、WMS等,这三个也是系统中最基础的使用,笔者之前分析过Android进阶知识树——Android系统的启动过程 和 Android进阶知识树——应用进程的启动过程,在Android程序启动完成后回启动一系列的核心服务,AMS、PMS、WMS就是在此过程中启动的,之后的系列文章之后会一次介绍他们,本篇主要介绍PMS关于PMS文章共氛围3篇,本篇最为首篇也是PMS的主要逻辑部分;
在Android系统启动过程中,程序会执行到SystemServer中,然后调用startBootstrapServices()方法启动核心服务,在startBootstrapServices()方法中完成PMS的启动:
private void startBootstrapServices() {
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); // 1、调用main()创建PMS对象,注册Binder
mPackageManager = mSystemContext.getPackageManager(); //2、初始化PackageManager对象
}
public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
// 1、创建PMS对象
PackageManagerService m = new PackageManagerService(context, installer,factoryTest, onlyCore);
m.enableSystemUserPackages();
ServiceManager.addService("package", m); // 2、注册PMS对象到ServiceManager中
final PackageManagerNative pmn = m.new PackageManagerNative(); // 3、 创建PMN对象
ServiceManager.addService("package_native", pmn); // 4、注册PMN对象
return m;
}
@Override
public PackageManager getPackageManager() {
IPackageManager pm = ActivityThread.getPackageManager(); // 3、初始化PackageManagerService的代理Binder对象
if (pm != null) {
return (mPackageManager = new ApplicationPackageManager(this, pm)); //创建Packagemanager的实例
}
return null;
}
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
return sPackageManager;
}
IBinder b = ServiceManager.getService("package”); // 获取注册Binder
sPackageManager = IPackageManager.Stub.asInterface(b); // 获取IPackageManager代理对象,即PMS
return sPackageManager;
}
从上面的3个过程可以得出以下结论:
由上面的分析知道,在系统启动后程序执行PMS的构造函数创建对象,整个系统对程序的管理就从这里开始,先介绍下相关类和属性信息:
mSystemDir = new File(dataDir, "system"); //
mSettingsFilename = new File(mSystemDir, "packages.xml"); //获取系统目录下package.xml文件
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
mPackageListFilename = new File(mSystemDir, "packages.list”);
如:com.android.hai 10032 1 data/data/com.android.hai ,第一项:应用程序包名、第二项:Linux用户Id、第三项:1表示可以debug,0表示不能debug、第四项:程序数据文件目录
public PackageManagerService(Context context, Installer installer, // PMS的构造函数
boolean factoryTest, boolean onlyCore) {
sUserManager = new UserManagerService(context, this, // 创建UserManagerService
new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages); //1、创建保存系统信息的Settings对象
mHandlerThread = new ServiceThread(TAG,Process.THREAD_PRIORITY_BACKGROUND, true );
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper()); // 2、使用HandlerThread初始化PackageHandler对象
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false)); // 3、调用readLPw()读取并解析配置package.xml
}
final int packageSettingCount = mSettings.mPackages.size();
for (int i = packageSettingCount - 1; i >= 0; i--) {
PackageSetting ps = mSettings.mPackages.valueAt(i); // 4、遍历所有的程序的packageSettings对象
if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
&& mSettings.getDisabledSystemPkgLPr(ps.name) != null) { // 判断文件已经被删除的或程序已被卸载
mSettings.mPackages.removeAt(i); // 移除对应的PackageSettings对象
mSettings.enableSystemPackageLPw(ps.name); // 从mDisabledSysPackages集合中也移除此程序的Settings对象
}
}
File frameworkDir = new File(Environment.getRootDirectory(), "framework”); // 5、获取系统的framework文件
Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
while (pkgSettingIter.hasNext()) {
PackageSetting ps = pkgSettingIter.next();
if (isSystemApp(ps)) { // 6、保存已经安装的系统的应用程序
mExistingSystemPackages.add(ps.name);
}
}
scanDirTracedLI(frameworkDir, // 7、扫描framework文件目录
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_NO_DEX
| SCAN_AS_SYSTEM
| SCAN_AS_PRIVILEGED,
0);
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir, // 8、扫描系统app文件
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM,
0);
。。。。。。扫描各种目录下的文件信息
scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0); //9、扫描安装app目录/data/app/
mSettings.writeLPr(); // 10、写入配置文件
Runtime.getRuntime().gc();
在启动程序后,PMS的所有工作基本都在构造函数中执行的,具体的执行过程见上面代码注释,这里列出几点主要的执行步骤:
上面的几个主要过程即可实现PMS对所有安装程序的执行和管理,下面从源码的角度分析下PMS具体的执行细节;
boolean readLPw(@NonNull List<UserInfo> users) {
FileInputStream str = null;
if (mBackupSettingsFilename.exists()) { // 1、如果package-backUp.xml 文件存在,读取package-back.xml文件
str = new FileInputStream(mBackupSettingsFilename); // 一般当写入配置时发生意外才会存在此文件
}
str = new FileInputStream(mSettingsFilename); // 2、正常情况下读取package.xml文件信息
XmlPullParser parser = Xml.newPullParser(); // 3、使用PullParser解析xml文件
parser.setInput(str, StandardCharsets.UTF_8.name());
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { // 4、循环读取xml的节点数据
String tagName = parser.getName(); // 读取每个标签名称
3044 if (tagName.equals("package")) {
3045 readPackageLPw(parser); // 解析package标签中信息保存在PackageSetting对象中
3046 } else if (tagName.equals("permissions")) {
3047 mPermissions.readPermissions(parser); // 解析系统所有的权限信息,保存在PermissionSettings中
3048 } else if (tagName.equals("shared-user")) {
3051 readSharedUserLPw(parser); // 如果使用share-user,解析此标签
}
// 在解析package标签时,如果程序使用的shareUserId,则将此setting对象加入此集合,等相应共享的程序加载完成后再完善信息
final int N = mPendingPackages.size();
3172 for (int i = 0; i < N; i++) { // 5、遍历mPendingPackage集合中的PackageSetting对象,逐步完善每个对象
3173 final PackageSetting p = mPendingPackages.get(i);
3174 final int sharedUserId = p.getSharedUserId();
3175 final Object idObj = getUserIdLPr(sharedUserId); // 获取次shareUserId对应的程序
3176 if (idObj instanceof SharedUserSetting) {
3177 final SharedUserSetting sharedUser = (SharedUserSetting) idObj;
3178 p.sharedUser = sharedUser; // 完善p的信息
3179 p.appId = sharedUser.userId;
3180 addPackageSettingLPw(p, sharedUser);
3181 }
3192 }
3193 mPendingPackages.clear(); // 清除集合
}
}
文件在readLPw()中首先判断mBackupSettingsFilename文件是否存在,前面提到当更新配置文件时,系统会先将package.xml文件重名为backup文件,然后创建package.xml并将mSettings内容写入文件,写入完成之后将back-up为难删除,如果此过程发生意外则系统会保留back-up文件,再此重启PMS时会优先读取backup文件,一般情况会直接读取package.xml,读取信息后使用Xml解析文件中信息,在解析中提取每个标签中的属性,这里需要注意的是package 标签,其中包好应用程序的基本信息,程序回调用readPackageLPw()解析;
private void readPackageLPw(XmlPullParser parser) throws XmlPullParserException, IOException {
name = parser.getAttributeValue(null, ATTR_NAME); // 1、提前标签下的属性信息,保存在相应的变量中
realName = parser.getAttributeValue(null, "realName");
idStr = parser.getAttributeValue(null, "userId");
uidError = parser.getAttributeValue(null, "uidError");
sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
codePathStr = parser.getAttributeValue(null, "codePath");
.......
version = parser.getAttributeValue(null, "version");
timeStampStr = parser.getAttributeValue(null, "it");
timeStampStr = parser.getAttributeValue(null, "ut");
//2、创建PackageSetting对象保存从package标签解析出的信息,并保存在集合中mPackages集合中
packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
3836 new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString,
3837 secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags,
3838 pkgPrivateFlags, parentPackageName, null /*childPackageNames*/,
3839 null /*usesStaticLibraries*/, null /*usesStaticLibraryVersions*/);
packageSetting.setTimeStamp(timeStamp);
packageSetting.firstInstallTime = firstInstallTime;
packageSetting.lastUpdateTime = lastUpdateTime;
if (sharedIdStr != null) {//3、如果使用sharedId,则创建packageSetting对象保存在mPending集合中,稍后补充解析信息
3853 if (sharedUserId > 0) {
3854 packageSetting = new PackageSetting(name.intern(), realName, new File(
3855 codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr,
3856 primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
3857 versionCode, pkgFlags, pkgPrivateFlags, parentPackageName,
3858 null /*childPackageNames*/, sharedUserId,
3859 null /*usesStaticLibraries*/, null /*usesStaticLibraryVersions*/);
3860 packageSetting.setTimeStamp(timeStamp);
3861 packageSetting.firstInstallTime = firstInstallTime;
3862 packageSetting.lastUpdateTime = lastUpdateTime;
3863 mPendingPackages.add(packageSetting); // 4、将packageSetting保存在mPendingPackages集合中
3873 }
if (installerPackageName != null) {
mInstallerPackages.add(installerPackageName); // 添加到已安装程序列表集合中
}
在readPackageLPw()中首先从解析器parser中提取所有的标签信息,然后调用addPackageLPw()方法保存这些属性,最后当程序使用shareId时先暂时将对象的解析 添加到mPendingPackages集合中,等共享的应用执行结束后再补充信息;
PackageSetting addPackageLPw(String name,......) {
598 PackageSetting p = mPackages.get(name); //从集合中取出对象
599 if (p != null) {
600 if (p.appId == uid) {
601 return p;
602 }
606 }
607 p = new PackageSetting(name, realName, codePath, resourcePath, // 创建PackageSetting对象
608 legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
609 cpuAbiOverrideString, vc, pkgFlags, pkgPrivateFlags, parentPackageName,
610 childPackageNames, 0 /*userId*/, usesStaticLibraries, usesStaticLibraryNames);
611 p.appId = uid;
612 if (addUserIdLPw(uid, p, name)) {
613 mPackages.put(name, p); // 在mpackages中添加保存对象
614 return p;
615 }
616 return null;
617 }
}
addPackageLPw()中直接创建PackageSetting对象,将解析的信息封装起来,然后以程序的name为Key将PackageSetting对象添加的mPackages集合中,那此时mPackages就保存了手机中所有app的应用信息;
private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime) {
final File[] files = scanDir.listFiles(); // 1、获取目录下的文件集合,即所有的apk列表,然后逐个解析
try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
mParallelPackageParserCallback)) { // 2、创建ParallelPackageParser对象
int fileCount = 0;
for (File file : files) {
parallelPackageParser.submit(file, parseFlags); //3、遍历files集合,使用parallelPackageParser提交每个apk文件
fileCount++;
}
for (; fileCount > 0; fileCount--) {
ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();//4、取出每个File的扫描结果,执行scan
scanPackageChildLI(parseResult.pkg, parseFlags, scanFlags,currentTime, null);
}
}
scanDirLI()方法执行的逻辑很简单:
到这里我们知道PMS是对/data/app/目录中所有apk文件进行解析,在之前的版本中会直接创建PackageParser对象执行解析,在Androip P版本中引入ParallelPackageParser类,使用线程池和队列执行程序的解析;
private final BlockingQueue<ParseResult> mQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY); // 1、保存请求结果的队列,阻塞线程
private final ExecutorService mService = ConcurrentUtils.newFixedThreadPool(MAX_THREADS,
"package-parsing-thread", Process.THREAD_PRIORITY_FOREGROUND); // 2、创建线程池
public void submit(File scanFile, int parseFlags) {
mService.submit(() -> { // 3、线程池提交任务
ParseResult pr = new ParseResult();
try {
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
pp.setCacheDir(mCacheDir);
pp.setCallback(mPackageParserCallback);
pr.scanFile = scanFile;
pr.pkg = parsePackage(pp, scanFile, parseFlags); // 执行文件的解析扫描,将结果封装在ParseResult中
}
try {
mQueue.put(pr); // 4、将解析的结果添加到队列中
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
mInterruptedInThread = Thread.currentThread().getName();
}
});
}
public ParseResult take() {
try {
return mQueue.take(); // 从队列中取出解析结果
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException(e);
}
}
ParallelPackageParser中利用线程池处理并发问题,执行多个apk文件的解析,并使用阻塞队列的方式同步线程的数据,在submit提交的任务run()方法中,创建了PackageParser对象并调用parser()方法解析apk,之后将解析的结果封装在ParseResult中,最后添加到mQueue队列中,PMS中在依次调用take()方法从mQueue队列中获取执行的结果;
public Package parsePackage(File packageFile, int flags, boolean useCaches)
throws PackageParserException {
Package parsed = useCaches ? getCachedResult(packageFile, flags) : null; // 1、从缓存中获取解析结果
if (parsed != null) {
return parsed;
}
if (packageFile.isDirectory()) { // 2、判断是文件还是文件夹,分别执行不同的方法;
parsed = parseClusterPackage(packageFile, flags); // 执行文件夹解析
} else {
parsed = parseMonolithicPackage(packageFile, flags); // 执行单个apk文件解析,单个安装apk文件时执行
}
cacheResult(packageFile, flags, parsed); // 3、缓存解析的结果parser
return parsed;
}
ParserPackage.parser()中开始执行apk文件的解析,对于apk文件执行parseMonolithicPackage(),在执行解析结束后会缓存解析结果;
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags); // 1、使用AssetManager加载资源文件
try {
final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags); // 执行parseBaseAPk
pkg.setCodePath(apkFile.getCanonicalPath());
pkg.setUse32bitAbi(lite.use32bitAbi);
return pkg;
}
}
private static PackageLite parseMonolithicPackageLite(File packageFile, int flags) throws PackageParserException {
final ApkLite baseApk = parseApkLite(packageFile, flags);
final String packagePath = packageFile.getAbsolutePath();
return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
}
//先轻量级解析apk的基本信息
private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,SigningDetails signingDetails)
throws IOException, XmlPullParserException, PackageParserException {
final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
for (int i = 0; i < attrs.getAttributeCount(); i++) {
final String attr = attrs.getAttributeName(i);
if (attr.equals("installLocation")) {
installLocation = attrs.getAttributeIntValue(i,
PARSE_DEFAULT_INSTALL_LOCATION);
} else if (attr.equals("versionCode")) {
versionCode = attrs.getAttributeIntValue(i, 0);
} else if (attr.equals("versionCodeMajor")) {
versionCodeMajor = attrs.getAttributeIntValue(i, 0);
} else if (attr.equals("revisionCode")) {
revisionCode = attrs.getAttributeIntValue(i, 0);
}
.....
}
......
return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode,
installLocation, verifiers, signingDetails, coreApp, debuggable,
multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);
}
在parseMonolithicPackage()中先调用parseApkLite()将File先简单的解析以下,这里的解析只是获取注册清单中的基础信息,并将信息保存在ApkLite对象中,然后将ApkLite和文件路径
封装在PackageLite对象中;
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {// 参数:apk文件File、apk文件路径destCodePath
final String apkPath = apkFile.getAbsolutePath(); // 1、获取apk文件路径
mArchiveSourcePath = sourceFile.getPath();
399 int cookie = assmgr.findCookieForPath(mArchiveSourcePath); // 2、将apk的路径添加到AssetManager中加载资源
401 parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml”); // 3、解析xml注册清单文件
Resources res = new Resources(assmgr, metrics, null); // 4、创建Resource对象
pkg = parseBaseApk(res, parser, flags, errorText); // 解析parser中的信息,保存在Package对象中
pkg.setVolumeUuid(volumeUuid);
pkg.setApplicationVolumeUuid(volumeUuid);
pkg.setBaseCodePath(apkPath);
pkg.setSigningDetails(SigningDetails.UNKNOWN);
return pkg;
}
parseBaseApk()中从apkFile对象中获取apk文件路径,然后使用assmgr加载apk文件中的资源,从文件中读取注册清单文件,然后调用parseBaseApk解析注册清单;
private Package parseBaseApk(String apkPath,Resources res, XmlResourceParser parser, int flags, String[] outError){
Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser); //1、从parser中解析出“package”设置的包名pkgName
pkgName = packageSplit.first;
splitName = packageSplit.second;
Package pkg = new Package(pkgName); // 2、创建Package对象,保存apk的包名
//从Resource中获取各种信息,并保存在Package的属性中
pkg.mVersionCode = sa.getInteger(…...
pkg.mVersionName = sa.getNonConfigurationString(…...
pkg.mSharedUserId = str.intern(…...);
pkg.mSharedUserLabel = sa.getResourceId(…...
pkg.installLocation = sa.getInteger(…...
pkg.applicationInfo.installLocation = pkg.installLocation;
return parseBaseApkCommon(pkg, null, res, parser, flags, outError); // 3、调用parseBaseApkCommon()继续解析文件
}
parseBaseApk中从parser中提取注册清单中的基础信息,并封装保存在Pakage对象中,然后调用parseBaseApkCommon()方法继续解析清单文件中内容
//parseBaseApkCommon()从Parser对象中解析数据信息
int outerDepth = parser.getDepth(); // 获取parser的深度
while ((type=parser.next()) != parser.END_DOCUMENT. // 1、循环解析parser对象
804 && (type != parser.END_TAG || parser.getDepth() > outerDepth)) {
if (tagName.equals("application")) {
if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) { // 2、解析application标签
825 return null;
}else if (tagName.equals("permission")) { // 3、解析权限标签
832 if (parsePermission(pkg, res, parser, attrs, outError) == null) {
833 return null;
834 }
} else if (tagName.equals("uses-feature")) { // 4、解析使用的user-feature标签,并保存在Package的集合中
FeatureInfo fi = new FeatureInfo();
…….
pkg.reqFeatures.add(fi);
}else if (tagName.equals("uses-sdk")) { // 解析user-sdk标签
}else if (tagName.equals("supports-screens")) { // 解析support-screens标签
}
}
}
parseBaseApkCommon()中主要负责解析清单文件中的各种标签信息,其中最主要的就是解析标签下的四大组件的信息,在遇到applicaiton标签时直接调用了parseBaseApplication()执行解析;
String tagName = parser.getName();
final ApplicationInfo ai = owner.applicationInfo;
ai.theme = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
ai.descriptionRes = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
// 分别解析四大组件,将解析结果保存在Package对应的集合中
1644 if (tagName.equals("activity")) {
1645 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false);
1651 owner.activities.add(a);
1653 } else if (tagName.equals("receiver")) {
1654 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true);
1660 owner.receivers.add(a);
1662 } else if (tagName.equals("service")) {
1663 Service s = parseService(owner, res, parser, attrs, flags, outError);
1669 owner.services.add(s);
1671 } else if (tagName.equals("provider")) {
1672 Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
1678 owner.providers.add(p);
1680 }
清单文件解析共分两部分:
下面逐个分析下四大组件是如何解析保存的:
private Activity parseActivity(Package owner,...)
throws XmlPullParserException, IOException {
TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>”; // 1、判断为activity或receiver
cachedArgs.mActivityArgs.sa = sa;
cachedArgs.mActivityArgs.flags = flags;
Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo()); // 2、创建Activity实例,并初始化系列属性
a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
owner.applicationInfo.taskAffinity, str, outError);
a.info.launchMode = ...
if (parser.getName().equals("intent-filter")) { // 3、解析intent-filter
ActivityIntentInfo intent = new ActivityIntentInfo(a);
if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
intent, outError)) {
return null;
}
a.order = Math.max(intent.getOrder(), a.order);
a.intents.add(intent); // 将intent设置到Activity
}
return a;
在解析Activity和Receiver标签时,当标签设置intent-filter时则创建一个ActivityIntentInfo对象,并调用parseIntent()将intent-filter标签下的信息解析到ActivityIntentInfo中,并将ActivityIntentInfo对象保存在a.intents的集合中,简单的说一个intent-filter对应一个ActivityIntentInfo对象,一个Activity和Receiver可以包好多个intent-filter;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
String nodeName = parser.getName(); // 1、获取节点名称
if (nodeName.equals("action")) { //2、处理action节点
String value = parser.getAttributeValue( // 3、获取action节点的name属性,并保存在outInfo属性中
ANDROID_RESOURCES, "name");
outInfo.addAction(value); //
} else if (nodeName.equals("category")) {
String value = parser.getAttributeValue( // 4、获取category属性,保存在outInfo属性中
ANDROID_RESOURCES, "name");
outInfo.addCategory(value); // 添加到Category集合中
} else if (nodeName.equals("data")) {
sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestData); // 解析parser为sa属性
String str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
outInfo.addDataType(str); // 获取并保存mimeType中
str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
outInfo.addDataScheme(str); // 获取并保存scheme中
String host = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestData_host, 0); //
String port = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestData_port, 0);
outInfo.addDataAuthority(host, port); // 获取并保存host、port属性
outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT); // 设置Default属性
}
public final static class ActivityIntentInfo extends IntentInfo {}
public static abstract class IntentInfo extends IntentFilter {}
public final void addAction(String action) {
if (!mActions.contains(action)) {
mActions.add(action.intern()); // 在Intent-Filter中保存action
}
}
public final void addCategory(String category) {
if (mCategories == null) mCategories = new ArrayList<String>();
if (!mCategories.contains(category)) {
mCategories.add(category.intern()); //
}
}
public final void addDataScheme(String scheme) {
if (mDataSchemes == null) mDataSchemes = new ArrayList<String>();
if (!mDataSchemes.contains(scheme)) {
mDataSchemes.add(scheme.intern()); //
}
}
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestService);
cachedArgs.mServiceArgs.sa = sa;
cachedArgs.mServiceArgs.flags = flags;
Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo()); // 创建Service对象
if (parser.getName().equals("intent-filter")) { // 解析intent-filter节点
ServiceIntentInfo intent = new ServiceIntentInfo(s);
if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
intent, outError)) {
return null;
}
s.order = Math.max(intent.getOrder(), s.order);
s.intents.add(intent);
} else if (parser.getName().equals("meta-data")) { // 解析meta-data数据,保存在bundle中
if ((s.metaData=parseMetaData(res, parser, s.metaData,
outError)) == null) {
return null;
}
}
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestProvider);
cachedArgs.mProviderArgs.tag = "<provider>";
cachedArgs.mProviderArgs.sa = sa;
cachedArgs.mProviderArgs.flags = flags;
Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo()); // 创建Provider对象
p.info.exported = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestProvider_exported,
providerExportedDefault);
String permission = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
p.info.multiprocess = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
false);
p.info.authority = cpname.intern();
if (!parseProviderTags( // 调用parseProvider解析provider下的标签
res, parser, visibleToEphemeral, p, outError)) {
return null;
}
在解析provider标签中,创建ProviderInfo对象保存设置的属性信息,如export、permission等,然后调用parseProviderTags解析provider标签中使用的其他标签信息
private boolean parseProviderTags(Resources res, XmlResourceParser parser,
boolean visibleToEphemeral, Provider outInfo, String[] outError){
int outerDepth = parser.getDepth();
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG
|| parser.getDepth() > outerDepth)) {
if (parser.getName().equals("intent-filter")) {
ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
intent, outError)) {
return false;
}
outInfo.order = Math.max(intent.getOrder(), outInfo.order);
outInfo.intents.add(intent);
}
if (parser.getName().equals("meta-data")) {
if ((outInfo.metaData=parseMetaData(res, parser,
outInfo.metaData, outError)) == null) {
return false;
}
}
if (parser.getName().equals("grant-uri-permission")) {
String str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
PatternMatcher pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL); // 创建PatterMatcher匹配权限
PatternMatcher[] newp = new PatternMatcher[N+1];
newp[N] = pa;
outInfo.info.uriPermissionPatterns = newp; // 保存临时权限数组
}
if (parser.getName().equals("path-permission")) { // 保存路径权限
newp[N] = pa;
outInfo.info.pathPermissions = newp;
}
}
}
主要解析如下:
到此apk文件已经解析完成,相应的文件和属性都封装在Package对象中,并都保存在PMS属性集合mPackages集合中;
在使用线程池执行所有的apk解析后,所有的解析结果都保存在队列中,系统会循环调用take()方法取出解析的结果
for (; fileCount > 0; fileCount--) {
ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
scanPackageChildLI(parseResult.pkg, parseFlags, scanFlags,
currentTime, null);
}
取出apk文件解析结果后,调用scanPackageChildLI()扫描获取到的ParseResult中的Pakcage对象,scanPackageChildLI()中直接调用addForInitLI()方法
synchronized (mPackages) {
final PackageSetting installedPkgSetting = mSettings.getPackageLPr(pkg.packageName); // 1、获取从配置文件中读取的Settings
final PackageParser.Package scannedPkg = scanPackageNewLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user); // 调用scanPackageNewLI将pkg中的数据保存到PMS的变量中
}
// scanPackageNewLI():创建ScanRequest对象,执行文件扫描修改或更新对应的PackageSetting对象
final ScanRequest request = new ScanRequest(pkg, sharedUserSetting,
pkgSetting == null ? null : pkgSetting.pkg, pkgSetting, disabledPkgSetting,
originalPkgSetting, realPkgName, parseFlags, scanFlags,
(pkg == mPlatformPackage), user);
final ScanResult result = scanPackageOnlyLI(request, mFactoryTest, currentTime);
if (result.success) {
commitScanResultsLocked(request, result); // 调用commitScanResultsLocked()
}
commitScanResultsLocked()中直接调用commitPackageSettings()调教apk的解析数据
commitPackageSettings(pkg, oldPkg, pkgSetting, user, scanFlags,
(parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/); // 提交包解析数据
final String pkgName = pkg.packageName;
if (pkg.packageName.equals("android")) { // 1、针对系统包,特殊处理属性的初始化
mPlatformPackage = pkg;
2897 pkg.mVersionCode = mSdkVersion;
2898 mAndroidApplication = pkg.applicationInfo;
2899 mResolveActivity.applicationInfo = mAndroidApplication;
2900 mResolveActivity.name = ResolverActivity.class.getName();
。。。。。。
2912 mResolveComponentName = new ComponentName(
2913 mAndroidApplication.packageName, mResolveActivity.name);
}
int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2950 for (int i=0; i<N; i++) {
2951 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
mTmpSharedLibraries[num] = file; // 遍历所有的user-library标签保存在数组中
2960 num++;
2961 }
if (!verifySignaturesLP(pkgSetting, pkg)) { // 校验签名文件
…….
}
int N = pkg.providers.size();
3404 StringBuilder r = null;
3405 int i;
3406 for (i=0; i<N; i++) {
3407 PackageParser.Provider p = pkg.providers.get(i); //遍历提取每个provider
3408 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
3409 p.info.processName, pkg.applicationInfo.uid);
3410 mProvidersByComponent.put(new ComponentName(p.info.packageName,
3411 p.info.name), p); // 针对Provider创建ComponentName对象,保存在mProvidersByComponent集合中
3413 if (p.info.authority != null) {
3414 String names[] = p.info.authority.split(";”); // 获取Provider的权限信息
3415 p.info.authority = null;
3416 for (int j = 0; j < names.length; j++) {
3417 if (j == 1 && p.syncable) {
3425 p = new PackageParser.Provider(p);
3426 p.syncable = false;
3427 }
3428 if (!mProviders.containsKey(names[j])) {
3429 mProviders.put(names[j], p); // 将权限和对应的Provider以键值对保存在 mProviders 集合中
3447 }
3448 }
3457 }
3460 }
N = pkg.services.size();
3463 r = null;
3464 for (i=0; i<N; i++) {
3465 PackageParser.Service s = pkg.services.get(i);
3466 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
3467 s.info.processName, pkg.applicationInfo.uid);
3468 mServices.addService(s);
N = pkg.receivers.size();
3483 r = null;
3484 for (i=0; i<N; i++) {
3485 PackageParser.Activity a = pkg.receivers.get(i);
3486 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3487 a.info.processName, pkg.applicationInfo.uid);
3488 mReceivers.addActivity(a, "receiver");
3497 }
N = pkg.activities.size();
3503 r = null;
3504 for (i=0; i<N; i++) {
3505 PackageParser.Activity a = pkg.activities.get(i);
3506 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3507 a.info.processName, pkg.applicationInfo.uid);
3508 mActivities.addActivity(a, "activity");
}
在commitPackageSettings中,主要是将每个apk文件获得的Package对象中保存的四大组件信息分别提取保存在PMS内部对应的属性中,在PMS内部有4个专门储存四大组件的属性:
final ActivityIntentResolver mActivities = new ActivityIntentResolver();
final ActivityIntentResolver mReceivers = new ActivityIntentResolver();
final ServiceIntentResolver mServices = new ServiceIntentResolver();
final ProviderIntentResolver mProviders = new ProviderIntentResolver();
public final void addActivity(PackageParser.Activity a, String type) {
mActivities.put(a.getComponentName(), a); // 1、获取内部的Component对象,在Activity会自动创建Component对象
final int NI = a.intents.size();
for (int j=0; j<NI; j++) {
PackageParser.ActivityIntentInfo intent = a.intents.get(j); // 获取Activity中设置的intent
addFilter(intent); // 添加Intent过滤
}
}
public final void addService(PackageParser.Service s) {
mServices.put(s.getComponentName(), s); //保存service
final int NI = s.intents.size();
int j;
for (j=0; j<NI; j++) {
PackageParser.ServiceIntentInfo intent = s.intents.get(j);
addFilter(intent);
}
}
public final void addProvider(PackageParser.Provider p) {
if (mProviders.containsKey(p.getComponentName())) {
return;
}
mProviders.put(p.getComponentName(), p); // 保存provider
final int NI = p.intents.size();
int j;
for (j = 0; j < NI; j++) {
PackageParser.ProviderIntentInfo intent = p.intents.get(j);
addFilter(intent); // 添加查找过滤的intent
}
}
void writeLPr() {
if (mSettingsFilename.exists()) {
if (!mBackupSettingsFilename.exists()) { // 重命名文件
if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
Slog.wtf(PackageManagerService.TAG,
"Unable to backup package manager settings, "
+ " current changes will be lost at reboot");
return;
}
} else {
mSettingsFilename.delete(); //删除package文件
}
}
FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
BufferedOutputStream str = new BufferedOutputStream(fstr);
。。。。。。
for (final PackageSetting pkg : mPackages.values()) {
writePackageLPr(serializer, pkg); // 写入配置信息
}
.......
}
writePackageListLPr(); // 更新package.list文件
到此PMS的启动过程介绍完毕,简单来说系统在启动会会创建PMS对象,使用PMS对象读取配置文件,然后扫描手机上所有的app程序,并将所有的程序的内容信息都封装在Package对象中,然后将Package集合中信息转换为PMS的属性供系统使用,最后并更新配置文件;