Android PMS 安装 APK 流程

流程图

源码基于 sdk-31(12.0/S)

安装器安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// InstallInstalling.java

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

if (savedInstanceState != null) {
mSessionId = savedInstanceState.getInt(SESSION_ID);
mInstallId = savedInstanceState.getInt(INSTALL_ID);

InstallEventReceiver.addObserver(this, mInstallId,
this::launchFinishBasedOnResult);
} else {
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
final Uri referrerUri = getIntent().
// ... 设置参数

mInstallId = InstallEventReceiver
.addObserver(this, EventResultPersister.GENERATE_NEW_ID,
this::launchFinishBasedOnResult);

mSessionId = getPackageManager().getPackageInstaller().createSession(params);
}

}

/**
* Send the package to the package installer and then register a event result observer that
* will call {@link #launchFinishBasedOnResult(int, int, String)}
*/
private final class InstallingAsyncTask extends AsyncTask<Void, Void, PackageInstaller.Session> {

@Override
protected PackageInstaller.Session doInBackground(Void... params) {
PackageInstaller.Session session = getPackageManager().getPackageInstaller().openSession(mSessionId);
session.setStagingProgress(0);
return session;
}

@Override
protected void onPostExecute(PackageInstaller.Session session) {
if (session != null) {
Intent broadcastIntent = new Intent(BROADCAST_ACTION);
broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
broadcastIntent.setPackage(getPackageName());
broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);

PendingIntent pendingIntent = PendingIntent.getBroadcast(
InstallInstalling.this,
mInstallId,
broadcastIntent,
PendingIntent.FLAG_UPDATE_CURRENT);

session.commit(pendingIntent.getIntentSender());
mCancelButton.setEnabled(false);
setFinishOnTouchOutside(false);
} else {
getPackageManager().getPackageInstaller().abandonSession(mSessionId);

if (!isCancelled()) {
launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
}
}
}
}
  1. 通过 InstallEventReceiver 注册安装成功后的监听器;
  2. 构造 SessionParams,获取 SessionID;
  3. 创建子线程,通过 SessionID 创建 Session,如果创建成功,调用 PackageInstaller.Session#commit() 方法开始安装;
  4. 如果 Session 创建失败,跳转到安装失败界面;

PackageInstallerSession 安装会话

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// PackageInstallerSession.java

@Override
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
if (!markAsSealed(statusReceiver, forTransfer)) {
return;
}
// 发送 MSG_ON_SESSION_SEALED 消息,调用 handleSessionSealed() 方法
dispatchSessionSealed();
}

private void handleSessionSealed() {
mCallback.onSessionSealedBlocking(this);
// 发送 MSG_STREAM_VALIDATE_AND_COMMIT 消息,调用 handleStreamValidateAndCommit() 方法
dispatchStreamValidateAndCommit();
}

private void handleStreamValidateAndCommit() {
boolean allSessionsReady = streamValidateAndCommit();
if (!allSessionsReady) {
return;
}
// 发送 MSG_INSTALL 消息,执行 handleInstall() 方法
mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
}

private boolean streamValidateAndCommit() {
if (!params.isMultiPackage) {
if (!prepareDataLoaderLocked()) {
return false;
}

if (isApexSession()) {
validateApexInstallLocked();
} else {
validateApkInstallLocked();
}
}

if (!isIncrementalInstallation()) {
// For non-incremental installs, client staging is fully done at this point
mClientProgress = 1f;
computeProgressLocked(true);
}
return true;
}

private void handleInstall() {
if (isApexInstallation()) {
// 处理 Apex 安装
return;
}
// 调用 verifyNonStaged()
verify();
}

private void verifyNonStaged() {
// 间接调用 makeVerificationParamsLocked() 方法,初始化 VerificationParams 对象,设置回调
final PackageManagerService.VerificationParams verifyingSession = prepareForVerification();
if (verifyingSession == null) {
return;
}
if (isMultiPackage()) {
// 多 Apk 安装
} else {
mPm.verifyStage(verifyingSession);
}
}

