PackageManagerService简要分析

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时序图如下:
在这里插入图片描述

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好的博客
推荐1
推荐2
推荐3

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值