PackageManagerService注记
发布日期:2021-09-28 18:45:49 浏览次数:4 分类:技术文章

本文共 6489 字,大约阅读时间需要 21 分钟。

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/<pkgName>目录而已.
PackageManagerService中的几个关键成员变量:
  1. // (pkgName => Package), package is the one installed.
  2. final HashMap<String, PackageParser.Package> mPackages =
  3.             new HashMap<String, PackageParser.Package>();
  4. // current package settings info, such as userid, origPackage
  5. // , shareUser, permission, signature, etc
  6. final Settings mSettings;
  7. // (system uid => permission), permissions read from /system/etc/permissions/<files> are stored here.
  8. // especially /system/etc/permissions/platform.xml
  9. final SparseArray<HashSet<String>> mSystemPermissions =
  10.             new SparseArray<HashSet<String>>();
  11. //(pkgName => sharedLib), corresponding to <library> tag
  12. final HashMap<String, String> mSharedLibraries =
  13.             new HashMap<String, String>();
  14. // All available activities, for resolving intent
  15. final ActivityIntentResolver mActivities =
  16.             new ActivityIntentResolver();
  17. // All available receivers, for resolving intent
  18. final ActivityIntentResolver mReceivers =
  19.             new ActivityIntentResolver();
  20. // All available services, for resolving intent
  21. final ServiceIntentResolver mServices =
  22.             new ServiceIntentResolver();
几个关键流程,
初始化过程
--------------
PackageManagerService由SystemServer在创建ActivityManagerService后调用main创建, 是单实例的.
  1.     Slog.i(TAG, "Power Manager");
  2.     power = new PowerManagerService();
  3.     ServiceManager.addService(Context.POWER_SERVICE, power);
  4.     Slog.i(TAG, "Activity Manager");
  5.     context = ActivityManagerService.main(factoryTest);
  6.     Slog.i(TAG, "Telephony Registry");
  7.     ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
  8.     AttributeCache.init(context);
  9.     Slog.i(TAG, "Package Manager");
  10.     pm = PackageManagerService.main(context,
  11.             factoryTest != SystemServer.FACTORY_TEST_OFF);
  12.     ActivityManagerService.setSystemProcess();
  13.     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.protectedBroadcasts
install 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情况.

转载地址:https://blog.csdn.net/h3c4lenovo/article/details/8109385 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Android apk dex与odex
下一篇:PackageInstaller 原理简述

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年03月11日 08时15分04秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章