PackageManagerService注记

Email:    [email protected]
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情况.

你可能感兴趣的:(PackageManagerService注记)