欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

PackageManagerService简要分析

程序员文章站 2024-03-15 14:10:12
...

PackageManagerService主要职责
1 给应用程序分配Linux UID 和 GID
2 管理系统权限
3 扫描APK安装信息(解析AndroidManifest.xml)
4 提供查询四大组件等服务
5 APP安装与卸载

1 给应用程序分配Linux UID
Android 系统中 UID/GID 介绍:
UID 为用户 ID 的缩写,GID 为用户组 ID 的缩写,这两个概念均与 Linux 系统中进程的权限管理有关。
一般说来,每一个进程都会有一个对应的 UID(即表示该进程属于哪个 user,不同 user 有不同权限)。
一个进程也可分属不同的用户组(每个用户组都有对应的权限)。

UID分为独立的Linux用户ID和共享Linux用户ID,如果没有在manifest中声明android:sharedUserId会给APP分配一个普通的UID,
如果使用android:sharedUserId,那对应的android:sharedUserId相同的APP将共享同一个UID
// SystemUI AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
        package="com.android.systemui"
        android:sharedUserId="android.uid.systemui"
        coreApp="true">

1 PackageManagerService 初始化时, 会调用Settings类的addSharedUserLPw函数添加一些默认的Linux共享UID
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
        SharedUserSetting s = mSharedUsers.get(name);
        if (s != null) {
            if (s.userId == uid) {
                return s;
            }
            PackageManagerService.reportSettingsProblem(Log.ERROR,
                    "Adding duplicate shared user, keeping first: " + name);
            return null;
        }
                // 一个SharedUserSetting对象对应一个Linux共享UID的描述
        s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
        s.userId = uid;
        if (addUserIdLPw(uid, s, name)) {
            mSharedUsers.put(name, s);
            return s;
        }
        return null;
}

private boolean addUserIdLPw(int uid, Object obj, Object name) {
        if (uid > Process.LAST_APPLICATION_UID) {
            return false;
        }
                // 普通APP的UID 大于 Process.FIRST_APPLICATION_UID 
        if (uid >= Process.FIRST_APPLICATION_UID) {
            int N = mUserIds.size();
            final int index = uid - Process.FIRST_APPLICATION_UID;
            while (index >= N) {
                mUserIds.add(null);
                N++;
            }
            if (mUserIds.get(index) != null) {
                PackageManagerService.reportSettingsProblem(Log.ERROR,
                        "Adding duplicate user id: " + uid
                        + " name=" + name);
                return false;
            }
            // 普通UID的添加,obj对为PackageSetting的实例对象
            mUserIds.set(index, obj);
        } else {
            if (mOtherUserIds.get(uid) != null) {
                PackageManagerService.reportSettingsProblem(Log.ERROR,
                        "Adding duplicate shared id: " + uid
                                + " name=" + name);
                return false;
            }
            // 将对应的SharedUserSetting对象保存在Settings类的mOtherUserIds中
            mOtherUserIds.put(uid, obj);
        }
        return true;
    }

2 PackageManagerService 会扫描/system/priv-app, /system/app,/vendor/app等目录下apk中的AndroidManifest.xml文件,
scanDirTracedLI扫描过于复杂,后面再详细介绍
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);

scanDirTracedLI最终会调用scanPackageDirtyLI,scanPackageDirtyLI中又接着调用Settings类的addUserToSettingLPw函数
scanPackageDirtyLI
    mSettings.addUserToSettingLPw(pkgSetting);

   /**
     * Registers a user ID with the system. Potentially allocates a new user ID.
     * @throws PackageManagerException If a user ID could not be allocated.
     */
    // 分配一个新的Linux UID
    void addUserToSettingLPw(PackageSetting p) throws PackageManagerException {
        if (p.appId == 0) {
            // Assign new user ID
            p.appId = newUserIdLPw(p);
        } else {
            // Add new setting to list of user IDs
            addUserIdLPw(p.appId, p, p.name);
        }
        if (p.appId < 0) {
            PackageManagerService.reportSettingsProblem(Log.WARN,
                    "Package " + p.name + " could not be assigned a valid UID");
            throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                    "Package " + p.name + " could not be assigned a valid UID");
        }
    }
2 管理系统权限
1 扫描系统默认的权限
ArrayMap<String, SystemConfig.PermissionEntry> permConfig
        = systemConfig.getPermissions();
