PMS 安装 Apk 流程

本文分析安装器提交 Apk 到 PMS 进行安装的过程。

安装器创建 Session 的任务完成后开始安装操作:

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
// frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java

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);
}
}
}

安装任务走到 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
112
113
114
115
116
117
118
119
120
121
122
123
124
// PackageInstallerSession.java
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_STREAM_VALIDATE_AND_COMMIT:
handleStreamValidateAndCommit();
break;
case MSG_INSTALL:
handleInstall();
break;
case MSG_ON_PACKAGE_INSTALLED:
sendOnPackageInstalled(mContext, statusReceiver, ...);
break;
case MSG_SESSION_VERIFICATION_FAILURE:
// ...
break;
}

return true;
}
};

@Override
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
dispatchStreamValidateAndCommit();
}

private void dispatchStreamValidateAndCommit() {
mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget();
}

private void handleStreamValidateAndCommit() {
boolean allSessionsReady = streamValidateAndCommit();
if (!allSessionsReady) {
return;
}
mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
}

private void handleInstall() {
if (params.isStaged) {
mStagingManager.commitSession(this);
destroyInternal();
dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null);
return;
}

if (isApexInstallation()) {
destroyInternal();
dispatchSessionFinished(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
"APEX packages can only be installed using staged sessions.", null);
return;
}

List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
installNonStagedLocked(childSessions);
}

private void installNonStagedLocked(List<PackageInstallerSession> childSessions) {
final PackageManagerService.ActiveInstallSession installingSession = makeSessionActiveLocked();
if (isMultiPackage()) {
// 默认 false
} else {
mPm.installStage(installingSession);
}
}

private PackageManagerService.ActiveInstallSession makeSessionActiveLocked(){
final IPackageInstallObserver2 localObserver;
if (isApexInstallation()) {
localObserver = null;
} else {
// 注册回调
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) {
// Apk 安装成功,删除临时文件
destroyInternal();
// 通知安装 Session 任务完成
dispatchSessionFinished(returnCode, msg, extras);
}
};
}

return new PackageManagerService.ActiveInstallSession(mPackageName, localObserver, ...);
}

private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
// 安装器提交 Session 时传递的 PendingIntent
final IntentSender statusReceiver;
if (statusReceiver != null) {
mHandler.obtainMessage(MSG_ON_PACKAGE_INSTALLED, args).sendToTarget();
}

final boolean success = (returnCode == PackageManager.INSTALL_SUCCEEDED);

// 发送广播,通知 Launcher
final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
if (success && isNewInstall && mPm.mInstallerService.okToSendBroadcasts()
&& (params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
mPm.sendSessionCommitBroadcast(generateInfoScrubbed(true /*icon*/), userId);
}
}

private static void sendOnPackageInstalled(Context context, IntentSender target, ...){
// 显示安装成功通知
if (PackageManager.INSTALL_SUCCEEDED == returnCode && showNotification) {
Notification notification = PackageInstallerService.buildSuccessNotification(context, ...);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(basePackageName, ..., notification);
} else {
final Intent fillIn = new Intent();
// 设置 Intent 参数
// 发送 PendingIntent,通知安装器安装成功
target.sendIntent(context, 0, fillIn, null, null);
}
}

调用到 PMS mPm.installStage(installingSession)

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
// PackageManagerService.java

class PackageHandler extends Handler {
public void handleMessage(Message msg) {
doHandleMessage(msg);
}

void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj;
if (params != null) {
// 分别调用 handleStartCopy() 和 handleReturnCode() 方法
params.startCopy();
}
break;
}
case POST_INSTALL: {
PostInstallData data = mRunningInstalls.get(msg.arg1);
handlePackagePostInstall(parentRes, args.observer, ...);
} break;
}
}
}

void installStage(List<ActiveInstallSession> children) {
final Message msg = mHandler.obtainMessage(INIT_COPY);
final MultiPackageInstallParams params = new MultiPackageInstallParams(UserHandle.ALL, children);
msg.obj = params;
mHandler.sendMessage(msg);
}

public void handleStartCopy() {

}

public void handleReturnCode() {
processPendingInstall(mArgs, mRet);
}

private void processPendingInstall(final InstallArgs args, final int currentStatus) {
if (args.mMultiPackageInstallParams != null) {
args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
} else {
PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
processInstallRequestsAsync(
res.returnCode == PackageManager.INSTALL_SUCCEEDED,
Collections.singletonList(new InstallRequest(args, res)));
}
}

private void processInstallRequestsAsync(boolean success,
List<InstallRequest> installRequests) {
mHandler.post(() -> {
if (success) {
for (InstallRequest request : installRequests) {
request.args.doPreInstall(request.installResult.returnCode);
}
synchronized (mInstallLock) {
installPackagesTracedLI(installRequests);
}
for (InstallRequest request : installRequests) {
request.args.doPostInstall(
request.installResult.returnCode, request.installResult.uid);
}
}
for (InstallRequest request : installRequests) {
restoreAndPostInstall(request.args.user.getIdentifier(), ...);
}
});
}

private void restoreAndPostInstall(int userId, ...){
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
doRestore = performBackupManagerRestore(userId, token, res);
}
if (!doRestore) {
Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
mHandler.sendMessage(msg);
}
}

发送 POST_INSTALL 消息,调用 handlePackagePostInstall() 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// PackageManagerService.java

private void handlePackagePostInstall(PackageInstalledInfo res, IPackageInstallObserver2 installObserver, ...){
boolean succeeded = res.returnCode == PackageManager.INSTALL_SUCCEEDED;
if (succeeded) {
// ...
}
notifyInstallObserver(res, installObserver);
final boolean deferInstallObserver = succeeded && update && !killApp;
if (deferInstallObserver) {
scheduleDeferredNoKillInstallObserver(res, installObserver);
} else {
notifyInstallObserver(res, installObserver);
}
}

private void notifyInstallObserver(PackageInstalledInfo info, IPackageInstallObserver2 installObserver) {
if (installObserver != null) {
Bundle extras = extrasForInstallResult(info);
installObserver.onPackageInstalled(info.name, ...);
}
}