PackageManagerService架构剖析开篇

PackageManagerService在Android中的非常重要,主要负责的功能如下:
1.解析AndroidManifest.xml,主要包括AndroidManifest中节点信息的解析和target-name的分析和提炼,这部分和ActivityManagerService和WindowManagerService都有紧急的联系。关于AndroidManifest.xml中的属性设置,会单独拎出来讲解,本文不扩展讲解。
2.扫描本地文件,主要针对apk,主要是系统应用、本地安装应用等等。这部分会在下面仔细讲解。
3.管理本地apk,主要包括安装、删除等等。
下面称PackageManagerService为PMS

一、PMS启动

PMS是系统的关键服务,也是在system_server进程中启动的,同AMS与其他的系统服务,下面是PMS的启动流程:


PackageManagerService架构剖析开篇_第1张图片
PackageManagerService启动流程.jpg

上面是PMS启动流程,PMS还是从systemServer中启动的系统服务,主要关注一下PMS在构造函数中做了什么,构造函数中一般是初始化PMS中需要使用的线程和读取基本的配置。

1.1 PMS系统服务注册的地方

PMS中的main函数中有PMS服务的注册,还是将PMS注册到ServiceManager中,然后service写入/dev/binder中,可以实现用户空间和内核空间的通信,这是binder通信机制相关的知识。

PackageManagerService.java
public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        // Self-check for initial settings.
        PackageManagerServiceCompilerMapping.checkProperties();

        PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
        m.enableSystemUserPackages();
        ServiceManager.addService("package", m);
        final PackageManagerNative pmn = m.new PackageManagerNative();
        ServiceManager.addService("package_native", pmn);
        return m;
    }

除了PMS,这儿还注册了“package_native”的服务,这个服务主要是给native代码调用的,包含3个函数,获取package的相关信息(versionCode、uid、Installer相关信息)。

 PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);

这里传入PMS构造中的几个参数需要了解一下。
1.context,上下文。
2.installer,类是Installer.java
frameworks/base/services/core/java/com/android/server/pm/Installer.java

public class Installer extends SystemService {
//......
}

这是一个负责package安装、删除、迁移、更新的系统服务。因为PMS中需要管理package,那么就需要installer实例的协助。
3.factoryTest,当前是否是测试模式。
4.onlyCore,onlyCore为true表明当前的设置正在加密或者已经是加密的,说明此时只能运行核心app,刚开始不会扫描非系统app,这个会在扫描流程中详细说明下。

1.2 PMS构造函数剖析

PMS的构造函数代码非常多,有800多行,这么多代码,需要仔细剖析一下。这儿按照执行顺序将PMS构造函数分为下面几块:

1.2.1 设置uid属性

这里主要设置的是shareUsers属性,放在Settings中的ArrayMap中,先存起来。

1.2.2 初始化package解析和管理的对象

主要初始化的类是:
1.PackageDexOptimizer
2.DexManager
3.ArtManagerService
4.ProtectedPackages

1.2.3 创建PackageHandler处理package管理中消息
1.2.4 扫描系统app和系统目录下的jar
1.2.5 扫描应用app和应用目录下的lib

这个步骤的执行是有条件的,具体条件是 1.1小节中提到的onlyCore变量,如果onlyCore为false,才会执行扫描操作。