for (int i=0; i<permConfig.size(); i++) {
    SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
    BasePermission bp = mSettings.mPermissions.get(perm.name);
    if (bp == null) {
        bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
        mSettings.mPermissions.put(perm.name, bp);
    }
    if (perm.gids != null) {
        bp.setGids(perm.gids, perm.perUser);
    }
}

mSystemPermissions = systemConfig.getSystemPermissions();
SystemConfig() {
        // 读取system目录下的XML文件信息
        // Read configuration from system
        readPermissions(Environment.buildPath(
                Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
        // Read configuration from the old permissions dir
        readPermissions(Environment.buildPath(
                Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
        // Allow Vendor to customize system configs around libs, features, permissions and apps
        int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
                ALLOW_APP_CONFIGS;
        // 读取vendor目录下的XML文件信息
        readPermissions(Environment.buildPath(
                Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
        readPermissions(Environment.buildPath(
                Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
        // Allow ODM to customize system configs around libs, features and apps
        int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
        readPermissions(Environment.buildPath(
                Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
        readPermissions(Environment.buildPath(
                Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
        // Only allow OEM to customize features
        readPermissions(Environment.buildPath(
                Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES);
        readPermissions(Environment.buildPath(
                Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES);
    }

2 读取apk中的AndroidManifest.xml解析的权限信息
commitPackageSettings
    N = pkg.permissions.size();
    for (i=0; i<N; i++) {
                // permissionMap 为 mSettings.mPermissions,和上面的mSettings.mPermissions.put(perm.name, bp);对应
        ArrayMap<String, BasePermission> permissionMap =
                p.tree ? mSettings.mPermissionTrees
                        : mSettings.mPermissions;
            BasePermission bp = permissionMap.get(p.info.name);
            if (bp == null) {
                bp = new BasePermission(p.info.name, p.info.packageName,
                        BasePermission.TYPE_NORMAL);
                // 将BasePermission添加到mSettings.mPermissions中
                permissionMap.put(p.info.name, bp);
      }

3 Android6.0以后引入了动态权限 
动态权限的核心工作流程:
checkSelfPermission(检查是否已被授予)
requestPermissions(申请权限)
onRequestPermissionsResult(自动回调)
checkSelfPermission 最终调用 PackageManagerService中的checkUidPermission函数
requestPermissions 最终调用 PackageManagerService中的grantRuntimePermission函数
3 扫描APK安装信息
//  扫描/system/framework目录
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
// 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);

//  扫描/system/priv-app目录
// 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);

//  扫描/system/app目录
// 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);

//  扫描/vendor/app目录
// Collect all vendor packages.
File vendorAppDir = new File("/vendor/app");
scanDirTracedLI(vendorAppDir, mDefParseFlags
    | PackageParser.PARSE_IS_SYSTEM
    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

//  扫描/oem目录
// Collect all OEM packages.
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir, mDefParseFlags
    | PackageParser.PARSE_IS_SYSTEM
    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

//  扫描/data/app目录
mAppInstallDir = new File(dataDir, "app");
scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);

//  扫描/system/priv-app目录
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
        | PackageParser.PARSE_FORWARD_LOCK,
        scanFlags | SCAN_REQUIRE_KNOWN, 0);
        

scanDirTracedLI函数调用流程非常复杂,ParallelPackageParser涉及线程池相关,
PackageParser对AndroidManifest.xml中的四大组件,权限等各种标签解析,Settings存储一些解析后的数据,
scanDirTracedLI时序图(对pkg的解析分为parseClusterPackage和parseMonolithicPackage,如果一个apk文件包含多个子apk
,则使用parseClusterPackage,否则使用parseMonolithicPackage)scanDirTracedLI时序图如下:
PackageManagerService简要分析

4 提供查询四大组件等服务
PackageManager 常用API
getPackageInfo
getPackageGids
getPermissionInfo
getApplicationInfo

getActivityInfo
getReceiverInfo
getServiceInfo
getProviderInfo
getInstalledPackages

resolveActivity
resolveService
resolveContentProvider

queryIntentActivities
queryBroadcastReceivers
queryIntentServices
queryIntentContentProviders
5 APP安装与卸载

APP的安装和卸载
1 可以通过发送Intent
2 pm install/uninstall
3 adb install
4 ApplicationPackageManager安装
apk的安装最终都需要通过PackageManagerService来安装
apk的安装卸载时序图如下
PackageManagerService简要分析
PackageManagerService好的博客
推荐1
推荐2
推荐3

相关标签: framework