
Android应用安装过程
Android应用安装是系统核心流程之一,涉及Framework层的逻辑调度、Binder跨进程通信、C++层的底层文件操作与系统调用,贯穿了应用包解析、权限校验、Dex优化、目录创建等关键环节。
本文将从用户触发安装 到系统完成部署的全链路,结合Framework(Java)和Native(C++)层源码,拆解Android 11(API 30)的应用安装核心流程。
整体流程
Android应用安装可分为触发阶段、Framework层处理阶段、Native层执行阶段、收尾阶段四大环节,核心参与者包括:
- Framework层:PackageManagerService(PMS)、PackageInstaller、PackageParser、Installer(Java层代理);
- Native层:installd守护进程(C++)、dex2oat工具(Dex优化)、bionic库(系统调用);
- 其他组件:Binder驱动(跨进程通信)、SELinux(权限管控)、PackageManager(应用层接口)。
整体流程链路:
应用层触发安装(如PM命令/应用市场)→ PackageInstaller(Framework)→ PMS核心处理 → Installer(Java)→ Binder调用installd(C++)→ 底层文件操作 → PMS更新包信息 → 完成安装
阶段1:安装触发与Framework层入口
应用安装的触发方式包括:pm install命令、应用市场下载安装、ADB安装、系统预置应用安装等,所有触发方式最终都会走到PMS的installPackage系列接口。
1 入口:PackageInstaller的安装请求
以应用市场安装为例,应用层通过PackageInstaller.Session提交安装请求,核心源码如下(Framework层):
java
// PackageInstaller.java(frameworks/base/core/java/android/content/pm/PackageInstaller.java)
public Session openSession(long sessionId) throws IOException {
// 获取PMS的Binder代理,发起跨进程请求
IPackageInstaller session = mService.openSession(sessionId);
return new Session(this, session, sessionId);
}
// Session.java(内部类)
public void commit(IntentSender statusReceiver) throws IOException {
try {
// 提交安装请求,最终调用PMS的installStage方法
mSession.commit(statusReceiver);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
核心逻辑 :应用层通过PackageInstaller封装安装参数(APK路径、安装标志、用户ID),通过Binder跨进程调用PMS的安装接口,完成安装请求的传递。
2 PMS接收请求:installStage方法
PMS是安装流程的"总调度中心",installStage方法接收安装请求后,先做前置校验,再启动安装流程:
java
// PackageManagerService.java
void installStage(PackageInstallArgs args, PackageInstalledInfo res) {
// 1. 权限校验:检查调用方是否有INSTALL_PACKAGES权限(系统应用/签名校验)
if (!checkInstallPermission(args.installerUid, args.packageName)) {
res.setError(PackageManager.INSTALL_FAILED_PERMISSION_DENIED);
finishInstall(args, res);
return;
}
// 2. 解析APK包:调用PackageParser解析AndroidManifest.xml
PackageParser.Package pkg = parsePackage(args.apkPath, parseFlags);
// 3. 校验APK合法性:签名、版本、包名冲突、SELinux规则
if (!verifyPackageSignature(pkg, args)) {
res.setError(PackageManager.INSTALL_FAILED_INVALID_SIGNATURE);
finishInstall(args, res);
return;
}
// 4. 启动异步安装流程(避免阻塞PMS主线程)
mHandler.post(() -> processInstallRequest(args, pkg, res));
}
关键动作:
- 权限校验:仅系统应用(如应用市场、Settings)或拥有
INSTALL_PACKAGES权限的应用可触发安装; - 包解析:
PackageParser解析APK中的AndroidManifest.xml,提取包名、版本、组件(Activity/Service)、权限声明等信息; - 签名校验:校验APK签名是否合法(系统应用需匹配系统签名,第三方应用需通过证书校验)。
阶段2:Framework层核心处理(Java)
PMS的processInstallRequest方法是Framework层安装逻辑的核心,负责协调目录创建、Dex优化、权限分配等环节,核心依赖Installer(Java层)与Native层的installd通信。
1 Installer(Java):与installd的通信代理
Installer是Framework层与Native层installd守护进程通信的桥梁,封装了Binder调用逻辑,核心源码如下:
java
// Installer.java(frameworks/base/services/core/java/com/android/server/pm/Installer.java)
public class Installer {
private final IBinder mInstalld; // 指向installd的Binder代理
// 初始化:连接installd守护进程
public Installer() {
mInstalld = ServiceManager.getService("installd");
if (mInstalld == null) {
throw new RuntimeException("Failed to connect to installd");
}
}
// 创建应用数据目录(调用installd的create_data_dir方法)
public int createDataDir(String pkgName, int uid, int gid) {
try {
// Binder调用installd的create_data_dir接口
return ((IInstalld) mInstalld).createDataDir(pkgName, uid, gid);
} catch (RemoteException e) {
return -1;
}
}
// Dex优化(调用installd的dexopt方法)
public int dexopt(String apkPath, String pkgName, int uid, String instructionSet) {
try {
return ((IInstalld) mInstalld).dexopt(apkPath, pkgName, uid, instructionSet);
} catch (RemoteException e) {
return -1;
}
}
}
核心作用 :将Framework层的安装指令(如创建目录、Dex优化)通过Binder传递给Native层的installd,由installd执行底层操作。
2 核心步骤:创建应用目录与Dex优化
PMS通过Installer调用Native层接口,完成应用安装的核心操作:
java
// PackageManagerService.java - processInstallRequest方法
private void processInstallRequest(PackageInstallArgs args, PackageParser.Package pkg, PackageInstalledInfo res) {
// 1. 分配UID/GID:每个应用对应唯一的UID(10000+),GID与UID一致
int uid = assignNewUid(pkg.packageName);
// 2. 创建应用目录:调用Installer的createDataDir方法
int createResult = mInstaller.createDataDir(pkg.packageName, uid, uid);
if (createResult != 0) {
res.setError(PackageManager.INSTALL_FAILED_CREATE_DIR);
finishInstall(args, res);
return;
}
// 3. Dex优化:将APK中的dex文件优化为oat文件(提升运行效率)
int dexoptResult = mInstaller.dexopt(
args.apkPath, pkg.packageName, uid, Build.SUPPORTED_ABIS[0]
);
if (dexoptResult != 0) {
res.setError(PackageManager.INSTALL_FAILED_DEXOPT);
finishInstall(args, res);
return;
}
// 4. 分配权限:为应用授予声明的权限(系统权限需校验,普通权限直接授予)
grantPermissions(pkg, uid);
// 5. 更新PMS内存数据库:将新安装的应用信息加入mPackages
addPackageToInternalMap(pkg, uid);
// 6. 持久化包信息:写入/packages.xml和/packages.list
writePackageInfoToDisk(pkg);
// 7. 完成安装:通知Launcher更新图标、发送安装完成广播
finishInstall(args, res);
}
关键说明:
- UID分配:Android通过UID隔离应用进程,每个第三方应用分配唯一UID,系统应用使用固定UID(如1000);
- Dex优化:
dexopt调用dex2oat工具,将Dex文件编译为机器码(OAT文件),避免应用运行时实时编译,提升启动速度; - 持久化:
packages.xml存储应用的包信息、权限、签名,packages.list存储包名与UID的映射,下次系统启动时PMS直接加载这些文件。
阶段3:Native层核心执行(C++)
Framework层的所有底层操作最终由installd守护进程(C++实现)执行,installd是Android系统启动时由init进程拉起的核心守护进程,负责应用安装/卸载的底层文件操作。
1 installd的启动与Binder服务注册
installd的入口在system/core/installd/installd.cpp,启动时注册Binder服务,核心源码:
cpp
// installd.cpp
int main() {
// 1. 初始化日志、SELinux
android::base::InitLogging(nullptr, android::base::LogdLogger());
selinux_initialize();
// 2. 创建Binder服务端,注册到ServiceManager(服务名:installd)
sp<IServiceManager> sm = defaultServiceManager();
sp<InstalldNativeService> service = new InstalldNativeService();
status_t ret = sm->addService(String16("installd"), service, false);
if (ret != OK) {
ALOGE("Failed to register installd service");
return 1;
}
// 3. 启动Binder循环,等待Framework层调用
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
核心逻辑 :installd启动后注册为Binder服务,Framework层的Installer(Java)通过ServiceManager获取其代理,实现跨进程调用。
2 InstalldNativeService:底层操作的实现
InstalldNativeService是installd的核心实现类,封装了创建目录、Dex优化、文件权限修改等操作,核心源码如下:
cpp
// InstalldNativeService.cpp
status_t InstalldNativeService::createDataDir(const std::string& pkgname, int uid, int gid) {
// 1. 构造应用数据目录路径:/data/data/<pkgname>
std::string dataDir = StringPrintf("/data/data/%s", pkgname.c_str());
// 2. 创建目录,设置权限(751),所有者为uid:gid
if (mkdir(dataDir.c_str(), 0751) != 0 && errno != EEXIST) {
ALOGE("mkdir failed for %s: %s", dataDir.c_str(), strerror(errno));
return -1;
}
// 3. 设置目录的UID/GID(chown)
if (chown(dataDir.c_str(), uid, gid) != 0) {
ALOGE("chown failed for %s: %s", dataDir.c_str(), strerror(errno));
return -1;
}
// 4. 设置SELinux上下文(确保目录符合SELinux规则)
if (selinux_restorecon(dataDir.c_str()) != 0) {
ALOGE("restorecon failed for %s: %s", dataDir.c_str(), strerror(errno));
return -1;
}
return 0;
}
status_t InstalldNativeService::dexopt(const std::string& apk_path, const std::string& pkgname,
int uid, const std::string& isa) {
// 构造dex2oat命令:/system/bin/dex2oat --apk <apk_path> --output <oat_path>
std::vector<std::string> args;
args.push_back("/system/bin/dex2oat");
args.push_back("--apk");
args.push_back(apk_path);
args.push_back("--output");
args.push_back(StringPrintf("/data/dalvik-cache/%s@%s.oat", pkgname.c_str(), isa.c_str()));
args.push_back("--instruction-set");
args.push_back(isa);
// 执行dex2oat命令(fork+exec)
int result = execute(args, uid);
return result == 0 ? OK : -1;
}
核心操作解析:
createDataDir:创建应用私有数据目录/data/data/<包名>,设置权限为751(仅应用自身可读写,其他进程可执行),并通过chown设置目录所有者为应用UID;dexopt:拼接dex2oat命令,通过fork+exec执行,将APK中的Dex文件编译为OAT文件(存储在/data/dalvik-cache);- SELinux管控:
selinux_restorecon设置目录的SELinux上下文(如u:object_r:app_data_file:s0:c123,c456),确保应用只能访问自身目录。
3 底层系统调用
installd的所有操作最终依赖Linux系统调用,如:
mkdir:创建目录;chown/chmod:修改文件/目录的所有者和权限;fork/exec:执行dex2oat等外部工具;unlink:删除文件(卸载时);mount:挂载APK(针对应用分身/多用户场景)。
以createDataDir中的mkdir为例,底层调用链:
cpp
// bionic/libc/unistd/mkdir.cpp
int mkdir(const char* path, mode_t mode) {
// 调用Linux系统调用sys_mkdir
return syscall(__NR_mkdirat, AT_FDCWD, path, mode);
}
阶段4:安装收尾与系统通知
当Native层完成所有底层操作后,Framework层的PMS会完成收尾工作,确保应用可被系统识别和启动:
1 更新内存数据库与持久化
PMS将新安装的应用信息加入mPackages(内存中的包信息映射表),并写入/data/system/packages.xml和/data/system/packages.list:
xml
<!-- packages.xml示例 -->
<package name="com.example.app" codePath="/data/app/com.example.app-1" uid="10123">
<version code="1" name="1.0"/>
<permissions>
<permission name="android.permission.INTERNET" granted="true"/>
</permissions>
<signature>...</signature>
</package>
2 发送安装完成广播
PMS发送Intent.ACTION_PACKAGE_ADDED广播,通知系统组件(如Launcher、Settings)应用已安装:
java
// PackageManagerService.java - finishInstall方法
private void finishInstall(PackageInstallArgs args, PackageInstalledInfo res) {
// 发送广播
Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED);
intent.setData(Uri.parse("package:" + args.packageName));
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
// 通知Launcher更新应用图标
notifyPackageChanged(args.packageName);
}
3 应用启动准备
Launcher接收到广播后,解析应用的AndroidManifest.xml中的图标和名称,添加到桌面;同时,PMS为应用的组件(Activity/Service)注册到AMS,确保应用可被启动。
关键异常场景与容错机制
Android在安装流程中设计了多层容错机制,避免因单点失败导致安装异常:
- 目录创建失败 :若
createDataDir失败(如磁盘满、权限不足),PMS会回滚已创建的目录,返回INSTALL_FAILED_CREATE_DIR; - Dex优化失败 :若
dexopt失败(如APK损坏、指令集不兼容),PMS会删除已创建的目录,返回INSTALL_FAILED_DEXOPT; - 签名校验失败 :若APK签名不合法,直接终止安装,返回
INSTALL_FAILED_INVALID_SIGNATURE; - 包名冲突 :若已存在同名应用且未指定覆盖安装,返回
INSTALL_FAILED_ALREADY_EXISTS。
总结
Android应用安装流程体现了分层、解耦、安全的核心设计原则:
- 分层设计:Framework层负责逻辑调度(校验、权限、通知),Native层负责底层操作(文件、编译),通过Binder实现跨层通信;
- 解耦思想 :PMS不直接执行底层文件操作,而是通过
Installer代理调用installd,降低模块耦合; - 安全管控:多层校验(权限、签名、SELinux)确保只有合法应用能被安装,UID隔离确保应用数据安全;
- 性能优化:Dex预编译(dex2oat)避免运行时编译,提升应用启动速度;异步安装避免阻塞PMS主线程。