PackageManagerService.java

            // Find base frameworks (resource packages without code).
            scanDirTracedLI(frameworkDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_IS_PRIVILEGED,
                    scanFlags | SCAN_NO_DEX, 0);

            // Collected privileged system packages.
            final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
            scanDirTracedLI(privilegedAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);

            // Collect ordinary system packages.
            final File systemAppDir = new File(Environment.getRootDirectory(), "app");
            scanDirTracedLI(systemAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

它们都是调用scanDirTracedLI,除了检索的目录不同,这个函数值得进一步探讨。
下面挑出final File systemAppDir = new File(Environment.getRootDirectory(), "app");
这个Environment.getRootDirectory()是什么?

private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system");
private static final File DIR_ANDROID_DATA = getDirectory(ENV_ANDROID_DATA, "/data");
public static File getRootDirectory() {
        return DIR_ANDROID_ROOT;
    }

说明这个systemAppDir目录就是/system/app/,存放系统应用的地方。
接下里讨论一下scanDirTracedLI(...)做什么。
先阐述一下scanDirTracedLI(...)的调用流程:


PackageManagerService架构剖析开篇_第2张图片
scanDirTraceLI流程.jpg

这儿做的事情很简单,总结起来就是解析/system/app 目录下面的所有apk,然后解析其中的文件,例如解析AndroidManifest.xml,解析assets,解析res等等,分别使用存储结构存储起来,这些数据在后面都会用到,本文只谈大纲,代码的详细分析流程我后面会重新开章节讲解,请见谅。

二、PMS结构分析

分析PMS的代码结构,有助于我们从整体架构的角度来分析PMS。

PackageManagerService.java
public class PackageManagerService extends IPackageManager.Stub
        implements PackageSender {
}

IPackageManager.Stub是IPackageManager.aidl自动生成的,正好也说明了PMS是service端的,通过binder交互,这里主要看看IPackageManager.aidl有什么主要的方法。
我简单的分为下面几类:

2.1 权限管理方法

    PermissionInfo getPermissionInfo(String name, String packageName, int flags);
    ParceledListSlice queryPermissionsByGroup(String group, int flags);
    PermissionGroupInfo getPermissionGroupInfo(String name, int flags);
    ParceledListSlice getAllPermissionGroups(int flags);
    int checkPermission(String permName, String pkgName, int userId);
    int checkUidPermission(String permName, int uid);
    boolean addPermission(in PermissionInfo info);
    void removePermission(String name);
    void grantRuntimePermission(String packageName, String permissionName, int userId);
    void revokeRuntimePermission(String packageName, String permissionName, int userId);
    void resetRuntimePermissions();
    int getPermissionFlags(String permissionName, String packageName, int userId);
    void updatePermissionFlags(String permissionName, String packageName, int flagMask,
            int flagValues, int userId);
    void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId);
    boolean shouldShowRequestPermissionRationale(String permissionName,
            String packageName, int userId);

2.2 通用属性方法

    PackageInfo getPackageInfo(String packageName, int flags, int userId);
    PackageInfo getPackageInfoVersioned(in VersionedPackage versionedPackage,
            int flags, int userId);
    int getPackageUid(String packageName, int flags, int userId);
    int[] getPackageGids(String packageName, int flags, int userId);
    ApplicationInfo getApplicationInfo(String packageName, int flags ,int userId);
    ActivityInfo getActivityInfo(in ComponentName className, int flags, int userId);
    boolean activitySupportsIntent(in ComponentName className, in Intent intent,
            String resolvedType);
    ActivityInfo getReceiverInfo(in ComponentName className, int flags, int userId);
    ServiceInfo getServiceInfo(in ComponentName className, int flags, int userId);
    ProviderInfo getProviderInfo(in ComponentName className, int flags, int userId);

2.3 组件处理方法

    ParceledListSlice queryIntentActivities(in Intent intent,
            String resolvedType, int flags, int userId);
    ParceledListSlice queryIntentActivityOptions(
            in ComponentName caller, in Intent[] specifics,
            in String[] specificTypes, in Intent intent,
            String resolvedType, int flags, int userId);
    ParceledListSlice queryIntentReceivers(in Intent intent,
            String resolvedType, int flags, int userId);
    ResolveInfo resolveService(in Intent intent,
            String resolvedType, int flags, int userId);
    ParceledListSlice queryIntentServices(in Intent intent,
            String resolvedType, int flags, int userId);
    ParceledListSlice queryIntentContentProviders(in Intent intent,
            String resolvedType, int flags, int userId);
    ProviderInfo resolveContentProvider(String name, int flags, int userId);
    void querySyncProviders(inout List outNames,
            inout List outInfo);
    ParceledListSlice queryContentProviders(
            String processName, int uid, int flags, String metaDataKey);
    ComponentName getInstantAppResolverComponent();
    ComponentName getInstantAppResolverSettingsComponent();
    ComponentName getInstantAppInstallerComponent();

2.4 其他方法

//......
    boolean isFirstBoot();
    boolean isOnlyCoreApps();
    boolean isUpgrade();
    boolean isStorageLow();
//......

这儿并没有列出所有的方法,这些方法大家了解即可,不需要一个一个方法去抠,只需要抓住核心调用方法,最好和app开发结合起来理解即可。

PackageSender接口是主要处理receiver的,这些个receiver都是解析AndroidManifest的时候得到的receiver,了解即可。

interface PackageSender {
    void sendPackageBroadcast(final String action, final String pkg,
        final Bundle extras, final int flags, final String targetPkg,
        final IIntentReceiver finishedReceiver, final int[] userIds);
    void sendPackageAddedForNewUsers(String packageName, boolean isSystem,
        int appId, int... userIds);
}

三、小结

本文简单分析了PMS的启动和构造函数,只阐述了大纲,我的思路是接下来会用一个章节讨论一下PMS是如何解析apk的。谢谢大家。

你可能感兴趣的:(PackageManagerService架构剖析开篇)