Android PMS(Package Manager Service)源码介绍
文章目录
- 前言
- 一、PMS 启动流程
- 二、APK 安装流程
- 三、APK 卸载流程
- 四、权限管理
- 静态权限
- 动态权限
- 五、 数据存储与一致性
- 六、 PMS 的安全性策略
- 1、权限检查
- 2、签名认证
- 3、动态权限管理
- 4、应用安装验证
- 5、保护系统目录
- 七、PMS 调试方法
- 总结
前言
PackageManagerService(简称 PMS)是 Android 系统中的核心服务之一,负责应用的安装、卸载、查询和权限管理等。它是 Android 应用生命周期管理和安全机制的基石。
主要职责:
1、应用安装与卸载
2、静态权限解析与动态权限授予
3、应用信息查询
4、系统应用的预加载
5、数据存储与一致性管理
提示:以下是本篇文章正文内容,下面案例可供参考
一、PMS 启动流程
PMS 在系统启动时由 SystemServer 启动。其核心流程如下:
1、SystemServer 初始化
在 SystemServer 的 startBootstrapServices 方法中,调用 PackageManagerService.main(),完成 PMS 的创建和初始化。
2、关键方法解析
PackageManagerService.main()
public static PackageManagerService main(Context context, Installer installer, boolean factoryTest) {PackageManagerService pms = new PackageManagerService(context, installer, factoryTest);ServiceManager.addService("package", pms);return pms;
}
这里完成了:
1、PMS 对象的实例化。
2、将 PMS 注册到 ServiceManager,供其他服务访问。
3、扫描已安装应用
调用 scanDirLI 方法扫描 /system/app、/data/app 等目录,加载所有已安装的应用包信息,并存储到内存和文件中(如 packages.xml)。
二、APK 安装流程
APK 的安装是 PMS 最重要的功能之一。从用户触发安装到系统完成更新的完整流程如下:
1、入口方法 应用安装请求通过 PackageInstaller 模块发起,最终调用 installPackageAsUser 方法。
public void installPackageAsUser(String originPath, InstallParams params, int userId) {mHandler.post(new InstallParams(originPath, params, userId));
}
此处将安装请求交给 InstallParams 处理。
2、核心处理逻辑在 InstallParams 的 handleStartCopy 方法中,执行以下步骤:
- 解析 APK 文件:通过 PackageParser 提取包名、版本等信息。
- 签名校验:调用 verifySignatures 确保 APK 签名合法。
- 写入系统记录:调用 mSettings.addPackage() 更新系统数据。
- 通知系统服务:更新系统组件(如 AMS)和广播安装完成事件
3、安装完成广播 APK 安装完成后,PMS 会通过 Intent.ACTION_PACKAGE_ADDED 广播通知其他组件。
三、APK 卸载流程
APK 卸载的主要流程类似于安装,但涉及的数据清理步骤更多:
1、卸载入口 卸载请求通过 deletePackageAsUser 方法发起,最终调用 deletePackageLI 方法。
2、核心处理逻辑
清理应用数据:删除 /data/app/ 目录中的文件。
移除系统记录:从 packages.xml 中删除相关记录。
广播通知:通过 Intent.ACTION_PACKAGE_REMOVED 通知系统组件和应用。
3、特殊情况 如果应用包含共享库或依赖的资源,PMS 会延迟清理,确保不会影响其他应用。
四、权限管理
权限分为静态权限和动态权限,PMS 通过解析 AndroidManifest.xml 和系统调用提供管理功能。
静态权限
解析过程
在应用安装时,PMS 调用 PackageParser 的 parsePackage 方法,解析应用的 AndroidManifest.xml 文件,提取 标签内容。
PermissionInfo permission = new PermissionInfo();
permission.name = parser.getName();
mPermissions.add(permission);
动态权限
授予与撤销
动态权限的管理主要通过 grantRuntimePermission 和 revokeRuntimePermission 方法实现。
public void grantRuntimePermission(String packageName, String permissionName, int userId) {enforcePermissionChecks(permissionName);mSettings.grantRuntimePermission(packageName, permissionName, userId);
}
实际场景
例如,在某些即时通讯应用中,用户拒绝麦克风权限会导致无法发送语音消息。
五、 数据存储与一致性
PMS 的数据存储主要通过以下文件完成:
1、packages.xml 存储应用的基本信息,如包名、路径、版本等。
<package name="com.example.app" codePath="/data/app/com.example.app-1/base.apk" />
2、runtime-permissions.xml 存储动态权限授予记录。
<permissions><permission name="android.permission.CAMERA" granted="true" />
</permissions>
3、一致性保障
锁机制:PMS 使用锁机制保护并发读写,确保数据一致性。
文件备份:在文件更新前,系统会先保存备份副本,确保异常恢复能力。
六、 PMS 的安全性策略
PMS 是 Android 安全机制的核心,以下几点尤为重要:
签名校验:通过验证应用签名确保来源可信。
SELinux 策略:限制 PMS 的文件访问权限,增强系统安全性。
权限隔离:动态权限机制确保用户对敏感操作的控制权。
源码介绍
1、权限检查
PMS 负责管理应用的权限,包括动态权限和安装时权限。
权限检查主要在 checkPermission() 和 checkUidPermission() 方法中完成。
源码位置:
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
@Override
public int checkPermission(String permName, int uid) {final int permission = mSettings.getPermissionLocked(permName, uid);return (permission == PERMISSION_GRANTED) ? PERMISSION_GRANTED : PERMISSION_DENIED;
}
2、签名认证
在应用安装或更新时,PMS 会通过 verifySignatures() 方法验证签名是否一致。
防止未授权的 APK 替换已安装的 APK。
源码位置:
frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
private void verifySignatures(PackageParser.Package pkg, PackageSetting ps)throws PackageManagerException {if (!compareSignatures(pkg.mSigningDetails.signatures, ps.signatures.mSignatures)) {throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,"Signature mismatch for " + pkg.packageName);}
}
3、动态权限管理
动态权限是通过运行时授予或拒绝的,主要涉及以下文件:
runtime-permissions.xml 用于存储动态权限的状态。
相关代码示例:
源码位置:
frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
public void grantRuntimePermission(String packageName, String permissionName, int userId) {// 检查权限是否属于动态权限enforceGrantRuntimePermission(packageName, permissionName, userId);// 更新权限的状态mPermissionManager.grantRuntimePermission(packageName, permissionName, userId);
}
4、应用安装验证
PMS 在应用安装时会调用 PackageInstaller 验证 APK 文件的完整性。
相关代码包括:
安装路径检查
签名校验
安全区域限制
源码位置:
frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
private void enforceSystemOrRoot(String message) {if (Binder.getCallingUid() != Process.SYSTEM_UID &&Binder.getCallingUid() != Process.ROOT_UID) {throw new SecurityException(message);}
}
5、保护系统目录
只有系统权限的应用才可以访问 /system/app、/system/priv-app 等系统目录。
安全性检查代码:
源码位置:
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
private boolean isPrivilegedApp(String packageName) {PackageSetting ps = mSettings.mPackages.get(packageName);return ps != null && ps.isPrivileged();
}
七、PMS 调试方法
开发或调试 PMS 时,可以使用以下方法:
1、日志调试
通过 adb logcat | grep PackageManager 查看安装、卸载日志。
2、源码定位
关注 PackageManagerService.java 文件,定位核心方法,如 installPackageAsUser 和 deletePackageLI。
3、文件检查
检查 /data/system/packages.xml 和 runtime-permissions.xml 文件内容,排查问题。
总结
PMS 是 Android 系统中连接应用、用户和系统的桥梁,其源码体现了安装、卸载、权限管理的高效性和安全性。通过深挖源码,理解其核心流程,可以帮助开发者更好地优化和调试应用。
相关文章:

Android PMS(Package Manager Service)源码介绍
文章目录 前言一、PMS 启动流程二、APK 安装流程三、APK 卸载流程四、权限管理静态权限动态权限 五、 数据存储与一致性六、 PMS 的安全性策略1、权限检查2、签名认证3、动态权限管理4、应用安装验证5、保护系统目录 七、PMS 调试方法总结 前言 PackageManagerService…...

运维面试整理总结
面试题可以参考:面试题总结 查看系统相关信息 查看系统登陆成功与失败记录 成功:last失败:lastb 查看二进制文件 hexdump查看进程端口或连接 netstat -nltp ss -nltp补充:pidof与lsof命令 pidof [进程名] #根据 进程名 查询进程id ls…...

图数据库 Cypher语言
图数据库 属性图 属性图(Property Graph)概述 属性图是一种广泛用于建模关系数据的图数据结构,它将**顶点(节点)和边(关系)**进行结构化存储,并为它们附加属性以提供丰富的语义信…...

阿里云oss转发上线-实现不出网钓鱼
本地实现阿里云oss转发上线,全部代码在文末,代码存在冗余 实战环境 被钓鱼机器不出网只可访问内部网络包含集团oss 实战思路 若将我们的shellcode文件上传到集团oss上仍无法上线,那么就利用oss做中转使用本地转发进行上线,先发送…...

Spring Boot 3.4.0 发行:革新与突破的里程碑
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
【网络安全】
黑客入侵 什么是黑客入侵? “黑客”是一个外来词,是英语单词hacker的中文音译。最初,“黑客”只是一个褒义词,指的是那些尽力挖掘计算机程序最大潜力的点脑精英,他们讨论软件黑客的技巧和态度,以及共享文化…...

在SQLyog中导入和导出数据库
导入 假如我要导入一个xxx.sql,我就先创建一个叫做xxx的数据库。 然后右键点击导入、执行SQL脚本 选择要导入的数据库文件的位置,点击执行即可 注意: 导入之后记得刷新一下导出 选择你要导出的数据库 右键选择:备份/导出、…...

