From 2c5542037b27989c8f72620702d86a1360788d78 Mon Sep 17 00:00:00 2001 From: renjianbo <18691577328@163.com> Date: Fri, 16 Jan 2026 17:23:12 +0800 Subject: [PATCH] =?UTF-8?q?=E9=8F=87=E5=AD=98=E6=9F=8A=E9=8F=82=E5=9B=A8?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .obsidian/workspace.json | 2 +- docs/android面试/系统原理/PMS常见面试题.md | 710 +++++++++++++++++++++ mkdocs.yml | 3 +- 3 files changed, 713 insertions(+), 2 deletions(-) create mode 100644 docs/android面试/系统原理/PMS常见面试题.md diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index e8e243e..0041d58 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -200,6 +200,7 @@ }, "active": "25c9f7051aac05b3", "lastOpenFiles": [ + "docs/android面试/系统原理/PMS常见面试题.md", "docs/android面试/系统原理/DPMS常见面试题.md", "docs/android面试/系统原理/DPMS常见面试题", "docs/DPMS常见面试题", @@ -229,7 +230,6 @@ "docs/Google开发文档体系/核心主题/后台任务.md", "docs/Google开发文档体系/核心主题/Material_Design.md", "docs/Google开发文档体系/核心主题/Jetpack组件.md", - "docs/Google开发文档体系/示例代码/架构示例.md", "docs/Google开发文档体系/视频和教程", "docs/Google开发文档体系/核心主题", "docs/Google开发文档体系/示例代码", diff --git a/docs/android面试/系统原理/PMS常见面试题.md b/docs/android面试/系统原理/PMS常见面试题.md new file mode 100644 index 0000000..d5c7b97 --- /dev/null +++ b/docs/android面试/系统原理/PMS常见面试题.md @@ -0,0 +1,710 @@ +# PMS常见面试题 + +--- + +## 一、PMS基础概念 + +### Q1: 什么是PMS?它的作用是什么? + +**A:** PMS(PackageManagerService)是Android系统的核心服务之一,运行在system_server进程中。 + +**主要作用:** + +1. **应用安装管理**:管理应用的安装、卸载、更新 +2. **权限管理**:管理应用权限的授予、撤销和检查 +3. **组件管理**:管理Activity、Service、BroadcastReceiver、ContentProvider等组件信息 +4. **包扫描**:扫描系统和应用目录中的APK文件 +5. **签名验证**:验证APK的签名信息,确保应用安全性 +6. **多用户管理**:支持多用户环境下的应用隔离和管理 + +### Q2: PMS在系统启动流程中的位置? + +**A:** PMS在系统启动流程中的位置: + +1. **Bootloader阶段**:加载Linux内核 +2. **Kernel启动**:初始化硬件,启动init进程 +3. **Init进程**:解析init.rc,启动Zygote和ServiceManager +4. **Zygote进程**:预加载类和资源,fork出SystemServer进程 +5. **SystemServer进程**:启动各类系统服务 + - 启动PMS(PackageManagerService) + - 启动AMS(ActivityManagerService) + - 启动WMS(WindowManagerService) + - 启动其他系统服务 +6. **PMS扫描应用**:系统启动时,PMS扫描系统目录和应用目录中的APK文件 + +### Q3: PMS与其他系统服务的关系? + +**A:** PMS与其他系统服务的关系: + +1. **PMS与AMS**:AMS需要PMS提供包信息来启动Activity +2. **PMS与Installer**:PMS通过Installer执行实际的APK安装操作 +3. **PMS与UserManagerService**:PMS需要UserManagerService管理多用户 +4. **PMS与StorageManagerService**:PMS需要StorageManagerService管理存储空间 + +--- + +## 二、应用安装流程 + +### Q4: 请详细描述应用的安装流程? + +**A:** 应用安装流程: + +**客户端进程:** +1. `PackageInstaller.install()`:用户点击安装或调用安装API +2. `PackageInstaller.Session.commit()`:提交安装会话 +3. `PackageInstaller.Session.commit()`:通过Binder调用PMS + +**服务端进程(system_server):** +4. `PackageManagerService.installPackageAsUser()`:PMS接收安装请求 +5. `PackageManagerService.createInstallSession()`:创建安装会话 +6. `PackageManagerService.writeApkToSession()`:写入APK文件到临时目录 +7. `PackageManagerService.commitSession()`:提交安装会话 +8. `PackageManagerService.installPackageTracedLI()`:执行安装 +9. `PackageParser.parsePackage()`:解析APK文件 + - 解析AndroidManifest.xml + - 提取四大组件信息 + - 提取权限信息 + - 验证签名 +10. `PackageManagerService.scanPackageTracedLI()`:扫描包信息 +11. `PackageManagerService.updateSettingsLI()`:更新包设置 +12. `PackageManagerService.sendPackageBroadcast()`:发送安装完成广播 + +**关键步骤:** +- 权限检查:检查安装权限 +- APK解析:解析APK的AndroidManifest.xml +- 签名验证:验证APK签名 +- 冲突检查:检查包名冲突、版本冲突 +- 存储检查:检查存储空间是否足够 +- 安装执行:复制APK文件、创建数据目录 +- 组件注册:注册Activity、Service等组件 +- 权限授予:授予声明的权限 + +### Q5: APK解析过程是怎样的? + +**A:** APK解析过程: + +1. **创建PackageParser** + ```java + PackageParser parser = new PackageParser(); + ``` + +2. **解析APK文件** + ```java + PackageParser.Package pkg = parser.parsePackage(apkFile, flags); + ``` + +3. **解析AndroidManifest.xml** + - 解析包名、版本号等基本信息 + - 解析四大组件(Activity、Service、BroadcastReceiver、ContentProvider) + - 解析权限声明 + - 解析Intent Filter + - 解析资源信息 + +4. **收集证书信息** + ```java + collectCertificates(pkg); + collectManifestDigest(pkg); + ``` + +5. **提取组件信息** + ```java + extractActivities(pkg); + extractServices(pkg); + extractReceivers(pkg); + extractProviders(pkg); + extractPermissions(pkg); + ``` + +6. **验证签名** + - 验证APK签名是否有效 + - 检查签名是否匹配 + - 验证签名证书链 + +### Q6: 签名验证是如何进行的? + +**A:** 签名验证过程: + +1. **提取签名信息** + ```java + // 从APK中提取签名 + Signature[] signatures = packageInfo.signatures; + ``` + +2. **验证签名格式** + - 检查签名文件是否存在(META-INF/) + - 验证签名文件格式是否正确 + +3. **验证签名证书** + - 验证证书是否有效 + - 验证证书是否过期 + - 验证证书链是否完整 + +4. **验证签名匹配** + - 如果是更新安装,验证新签名是否与旧签名匹配 + - 如果是共享UID应用,验证签名是否一致 + +5. **关键代码位置** + - `PackageManagerService.verifySignatures()` + - `PackageParser.collectCertificates()` + - `PackageManagerService.checkUpgradeKeySetLocked()` + +--- + +## 三、应用卸载流程 + +### Q7: 应用卸载流程是怎样的? + +**A:** 应用卸载流程: + +1. **卸载请求** + ```java + packageManager.deletePackage(packageName, observer, flags); + ``` + +2. **PMS处理卸载** + ```java + PackageManagerService.deletePackageAsUser(packageName, userId, flags); + ``` + +3. **检查卸载条件** + - 检查应用是否正在运行 + - 检查是否有其他应用依赖 + - 检查卸载权限 + +4. **停止应用** + - 停止应用的所有Activity + - 停止应用的所有Service + - 取消注册BroadcastReceiver + +5. **删除文件** + - 删除APK文件 + - 删除应用数据目录 + - 删除应用缓存 + +6. **更新包信息** + - 从包列表中移除 + - 清理组件注册信息 + - 清理权限信息 + +7. **发送卸载广播** + ```java + sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, packageName); + ``` + +### Q8: 卸载时如何清理应用数据? + +**A:** 卸载时清理应用数据: + +1. **删除应用目录** + ```java + // 删除应用数据目录 + /data/data// + /data/user/// + ``` + +2. **删除APK文件** + ```java + // 删除APK文件 + /data/app/-/ + ``` + +3. **删除外部存储数据** + ```java + // 删除外部存储中的应用数据 + /sdcard/Android/data// + ``` + +4. **清理数据库** + - 清理包信息数据库 + - 清理权限数据库 + - 清理组件注册信息 + +5. **清理缓存** + - 清理系统缓存中的应用信息 + - 清理其他服务中的应用引用 + +--- + +## 四、权限管理 + +### Q9: PMS如何管理应用权限? + +**A:** PMS权限管理机制: + +1. **权限声明** + - 应用在AndroidManifest.xml中声明权限 + - PMS解析时提取权限信息 + +2. **权限授予** + ```java + // 授予权限 + packageManager.grantRuntimePermission(packageName, permission, userHandle); + ``` + +3. **权限检查** + ```java + // 检查权限 + int result = packageManager.checkPermission(permission, packageName); + if (result == PackageManager.PERMISSION_GRANTED) { + // 权限已授予 + } + ``` + +4. **权限撤销** + ```java + // 撤销权限 + packageManager.revokeRuntimePermission(packageName, permission, userHandle); + ``` + +5. **权限存储** + - 权限授予状态存储在`/data/system/users//runtime-permissions.xml` + - 系统启动时加载权限状态 + +### Q10: 运行时权限和安装时权限的区别? + +**A:** 运行时权限和安装时权限的区别: + +**安装时权限(Normal Permissions):** +- 在应用安装时自动授予 +- 不需要用户确认 +- 通常是低风险权限 +- 例如:网络访问、振动等 + +**运行时权限(Dangerous Permissions):** +- 需要运行时动态申请 +- 需要用户确认 +- 通常是高风险权限 +- 例如:相机、位置、存储等 + +**权限分类:** +```java +// 权限保护级别 +PROTECTION_NORMAL // 普通权限,安装时授予 +PROTECTION_DANGEROUS // 危险权限,运行时申请 +PROTECTION_SIGNATURE // 签名权限,同签名应用自动授予 +PROTECTION_SIGNATURE_OR_SYSTEM // 签名或系统权限 +``` + +--- + +## 五、包扫描机制 + +### Q11: PMS如何扫描应用? + +**A:** PMS包扫描机制: + +1. **系统目录扫描** + - `/system/app/`:系统应用目录 + - `/system/priv-app/`:系统特权应用目录 + - `/vendor/app/`:厂商应用目录 + - `/oem/app/`:OEM应用目录 + +2. **用户目录扫描** + - `/data/app/`:用户安装的应用目录 + - `/data/app-private/`:私有应用目录 + +3. **扫描流程** + ```java + // PMS扫描流程 + void scanDirTracedLI(File scanDir, int parseFlags, int scanFlags) { + // 1. 遍历目录中的APK文件 + File[] files = scanDir.listFiles(); + + // 2. 解析每个APK + for (File file : files) { + PackageParser.Package pkg = parsePackage(file, parseFlags); + + // 3. 扫描包信息 + scanPackageTracedLI(pkg, parseFlags, scanFlags); + } + } + ``` + +4. **增量扫描** + - 只扫描新增或修改的APK + - 使用文件时间戳判断是否需要重新扫描 + - 优化启动速度 + +### Q12: 系统启动时PMS如何扫描应用? + +**A:** 系统启动时PMS扫描流程: + +1. **扫描系统应用** + ```java + // 扫描系统目录 + scanDirTracedLI(new File("/system/app"), ...); + scanDirTracedLI(new File("/system/priv-app"), ...); + scanDirTracedLI(new File("/vendor/app"), ...); + ``` + +2. **扫描用户应用** + ```java + // 扫描用户安装目录 + scanDirTracedLI(new File("/data/app"), ...); + ``` + +3. **并行扫描优化** + - 使用多线程并行扫描不同目录 + - 提高扫描速度 + +4. **延迟扫描** + - 非关键目录延迟扫描 + - 优先扫描系统应用 + - 用户应用可以延迟扫描 + +--- + +## 六、多用户管理 + +### Q13: PMS如何支持多用户? + +**A:** PMS多用户支持: + +1. **用户包状态管理** + ```java + // 每个用户有独立的包状态 + final SparseArray mSettingsByUser = new SparseArray<>(); + ``` + +2. **用户数据目录** + - 主用户:`/data/data//` + - 其他用户:`/data/user///` + +3. **用户包安装** + ```java + // 为用户安装包 + installPackageAsUser(packageName, userId); + ``` + +4. **用户包卸载** + ```java + // 删除用户包 + removePackageAsUser(packageName, userId); + ``` + +5. **用户权限管理** + - 每个用户有独立的权限授予状态 + - 权限存储在`/data/system/users//runtime-permissions.xml` + +### Q14: 多用户下应用数据如何隔离? + +**A:** 多用户数据隔离机制: + +1. **数据目录隔离** + ```java + // 主用户(user_id = 0) + /data/data// + + // 其他用户 + /data/user/// + ``` + +2. **包状态隔离** + - 每个用户有独立的PackageSetting + - 包启用/禁用状态独立管理 + +3. **权限隔离** + - 每个用户有独立的权限授予状态 + - 权限授予不影响其他用户 + +4. **组件隔离** + - Activity、Service等组件按用户隔离 + - 不同用户看到不同的应用列表 + +--- + +## 七、组件管理 + +### Q15: PMS如何管理Activity组件? + +**A:** PMS管理Activity组件: + +1. **组件注册** + ```java + // 解析AndroidManifest.xml时注册Activity + extractActivities(package); + ``` + +2. **组件查询** + ```java + // 查询Activity + ResolveInfo resolveInfo = packageManager.resolveActivity(intent, flags); + List activities = packageManager.queryIntentActivities(intent, flags); + ``` + +3. **组件信息存储** + - Activity信息存储在PackageParser.Package中 + - Intent Filter信息用于匹配Activity + +4. **组件启用/禁用** + ```java + // 启用/禁用组件 + packageManager.setComponentEnabledSetting(componentName, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP); + ``` + +### Q16: Intent匹配是如何工作的? + +**A:** Intent匹配机制: + +1. **Intent Filter解析** + - PMS解析AndroidManifest.xml中的Intent Filter + - 提取action、category、data等信息 + +2. **Intent匹配** + ```java + // Intent匹配 + List resolveInfos = packageManager.queryIntentActivities(intent, flags); + ``` + +3. **匹配规则** + - Action匹配:Intent的action必须在Intent Filter中声明 + - Category匹配:Intent的所有category都必须在Intent Filter中 + - Data匹配:Intent的data必须匹配Intent Filter的data规则 + +4. **匹配优先级** + - 精确匹配优先 + - 系统应用优先 + - 按优先级排序 + +--- + +## 八、PMS源码分析 + +### Q17: PMS的关键类有哪些? + +**A:** PMS的关键类: + +1. **PackageManagerService** + - PMS的主类,系统服务的实现 + - 管理所有包的安装、卸载、更新 + +2. **PackageParser** + - 解析APK文件 + - 提取包信息和组件信息 + +3. **PackageSettings** + - 存储包的安装信息和设置 + - 管理包的启用/禁用状态 + +4. **Installer** + - 执行实际的APK安装操作 + - 管理APK文件的复制和删除 + +5. **PackageInstaller** + - 应用层使用的安装接口 + - 管理安装会话 + +### Q18: PMS的关键方法有哪些? + +**A:** PMS的关键方法: + +**安装相关:** +- `installPackageAsUser()`:安装应用 +- `installPackageTracedLI()`:执行安装 +- `scanPackageTracedLI()`:扫描包信息 + +**卸载相关:** +- `deletePackageAsUser()`:卸载应用 +- `removePackage()`:移除包 + +**权限相关:** +- `grantRuntimePermission()`:授予权限 +- `revokeRuntimePermission()`:撤销权限 +- `checkPermission()`:检查权限 + +**查询相关:** +- `getPackageInfo()`:获取包信息 +- `getApplicationInfo()`:获取应用信息 +- `queryIntentActivities()`:查询Activity +- `resolveActivity()`:解析Activity + +--- + +## 九、性能优化 + +### Q19: 如何优化PMS的启动速度? + +**A:** PMS启动速度优化: + +1. **延迟扫描** + - 非关键目录延迟扫描 + - 优先扫描系统应用 + - 用户应用可以延迟扫描 + +2. **并行扫描** + - 使用多线程并行扫描不同目录 + - 提高扫描速度 + +3. **增量扫描** + - 只扫描新增或修改的APK + - 使用文件时间戳判断 + +4. **缓存机制** + - 缓存已解析的包信息 + - 减少重复解析 + +5. **优化解析** + - 优化PackageParser解析速度 + - 减少不必要的解析操作 + +### Q20: 如何优化应用安装速度? + +**A:** 应用安装速度优化: + +1. **优化APK解析** + - 只解析必要的信息 + - 延迟解析非关键信息 + +2. **优化文件操作** + - 使用异步IO + - 批量操作减少IO次数 + +3. **优化签名验证** + - 缓存签名信息 + - 优化签名验证算法 + +4. **优化数据库操作** + - 批量更新数据库 + - 使用事务减少数据库操作 + +--- + +## 十、问题排查 + +### Q21: 如何排查应用安装失败的问题? + +**A:** 应用安装失败排查: + +1. **查看日志** + ```bash + adb logcat | grep -i "package" + adb logcat | grep -i "install" + ``` + +2. **检查包信息** + ```bash + adb shell dumpsys package + ``` + +3. **检查安装会话** + ```bash + adb shell dumpsys package sessions + ``` + +4. **常见原因** + - 签名验证失败 + - 存储空间不足 + - 包名冲突 + - 版本冲突 + - 权限不足 + +### Q22: 如何排查权限问题? + +**A:** 权限问题排查: + +1. **查看权限状态** + ```bash + adb shell dumpsys package permissions + ``` + +2. **查看应用权限** + ```bash + adb shell dumpsys package | grep -i permission + ``` + +3. **检查权限授予状态** + ```java + int result = packageManager.checkPermission(permission, packageName); + ``` + +4. **常见问题** + - 权限未声明 + - 权限未授予 + - 权限被撤销 + - 权限保护级别不匹配 + +--- + +## 十一、高级问题 + +### Q23: 静默安装是如何实现的? + +**A:** 静默安装实现: + +1. **系统权限要求** + - 需要系统签名 + - 需要INSTALL_PACKAGES权限 + +2. **使用PackageInstaller** + ```java + PackageInstaller.Session session = packageInstaller.openSession(sessionId); + session.write("app.apk", 0, -1, inputStream); + session.commit(createIntentSender()); + ``` + +3. **直接调用PMS** + ```java + // 需要系统权限 + IPackageManager pm = ActivityManager.getService().getPackageManager(); + pm.installPackageAsUser(packageUri, observer, flags, installerPackageName, userId); + ``` + +4. **注意事项** + - 静默安装需要系统权限 + - 普通应用无法实现静默安装 + - 需要用户授权或系统签名 + +### Q24: 应用更新安装的流程? + +**A:** 应用更新安装流程: + +1. **版本检查** + - 检查新版本号是否大于旧版本 + - 检查签名是否匹配 + +2. **停止旧应用** + - 停止所有Activity + - 停止所有Service + - 取消注册BroadcastReceiver + +3. **备份数据** + - 备份应用数据 + - 备份SharedPreferences + +4. **安装新版本** + - 安装新APK + - 保留应用数据 + +5. **恢复数据** + - 恢复应用数据 + - 恢复SharedPreferences + +6. **启动新版本** + - 注册新组件 + - 发送更新广播 + +--- + +## 总结 + +PMS是Android系统的核心服务,负责管理应用的安装、卸载、权限管理等。 + +**关键知识点:** +1. PMS的职责和架构 +2. 应用安装流程(APK解析、签名验证、安装执行) +3. 应用卸载流程(停止应用、删除文件、清理数据) +4. 权限管理机制(权限声明、授予、检查、撤销) +5. 包扫描机制(系统目录扫描、用户目录扫描) +6. 多用户支持(数据隔离、权限隔离) +7. 组件管理(Activity、Service等组件注册和查询) +8. PMS源码关键类和方法 +9. 性能优化和问题排查 + +**面试重点:** +- 深入理解应用安装流程 +- 掌握APK解析和签名验证机制 +- 了解权限管理原理 +- 能够分析安装失败问题 +- 了解多用户支持机制 diff --git a/mkdocs.yml b/mkdocs.yml index c3f23b0..ad0d126 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -211,6 +211,7 @@ nav: - android面试/技术面试问题回答.md - android面试/系统原理/AMS面试.md - android面试/系统原理/WMS面试.md + - android面试/系统原理/DPMS常见面试题.md - android面试/README.md - android面试/基础知识/Android基础.md - android面试/基础知识/Android版本特性.md @@ -290,7 +291,7 @@ nav: - android面试/项目经验/技术选型.md - android面试/项目经验/问题排查经验.md - android面试/项目经验/项目架构设计.md - - android面试/系统原理/DPMS常见面试题.md + - android面试/系统原理/PMS常见面试题.md - Google开发文档体系: - Google开发文档体系/API参考/Android_API概览.md - Google开发文档体系/API参考/Jetpack_API.md