private PackageManagerService.VerificationParams prepareForVerification(){
if (!params.isMultiPackage) {
// 检查权限,判断是否需要用户允许
userActionRequirement = computeUserActionRequirement();
if (userActionRequirement == USER_ACTION_REQUIRED) {
sendPendingUserActionIntent();
return null;
} // else, we'll wait until we parse to determine if we need to
}

PackageLite result = parseApkLite();
computeProgressLocked(true);
extractNativeLibraries(mPackageLite, stageDir, ...);
return makeVerificationParamsLocked();
}

private PackageManagerService.VerificationParams makeVerificationParamsLocked() {
final IPackageInstallObserver2 localObserver;
if (!hasParentSessionId()) {
// Avoid attaching this observer to child session since they won't use it.
localObserver = new IPackageInstallObserver2.Stub() {
@Override
public void onUserActionRequired(Intent intent) {
throw new IllegalStateException();
}

@Override
public void onPackageInstalled(String basePackageName, int returnCode, String msg,
Bundle extras) {
if (returnCode == INSTALL_SUCCEEDED) {
onVerificationComplete();
} else {
onSessionVerificationFailure(returnCode, msg);
}
}
};
} else {
localObserver = null;
}

return mPm.new VerificationParams(user, stageDir, localObserver, ...);
}
  1. 安装任务分为了三个阶段,通过 Handler 发送不同的消息,执行不同的阶段;

  2. 第一个阶段是暂存 Apk 文件,防止应用在安装时又修改了文件,暂存文件是 /data/app/vmdl630439929.tmp/PackageInstaller,在第二阶段会重命名为 /data/app/vmdl630439929.tmp/base.apk

    1
    2
    3
    4
    5
    // PackageInstallerService.java
    private File buildTmpSessionDir(int sessionId, String volumeUuid) {
    final File sessionStagingDir = getTmpSessionDir(volumeUuid);
    return new File(sessionStagingDir, "vmdl" + sessionId + ".tmp");
    }
  3. 第二个阶段是校验 Apk 证书(更新时)、初始化安装进度;

  4. 第三个阶段是创建 VerificationParams 对象,并传递给 PMS 校验;

PMS 校验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// PackageManagerService.java

class VerificationParams extends HandlerParams {
@Override
public void handleStartCopy() {
// 校验1
mRet = verifyReplacingVersionCode(pkgLite, ...);
if (mRet != INSTALL_SUCCEEDED) {
return;
}
if (!origin.existing) {
// 校验2
sendApkVerificationRequest(pkgLite);
if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
// 校验3
sendEnableRollbackRequest();
}
}
}

@Override
void handleReturnCode() {
if (mWaitForVerificationToComplete || mWaitForIntegrityVerificationToComplete
|| mWaitForEnableRollbackToComplete) {
return;
}
sendVerificationCompleteNotification();
}

private void sendVerificationCompleteNotification() {
if (mParentVerificationParams != null) {
// ...
} else {
// 回调到 PackageInstallerSession
observer.onPackageInstalled(null, mRet, "Package Verification Result", new Bundle());
}
}
}

void verifyStage(VerificationParams params) {
mHandler.post(()-> {
// 分别调用 handleStartCopy() 和 handleReturnCode() 方法
params.startCopy();
});
}
  1. PMS#mHandler 和子线程绑定,所以执行消息时都运行在子线程中;
  2. 先调用 handleStartCopy() 方法,验证 VersionCode 是否允许降级、验证 Integrity(使用 AppIntegrityManagerServiceImpl)和验证 Rollback;
  3. 后调用 handleReturnCode() 方法,如果上一步的校验都通过后,回调 PackageInstallerSession#onVerificationComplete() 方法;

PMS 安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// PackageInstallerSession.java

private void onVerificationComplete() {
// Staged sessions will be installed later during boot
if (isStaged()) {
// ...
return;
}
// 调用 installNonStaged()
install();
}

private void installNonStaged() {
final PackageManagerService.InstallParams installingSession = makeInstallParams();
if (isMultiPackage()) {
// 多 Apk 安装
} else {
mPm.installStage(installingSession);
}
}

