转自
http://blog.chinaunix.net/space.php?uid=433806&do=blog&id=270768Android110427: PackageManagerService注记
Email: zcatt@163.com
Blog http://zcatt.blog.chinaunix.net
内容提要
Android如何寻找intent受体.以供备忘和参考。
声明
仅限学习交流,禁止商业用途。转载需注明出处。
版本记录
Date Ver Note
2011-04-27 0.1 Draft. zcatt, Beijing
PackageManagerService的方法大致可以分成这样几类,
1)从apk, xml中载入pacakge信息, 存储到内部成员变量中, 用于后面的查找. 关键的方法是scanPackageLI().
2)各种查询操作, 包括query Intent操作.
3)install package和delete package的操作. 关键的方法是installPackageLI().
4)其它操作, 包括permission, signature, freeStorage等等.
首先看看PacakgeManagerService用到的几个重要的支撑类, 然后罗列几个PackageManagerService的几个关键内部数据成员变量. 最后注记几个关键流程.
PackageManagerService用到了几个重要的支撑类:
PackageParser, 这个类主要用于解析apk, 分析其AndroidManifest.xml得到package的各种信息. 前已有注记文章,此不赘述. 特别的PackageParser.Package这个类用于容纳解析出的信息.
PackageManagerService.Settings, 用于容纳当前有效的package信息, 它是动态的. 例如, user id, shareUser, permission, signature以及origPackage(也就是mRenamedPackages)相关信息. 所谓的install package就包括从要安装的package中抽取信息更新PackageManagerService.Settings中的内容. 特别的, Settings针对shareUser和origPackage做了特别的关照. 另外, 为了加速启动速度, Settings的内容会写入到/data/system/packages.xml, packages-backup.xml, 和packages.list中, 下次启动时会直接载入.
Installer, 这个类协助安装过程, 更多的是将针对文件/路径的操作放到了c/cpp实现. 真正的工作是是由installd承担的, Installer只是通过named socket "installd"连接installd, 使用简单的cmd-respond协议指挥installd完成工作. 在其'install'命令中可以看到, 其实只是创建了/data/data/目录而已.
PackageManagerService中的几个关键成员变量:
- // (pkgName => Package), package is the one installed.
- final HashMap<String, PackageParser.Package> mPackages =
- new HashMap<String, PackageParser.Package>();
- // current package settings info, such as userid, origPackage
- // , shareUser, permission, signature, etc
- final Settings mSettings;
- // (system uid => permission), permissions read from /system/etc/permissions/ are stored here.
- // especially /system/etc/permissions/platform.xml
- final SparseArray<HashSet<String>> mSystemPermissions =
- new SparseArray<HashSet<String>>();
- //(pkgName => sharedLib), corresponding to tag
- final HashMap<String, String> mSharedLibraries =
- new HashMap<String, String>();
- // All available activities, for resolving intent
- final ActivityIntentResolver mActivities =
- new ActivityIntentResolver();
- // All available receivers, for resolving intent
- final ActivityIntentResolver mReceivers =
- new ActivityIntentResolver();
- // All available services, for resolving intent
- final ServiceIntentResolver mServices =
- new ServiceIntentResolver();
几个关键流程,初始化过程--------------PackageManagerService由SystemServer在创建ActivityManagerService后调用main创建, 是单实例的.- Slog.i(TAG, "Power Manager");
- power = new PowerManagerService();
- ServiceManager.addService(Context.POWER_SERVICE, power);
- Slog.i(TAG, "Activity Manager");
- context = ActivityManagerService.main(factoryTest);
- Slog.i(TAG, "Telephony Registry");
- ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
- AttributeCache.init(context);
- Slog.i(TAG, "Package Manager");
- pm = PackageManagerService.main(context,
- factoryTest != SystemServer.FACTORY_TEST_OFF);
- ActivityManagerService.setSystemProcess();
- mContentResolver = context.getContentResolver();
在构造函数中, PackageManagerService会做这些工作,1)启动自己的handlerThread, 生成自己的mHandler. 2)从/system/etc/permissions/的所有xml文件中, 尤其是platform.xml, 读入systemPermissions. 这些是系统默认的permission配置.3)扫描/system/framework/, /system/app/, /data/app/, 和/data/app-private/下的apk文件, 收集package各种信息, 更新到内部成员变量中. 这些将在PackageManagerService执行各种功能时用到. 尤其是query intent.更详尽的笔记,PackageManagerService mHandlerThread.start(); mHandler = new PackageHandler(mHandlerThread.getLooper()); readPermissions(); mRestoredSettings = mSettings.readLP(); --/system/framework/ scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode | SCAN_NO_DEX); --/system/app/ scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode); --Prune any system packages that no longer exist. --clean up any incomplete package installations --delete tmp files --/data/app/ scanDirLI(mAppInstallDir, 0, scanMode); --/data/app-private/ scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode); mSettings.writeLP();private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanMode) PackageParser pp = new PackageParser(scanPath); pkg = pp.parsePackage(scanFile, scanPath, mMetrics, parseFlags); collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags) setApplicationInfoPaths(pkg, codePath, resPath); scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE); --set mAndroidApplication and mResolveActivity to'Android' package --Check all shared libraries and map to their actual file path. --check pkg.usesLibraries are contained in mSharedLibraries. --fill in pkg.usesLibraryFiles according to pkg.usesLibraries and pkg.usesOptionalLibraries --check pkg.reqFeatures in mAvailableFeatures --if not in mSettings, create one ShareUserSettings and insert into mSettings. --Check and note if we are renaming from an original package name pkgSetting = mSettings.getPackageLP(pkg, origPackage, realName, suid, destCodeFile, destResourceFile, pkg.applicationInfo.flags, true, false); verifySignaturesLP(pkgSetting, pkg); --Verify that this new package doesn't have any content providers that conflict with existing packages. --get data dir. if not exists, install or create the data dir. if exists but uid not correct, reinstall. --Perform shared library installation and dex validation and optimization, if this is not a system app. --Request the ActivityManager to kill the process(only for existing packages) mSettings.insertPackageSettingLP(pkgSetting, pkg); --Add the new setting to mSettings mPackages.put(pkg.applicationInfo.packageName, pkg); --set mProvidersByComponent and mProviders according to pkg.providers --set mServices according to pkg.services --set mReceivers according to pkg.receivers --set mActivites according to pkg.activities --set mPermissionGroups according to pkg.permissionGroups --set mSettings.mPermissionTrees or mSettings.mPermissions according to pkg.permissions --set mInstrumentation according to pkg.instrumentation --set mProtectedBroadcasts according to pkg.protectedBroadcastsinstall package过程--------------install package的入口是installPackage(). install package通常是个耗时的过程, 因此会使用到android的handler机制.首先, 参数封装成INIT_COPY message, 发到handlerThread.handlerThread收到message后, 将参数排队到mPendingInstalls中. 随后,MCS_BOUND流程将会处理这个队列, 执行安装.MCS_BOUND的整个安装流程借助了几个InstallParams和InstallArgs完成其中的参数和安装结果的传递. 最终会调用processPendingInstall(), 进而调用到install过程的核心 installPackageLI().installPackageLI()的复杂性很大程度上是考虑了1)新安装还是升级情况, 2)origPackage情况.
阅读(2167) | 评论(0) | 转发(1) |