RabbitMQ简单应用
概念 RabbitMQ 是一种流行的开源消息代理(Message Broker)软件,它实现了高级消息队列协议(AMQP - Advanced Message Queuing Protocol)。RabbitMQ 通过高效的消息传递机制,主要应用于分布式系统中解耦应用…...

使用LUKS对Linux磁盘进行加密
前言 本实验用于日常学习用,如需对存有重要数据的磁盘进行操作,请做好数据备份工作。 此实验只是使用LUKS工具的冰山一角,后续还会有更多功能等待探索。 LUKS(Linux Unified Key Setup)是Linux系统中用于磁盘加密的一…...

戴尔电脑安装centos7系统遇到的问题
1,找不到启动盘(Operation System Loader signature found in SecureBoot exclusion database(‘dbx’).All bootable devices failed secure Boot Verification) 关闭 Secure Boot(推荐): 进入 BIOS/UEFI…...

3.4.SynchronousMethodHandler组件之ResponseHandler
前言 feign发送完请求后, 拿到返回结果, 那么这个返回结果肯定是需要经过框架进一步处理然后再返回到调用者的, 其中ResponseHandler就是用来处理这个返回结果的, 这也是符合正常思维的处理方式, 例如springmvc部分在调用在controller端点前后都会增加扩展点。 从图中可以看得…...

Linux 下进程的状态
操作系统中常见进程状态 在操作系统中有六种常见进程状态: 新建状态: 进程正在被创建. 此时操作系统会为进程分配资源, 如: 内存空间等, 进行初始化就绪状态: 进程已经准备好运行了, 只需要等待被调度, 获取 CPU 资源就可以执行了, 操作系统中可能同时存在多个进程处于就绪状…...

【计算机网络】核心部分复习
目录 交换机 v.s. 路由器OSI七层更实用的TCP/IP四层TCPUDP 交换机 v.s. 路由器 交换机-MAC地址 链接设备和设备 路由器- IP地址 链接局域网和局域网 OSI七层 物理层:传输设备。原始电信号比特流。数据链路层:代表是交换机。物理地址寻址,交…...
Spring Boot开发实战:从入门到构建高效应用
Spring Boot 是 Java 开发者构建微服务、Web 应用和后端服务的首选框架之一。其凭借开箱即用的特性、大量的自动化配置和灵活的扩展性,极大简化了开发流程。本文将以实战为核心,从基础到高级,全面探讨 Spring Boot 的应用开发。 一、Spring B…...

pyshark安装使用,ubuntu:20.04
1.容器创建 命令 docker run -d --name pyshark -v D:\src:/root/share ubuntu:2004 /bin/bash -c "while true;do sleep 1000;done" 用于创建并启动一个新的 Docker 容器。 docker run -d --name pyshark -v D:\src:/root/share ubuntu:2004 /bin/bash -c "w…...

基本功能实现
目录 1、环境搭建 2、按键控制灯&电机 LED 电机 垂直按键(机械按键) 3、串口调试功能 4、定时器延时和定时器中断 5、振动强弱调节 6、万年历 7、五方向按键 1、原理及分析 2、程序设计 1、环境搭建 需求: 搭建一个STM32F411CEU6工程 分析: C / C 宏定义栏…...
《那个让服务器“跳舞”的bug》
在程序的世界里,bug 就像隐藏在暗处的小怪兽,时不时跳出来捣乱。而在我的职业生涯中,有一个bug让我至今难忘,它不仅让项目差点夭折,还让我熬了无数个通宵。这个故事发生在一个风和日丽的下午,我们正在开发一…...
Python 网络爬虫进阶:动态网页爬取与反爬机制应对
在上一篇文章中,我们学习了如何使用 Python 构建一个基本的网络爬虫。然而,在实际应用中,许多网站使用动态内容加载或实现反爬机制来阻止未经授权的抓取。因此,本篇文章将深入探讨以下进阶主题: 如何处理动态加载的网…...
创建可直接用 root 用户 ssh 登陆的 Docker 镜像
有时候我们在 Mac OS X 或 Windows 平台下需要开发以 Linux 为运行时的应用,IDE 或可直接使用 Docker 容器,或 SSH 远程连接。本地命令行下操作虽然可以用 docker exec 连接正在运行的容器,但 IDE 远程连接的话 SSH 总是一种较为通用的连接方…...
wordpress 中添加图片放大功能
功能描述 使用 Fancybox 实现图片放大和灯箱效果。自动为文章内容中的图片添加链接,使其支持 Fancybox。修改了 header.php 和 footer.php 以引入必要的 CSS 和 JS 文件。在 functions.php 中通过过滤器自动为图片添加 data-fancybox 属性。 最终代码 1. 修改 hea…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...