private PackageManagerService.InstallParams makeInstallParams() {
final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
@Override
public void onUserActionRequired(Intent intent) {
throw new IllegalStateException();
}

@Override
public void onPackageInstalled(String basePackageName, int returnCode, String msg,
Bundle extras) {
if (isStaged()) {
sendUpdateToRemoteStatusReceiver(returnCode, msg, extras);
} else {
destroyInternal();
dispatchSessionFinished(returnCode, msg, extras);
}
}
};

return mPm.new InstallParams(stageDir, localObserver, ...);
}
  1. 实例化 InstallParams 对象,设置回调;
  2. 调用 PMS.installStage() 方法,传入 InstallParams 对象;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// PackageManagerService.java

void installStage(InstallParams params) {
// 发送 INIT_COPY 消息,分别调用 InstallParams 的 handleStartCopy() 和 handleReturnCode() 方法
final Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = params;
mHandler.sendMessage(msg);
}

class InstallParams extends HandlerParams {
@Override
public void handleStartCopy() {
if ((installFlags & PackageManager.INSTALL_APEX) != 0) {
mRet = INSTALL_SUCCEEDED;
return;
}
PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext, ...);

// For staged session, there is a delay between its verification and install. Device
// state can change within this delay and hence we need to re-verify certain conditions.
boolean isStaged = (installFlags & INSTALL_STAGED) != 0;
if (isStaged) {
mRet = verifyReplacingVersionCode(pkgLite, requiredInstalledVersionCode, installFlags);
if (mRet != INSTALL_SUCCEEDED) {
return;
}
}

mRet = overrideInstallLocation(pkgLite);
}

@Override
void handleReturnCode() {
processPendingInstall();
}

private void processPendingInstall() {
// 返回 FileInstallArgs 类型
InstallArgs args = createInstallArgs(this);
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
// 调用 doCopyApk()
mRet = args.copyApk();
}
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
F2fsUtils.releaseCompressedBlocks(
mContext.getContentResolver(), new File(args.getCodePath()));
}
if (mParentInstallParams != null) {
// ...
} else {
PackageInstalledInfo res = createPackageInstalledInfo(mRet);
processInstallRequestsAsync(
res.returnCode == PackageManager.INSTALL_SUCCEEDED,
Collections.singletonList(new InstallRequest(args, res)));
}
}
}

private void processInstallRequestsAsync(boolean success, List<InstallRequest> installRequests) {
mHandler.post(() -> {
List<InstallRequest> apexInstallRequests = new ArrayList<>();
List<InstallRequest> apkInstallRequests = new ArrayList<>();
// 1. 遍历 installRequests,分别添加到 apexInstallRequests 和 apkInstallRequests 集合中
// 2. 不能同时安装 APEXes 和 APKs

if (!apexInstallRequests.isEmpty()) {
// 处理 APES
return;
}
if (success) {
for (InstallRequest request : apkInstallRequests) {
// 安装前的预处理
request.args.doPreInstall(request.installResult.returnCode);
}
synchronized (mInstallLock) {
// 安装 APK
installPackagesTracedLI(apkInstallRequests);
}
for (InstallRequest request : apkInstallRequests) {
// 安装后处理
request.args.doPostInstall(
request.installResult.returnCode, request.installResult.uid);
}
}
for (InstallRequest request : apkInstallRequests) {
restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
new PostInstallData(request.args, request.installResult, null));
}
});
}

private void restoreAndPostInstall(
int userId, PackageInstalledInfo res, @Nullable PostInstallData data) {
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
doRestore = performBackupManagerRestore(userId, token, res);
}
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && !doRestore && update) {
doRestore = performRollbackManagerRestore(userId, token, res, data);
}
if (!doRestore) {
// 发送 POST_INSTALL 消息,调用 handlePackagePostInstall() 方法
Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
mHandler.sendMessage(msg);
}
}

