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时序图如下:
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
上一篇: Binder系列1—Binder Driver初探
下一篇: 连接管理
推荐阅读
-
PackageManagerService简要分析
-
AD/DA模块使用说明及原理分析
-
DA14580 启动过程分析
-
Android运行时ART简要介绍和学习计划
-
Spark1.4.0-SparkSQL与Hive整合-支持窗口分析函数 博客分类: hiveSpark sparkSQL与Hive整合
-
Spark架构原理-Checkpoint原理剖析和源码分析
-
【赵强老师】Redis案例分析:用setbit统计活跃用户 博客分类: Redis nosqlredissqlmysql数据库
-
深度学习PyTorch,TensorFlow中GPU利用率较低,CPU利用率很低,且模型训练速度很慢的问题总结与分析
-
如何手写一个深度学习框架、对比tensorflow分析
-
学习Hadoop权威指南之MapReducer气象数据分析 博客分类: hadoop hadoopMapReduce