private void handlePackagePostInstall(PackageInstalledInfo res, ...){
boolean succeeded = res.returnCode == PackageManager.INSTALL_SUCCEEDED;
final PackageSetting pkgSetting = succeeded ? getPackageSetting(packageName) : null;
if (succeeded) {
// Send installed broadcasts if the package is not a static shared lib.
if (res.pkg.getStaticSharedLibName() == null) {
sendPackageAddedForNewUsers(packageName, ...);
if (installerPackageName != null) {
// Send to the installer, even if it's not running.
// 发送 ACTION_PACKAGE_ADDED 广播给安装器
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
installerPackageName, null /*finishedReceiver*/,
updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
}

// If package installer is defined, notify package installer about new
// app installed
if (mRequiredInstallerPackage != null) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND /*flags*/,
mRequiredInstallerPackage, null /*finishedReceiver*/,
firstUserIds, instantUserIds, null /* broadcastAllowList */, null);
}

if (allNewUsers && !update) {
// 回调 PermissionPolicyService
notifyPackageAdded(packageName, res.uid);
} else {
notifyPackageChanged(packageName, res.uid);
}

final boolean deferInstallObserver = succeeded && update && !killApp;
if (deferInstallObserver) {
scheduleDeferredNoKillInstallObserver(res, installObserver);
} else {
// 回调 InstallParams 对象的监听器
notifyInstallObserver(res, installObserver);
}
}
}
}
  1. 发送 INIT_COPY 消息,分别调用 handleStartCopy() 和 handleReturnCode() 方法;
  2. handleStartCopy() 方法校验 VersionCode,设置 Apk 安装路径;
  3. handleReturnCode() 方法,根据上步的 Code,异步处理安装请求,安装成功后回调 InstallParams 对象的监听器;

安装成功回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// PackageInstallerSession.java

private PackageManagerService.InstallParams makeInstallParams() {

final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
@Override
public void onUserActionRequired(Intent intent) {
throw new IllegalStateException();
}

@Override
public void onPackageInstalled(String basePackageName, int returnCode, String msg,
Bundle extras) {
if (isStaged()) {
sendUpdateToRemoteStatusReceiver(returnCode, msg, extras);
} else {
// We've reached point of no return; call into PMS to install the stage.
// Regardless of success or failure we always destroy session.
// 删除临时文件
destroyInternal();
dispatchSessionFinished(returnCode, msg, extras);
}
}
};
}

private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
// 发送 MSG_ON_PACKAGE_INSTALLED 消息,调用 sendOnPackageInstalled() 方法
sendUpdateToRemoteStatusReceiver(returnCode, msg, extras);

final boolean success = (returnCode == INSTALL_SUCCEEDED);

// Send broadcast to default launcher only if it's a new install
// TODO(b/144270665): Secure the usage of this broadcast.
final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
if (success && isNewInstall && mPm.mInstallerService.okToSendBroadcasts()) {
// 发送广播,通知 Launcher
mPm.sendSessionCommitBroadcast(generateInfoScrubbed(true /*icon*/), userId);
}

// 回调安装成功接口,销毁 Session
mCallback.onSessionFinished(this, success);
if (isDataLoaderInstallation()) {
logDataLoaderInstallationSession(returnCode);
}
}

private static void sendOnPackageInstalled(Context context, IntentSender target, ...){
if (INSTALL_SUCCEEDED == returnCode && showNotification) {
// 显示安装成功通知
}
final Intent fillIn = new Intent();
fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, basePackageName);
fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
PackageManager.installStatusToPublicStatus(returnCode));
fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
PackageManager.installStatusToString(returnCode, msg));
fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
if (extras != null) {
final String existing = extras.getString(
PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
if (!TextUtils.isEmpty(existing)) {
fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing);
}
}
// 发送 PendingIntent,通知安装器安装成功
target.sendIntent(context, 0, fillIn, null, null);
}
  1. 接收到安装成功后的通知后删除临时目录 /data/app/vmdl630439929.tmp/
  2. 发送广播给安装器和桌面;
  3. 最后销毁 Session,保存 Session 到历史记录集合;