android源码分析目录
一 概述
之前咱们介绍了 PMS 的作业原理。首要包含 PMS 的发动流程,和 PMS 发动时扫描装置使用,并获取四大组件信息的流程。
今日咱们再来说说 PMS 的别的一个作业流程,那便是 PMS 装置 apk 的流程。
首要,Android 的装置会经过一个 InstallStart 进行跳转,到达一个 PackageInstallerActivity。
二 PackageInstallerActivity
2.1 onCreate
protected void onCreate(Bundle icicle) {
getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
super.onCreate(null);
if (icicle != null) {
mAllowUnknownSources = icicle.getBoolean(ALLOW_UNKNOWN_SOURCES_KEY);
}
// 获取 PackageManager
mPm = getPackageManager();
// 获取 IPackageManager
mIpm = AppGlobals.getPackageManager();
// 获取权限办理 AppOpsManager
mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
// 经过 PackageManager 取得 PackageInstaller
mInstaller = mPm.getPackageInstaller();
// 获取 多用户体系办理用户的类 UserManager
mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
final Intent intent = getIntent();
...
// 装置包的 Uri
final Uri packageUri;
if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction())) {
final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1);
// 经过 mInstaller 获取一个 PackageInstaller.SessionInfo
final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId);
mSessionId = sessionId;
packageUri = Uri.fromFile(new File(info.resolvedBaseCodePath));
mOriginatingURI = null;
mReferrerURI = null;
}
...
}
PackageInstallerActivity 的逻辑首要在onCreate和onResume中,在 onCreate 中,首要是获取一个PackageInstaller.SessionInfo,并构造一个 Uri。
2.2 onResume
protected void onResume() {
super.onResume();
if (mAppSnippet != null) {
// 在咱们覆盖这个布局之前,加载假布局并禁用OK按钮
bindUi();
// 查看是否答应装置该软件包,假如答应就发动装置。假如不答应
// 则显现相应的对话框。
checkIfAllowedAndInitiateInstall();
}
...
}
在 onResume 中,则进行了 UI 绑定,会展现咱们想要装置的 apk 的一些基本信息。
2.3 bindUi
bindUi 便是将咱们要装置的使用展现出来,并给用户弹窗挑选。
private void bindUi() {
// 展现要装置apk的根底信息
mAlert.setIcon(mAppSnippet.icon);
mAlert.setTitle(mAppSnippet.label);
mAlert.setView(R.layout.install_content_view);
// 两个按钮
mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
(ignored, ignored2) -> {
if (mOk.isEnabled()) {
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, true);
finish();
} else {
startInstall();
}
}
}, null);
mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
(ignored, ignored2) -> {
// Cancel and finish
setResult(RESULT_CANCELED);
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, false);
}
finish();
}, null);
setupAlert();
mOk = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
mOk.setEnabled(false);
...
}
在装置界面展现使用的一些简介信息 mAppSnippet,假如用户挑选赞同,就开端装置 startInstall,否则就关闭页面。
2.4 startInstall
startInstall 的逻辑便是发动一个子 Activity 来实践装置使用程序,它便是 InstallInstalling。
private void startInstall() {
Intent newIntent = new Intent();
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
mPkgInfo.applicationInfo);
newIntent.setData(mPackageURI);
// 设置目标 Activity
newIntent.setClass(this, InstallInstalling.class);
String installerPackageName = getIntent().getStringExtra(
Intent.EXTRA_INSTALLER_PACKAGE_NAME);
... // 传参
newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
startActivity(newIntent);
finish();
}
三 InstallInstalling
InstallInstalling 装置使用有两个阶段
- 发送装置包给 PackageManager 并处理来自 PackageManager 的成果。
- 处理成果回调,InstallSuccess 或 InstallFailed。
3.1 onCreate
相同咱们从 onCreate 开端,
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ApplicationInfo appInfo = getIntent()
.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
mPackageURI = getIntent().getData();
// 经过 scheme 来判别当时的第一阶段仍是第二阶段
if ("package".equals(mPackageURI.getScheme())) {
try {
// 假如是第二阶段,就跳转到处理成果的函数,成功或者失利
getPackageManager().installExistingPackage(appInfo.packageName);
launchSuccess();
} catch (PackageManager.NameNotFoundException e) {
launchFailure(PackageInstaller.STATUS_FAILURE,
PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
} else {
// 假如是第一阶段,就将装置包信息发送给 PackageManager
final File sourceFile = new File(mPackageURI.getPath());
PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
mAlert.setIcon(as.icon);
mAlert.setTitle(as.label);
mAlert.setView(R.layout.install_content_view);
mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
...
}, null);
setupAlert();
requireViewById(R.id.installing).setVisibility(View.VISIBLE);
if (savedInstanceState != null) {
mSessionId = savedInstanceState.getInt(SESSION_ID);
mInstallId = savedInstanceState.getInt(INSTALL_ID);
// 为成果注册观察者;假如成果被交付,或许会当即回调,同时
// 活动被破坏
try {
InstallEventReceiver.addObserver(this, mInstallId,
this::launchFinishBasedOnResult);
} catch (EventResultPersister.OutOfIdsException e) {
// Does not happen
}
} else {
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
final Uri referrerUri = getIntent().getParcelableExtra(Intent.EXTRA_REFERRER);
... // 填充参数
File file = new File(mPackageURI.getPath());
...
try {
// 获取 PackageManager 的 PackageInstaller,拿到 PackageInstallerService
// 发送装置参数
mSessionId = getPackageManager().getPackageInstaller().createSession(params);
} catch (IOException e) {
launchFailure(PackageInstaller.STATUS_FAILURE,
PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
}
mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);
}
}
在 onCreate 中有两个分支,进行装置仍是装置成功,
- 假如是装置成功,就会发动 InstallSuccess (一个对应的 Activity)。
- 进行装置就会进行参数填充。
最终经过 getPackageManager().getPackageInstaller().createSession(params) 创立了一个 Session。
3.2 onResume
protected void onResume() {
super.onResume();
if (mInstallingTask == null) {
PackageInstaller installer = getPackageManager().getPackageInstaller();
PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);
if (sessionInfo != null && !sessionInfo.isActive()) {
mInstallingTask = new InstallingAsyncTask();
// 执行装置使命
mInstallingTask.execute();
} else {
// we will receive a broadcast when the install is finished
mCancelButton.setEnabled(false);
setFinishOnTouchOutside(false);
}
}
}
- InstallingAsyncTask
- PackageInstallerService
四 InstallingAsyncTask
InstallingAsyncTask 承继自 AsyncTask,首要是将文件西悉尼写到 session,然后提交到 session。代码很长,咱们主重视主流程的提交即可。
private final class InstallingAsyncTask extends AsyncTask<Void, Void,
PackageInstaller.Session> {
volatile boolean isDone;
@Override
protected PackageInstaller.Session doInBackground(Void... params) {
PackageInstaller.Session session;
try {
// 1. 经过 mSessionId 获取对应的 session
session = getPackageManager().getPackageInstaller().openSession(mSessionId);
} ...
session.setStagingProgress(0);
try {
// 将文件信息写入 session
...
return session;
} ...
}
@Override
protected void onPostExecute(PackageInstaller.Session session) {
if (session != null) {
// 提交 session
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 | PendingIntent.FLAG_MUTABLE);
// IPackageInstallerSession 其实便是 PackageInstallerService
session.commit(pendingIntent.getIntentSender());
mCancelButton.setEnabled(false);
setFinishOnTouchOutside(false);
} else {
...
}
}
}
五 PackageInstallerService
5.1 createSession
[frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java]
public int createSession(SessionParams params, String installerPackageName,
String callingAttributionTag, int userId) {
try {
return createSessionInternal(params, installerPackageName, callingAttributionTag,
userId);
} catch (IOException e) {
throw ExceptionUtils.wrap(e);
}
}
createSession 是创立一个体系仅有的 session,这个 session 表明一次装置过程,这样哪怕后续装置中断了,都可用凭仗这个 session 进行康复装置。
接下来咱们看看提交的逻辑。
六 PackageInstallerSession
6.1 commit
session 提交之后会经过大量的 Handler 转发,所以咱们找到它终究调用的 handleInstall。
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
...
dispatchSessionSealed();
}
6.2 dispatchSessionSealed
private void dispatchSessionSealed() {
mHandler.obtainMessage(MSG_ON_SESSION_SEALED).sendToTarget();
}
6.3 handleSessionSealed
private void handleSessionSealed() {
...
dispatchStreamValidateAndCommit();
}
6.4 handleStreamValidateAndCommit
private void handleStreamValidateAndCommit() {
try {
// 发送消息 MSG_INSTALL
if (allSessionsReady && streamValidateAndCommit()) {
mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
}
} catch (PackageManagerException e) {
destroy();
String msg = ExceptionUtils.getCompleteMessage(e);
dispatchSessionFinished(e.error, msg, null);
maybeFinishChildSessions(e.error, msg);
}
}
6.5 handleInstall
private void handleInstall() {
/**
* 假如一个Session 需求用户操作,则中止整个Session集的装置
*/
if (sendPendingUserActionIntentIfNeeded()) {
return;
}
// isStaged 为 true 的时分表明下次体系发动的时分才真实装置
// 一般用于(体系的)apex装置
if (params.isStaged) {
mStagedSession.verifySession();
} else {
verify();
}
}
isStaged 为 true 表明现在不装置,下次发动发动的时分装置,一般用于装置体系的 apex 包。和咱们使用装置无关。
在 handleInstall 中,会调用 verify,之后都是一些装置的校验,包含且不限于包名,签名,Hash 值等等,这儿就不详细探讨了。关于装置包的校验,这儿就不多扩展了,咱们看一下调用流程即可。
6.6 verifySession
public void verifySession() {
verify();
}
6.7 verify
private void verify() {
try {
...
verifyNonStaged();
} catch (PackageManagerException e) {
...
}
}
6.8 verifyNonStaged
private void verifyNonStaged()
throws PackageManagerException {
mSessionProvider.getSessionVerifier().verify(this, (error, msg) -> {
mHandler.post(() -> {
...
// 调用完结而且成功,调用 onVerificationComplete
if (error == INSTALL_SUCCEEDED) {
onVerificationComplete();
} else {
// 校验不经过
onSessionVerificationFailure(error, msg);
}
});
});
}
6.9 onVerificationComplete
private void onVerificationComplete() {
// 校验完结,开端装置。
install();
}
当校验完结之后,就会调用 install 开端装置。
6.10 install
private void install() {
try {
installNonStaged();
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
onSessionInstallationFailure(e.error, completeMsg);
}
}
6.11 installNonStaged
private void installNonStaged()
throws PackageManagerException {
final PackageManagerService.InstallParams installingSession = makeInstallParams();
if (installingSession == null) {
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
"Session should contain at least one apk session for installation");
}
if (isMultiPackage()) {
...
mPm.installStage(installingSession, installingChildSessions);
} else {
mPm.installStage(installingSession);
}
}
在装置函数 installNonStaged 中,不论是批量装置的 isMultiPackage,仍是单个装置,终究都会执行到 PMS 的 installStage。
七 PMS
7.1 installStage
void installStage(InstallParams params) {
final Message msg = mHandler.obtainMessage(INIT_COPY);
params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
mHandler.sendMessage(msg);
}
在 PMS 的 installStage 中,首要就会经过 Handler 发送一条消息 INIT_COPY,开端复制装置包。
7.2 doHandleMessage
void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj;
if (params != null) {
params.startCopy();
}
break;
}
在 doHandleMessage 中,会调用 startCopy 复制装置包,这个 params,便是之前传入的
八 HandlerParams
private abstract class HandlerParams {
final void startCopy() {
handleStartCopy();
handleReturnCode();
}
}
这个 HandlerParams 是一个抽象类,它的 startCopy 调用了两个函数 handleStartCopy 和 handleReturnCode,这两个都是抽象办法,由子类完结。
而这个子类在之前传入的参数的[7.1]中咱们现已看到了,它便是 InstallParams。
九 PMS.InstallParams
9.1 handleStartCopy
public void handleStartCopy() {
if ((mInstallFlags & PackageManager.INSTALL_APEX) != 0) {
mRet = INSTALL_SUCCEEDED;
return;
}
// 获取一个包信息
PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mPm.mContext,
mPackageLite, mOriginInfo.mResolvedPath, mInstallFlags, mPackageAbiOverride);
// 验证和装置之间有一个推迟。设备的状况或许在这个推迟内发生变化
// 所以咱们需求从头验证。
boolean isStaged = (mInstallFlags & INSTALL_STAGED) != 0;
if (isStaged) {
Pair<Integer, String> ret = mInstallPackageHelper.verifyReplacingVersionCode(
pkgLite, mRequiredInstalledVersionCode, mInstallFlags);
mRet = ret.first;
if (mRet != INSTALL_SUCCEEDED) {
return;
}
}
final boolean ephemeral = (mInstallFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
if (!mOriginInfo.mStaged && pkgLite.recommendedInstallLocation
== InstallLocationUtils.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
// 假如 staged 为 false,但是可用空间太小,就释放缓存再测验一次
pkgLite.recommendedInstallLocation = mPm.freeCacheForInstallation(
pkgLite.recommendedInstallLocation, mPackageLite,
mOriginInfo.mResolvedPath, mPackageAbiOverride, mInstallFlags);
}
// 覆盖装置
mRet = overrideInstallLocation(pkgLite.packageName, pkgLite.recommendedInstallLocation,
pkgLite.installLocation);
}
handleStartCopy 准确来说是为复制做的一些预备,真实的复制是由 handleReturnCode 完结的。
9.2 handleReturnCode
void handleReturnCode() {
processPendingInstall();
}
9.3 processPendingInstall
private void processPendingInstall() {
// 创立装置参数
InstallArgs args = createInstallArgs(this);
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
// 复制 apk
mRet = args.copyApk();
}
...
// 下面两个函数,最终都会调用到 processInstallRequestsAsync
if (mParentInstallParams != null) {
mParentInstallParams.tryProcessInstallRequest(args, mRet);
} else {
PackageInstalledInfo res = new PackageInstalledInfo(mRet);
processInstallRequestsAsync(
res.mReturnCode == PackageManager.INSTALL_SUCCEEDED,
Collections.singletonList(new InstallRequest(args, res)));
}
}
- 这儿的 args 是一个 InstallArgs,这是一个抽象类,咱们直接看它的完结 FileInstallArgs。PMS 便是经过它完结的 apk 的复制。
- 然后经过 InstallParams 的 processInstallRequestsAsync 处理复制后的流程。
十 FileInstallArgs
10.1 copyApk
[frameworks/base/services/core/java/com/android/server/pm/FileInstallArgs.java]
int copyApk() {
return doCopyApk();
}
10.2 doCopyApk
private int doCopyApk() {
try {
final boolean isEphemeral = (mInstallFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
// 分配权限,创立目录 /data/app
final File tempDir =
mPm.mInstallerService.allocateStageDirLegacy(mVolumeUuid, isEphemeral);
mCodeFile = tempDir;
} catch (IOException e) {
...
}
// 复制apk
int ret = PackageManagerServiceUtils.copyPackage(
mOriginInfo.mFile.getAbsolutePath(), mCodeFile);
if (ret != PackageManager.INSTALL_SUCCEEDED) {
Slog.e(TAG, "Failed to copy package");
return ret;
}
final boolean isIncremental = isIncrementalPath(mCodeFile.getAbsolutePath());
final File libraryRoot = new File(mCodeFile, LIB_DIR_NAME);
NativeLibraryHelper.Handle handle = null;
try {
// 复制 so 库
handle = NativeLibraryHelper.Handle.create(mCodeFile);
ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
mAbiOverride, isIncremental);
} catch (IOException e) {
Slog.e(TAG, "Copying native libraries failed", e);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
} finally {
IoUtils.closeQuietly(handle);
}
return ret;
}
十一 PackageManagerServiceUtils
11.1 copyPackage
[frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java]
public static int copyPackage(String packagePath, File targetDir) {
try {
final File packageFile = new File(packagePath);
...
// 调用 copyFile 函数开端复制
copyFile(pkg.getBaseApkPath(), targetDir, "base.apk");
if (!ArrayUtils.isEmpty(pkg.getSplitNames())) {
for (int i = 0; i < pkg.getSplitNames().length; i++) {
copyFile(pkg.getSplitApkPaths()[i], targetDir,
"split_" + pkg.getSplitNames()[i] + ".apk");
}
}
return PackageManager.INSTALL_SUCCEEDED;
}
}
11.2 copyFile
private static void copyFile(String sourcePath, File targetDir, String targetName)
throws ErrnoException, IOException {
final File targetFile = new File(targetDir, targetName);
final FileDescriptor targetFd = Os.open(targetFile.getAbsolutePath(),
O_RDWR | O_CREAT, 0644);
Os.chmod(targetFile.getAbsolutePath(), 0644);
FileInputStream source = null;
try {
source = new FileInputStream(sourcePath);
FileUtils.copy(source.getFD(), targetFd);
} finally {
IoUtils.closeQuietly(source);
}
}
最终在 copyFile 函数进行了复制,权限为 0644,即用户具有读写权限,组用户和其它用户具有只读权限。
接下来咱们回到 [9.2] 继续看后面的流程 processInstallRequestsAsync。
十二 PMS
12.1 processInstallRequestsAsync
[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
// 排队进行异步操作,因为软件包的装置或许需求一点时间
private void processInstallRequestsAsync(boolean success,
List<InstallRequest> installRequests) {
...
if (success) {
for (InstallRequest request : apkInstallRequests) {
request.args.doPreInstall(request.installResult.returnCode);
}
synchronized (mInstallLock) {
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));
}
}
十三 InstallPackageHelper
13.1 processInstallRequests
[frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java]
public void processInstallRequests(boolean success, List<InstallRequest> installRequests) {
List<InstallRequest> apexInstallRequests = new ArrayList<>();
List<InstallRequest> apkInstallRequests = new ArrayList<>();
for (InstallRequest request : installRequests) {
if ((request.mArgs.mInstallFlags & PackageManager.INSTALL_APEX) != 0) {
apexInstallRequests.add(request);
} else {
apkInstallRequests.add(request);
}
}
// 支撑APEXs和APKs的多包装置或许需求一些考虑以确保装置的原子性。
if (!apexInstallRequests.isEmpty()) {
if (success) {
// 因为 installApexPackages 需求与外部服务(apexd)对话,
// 所以咱们 安排以异步方式运行它。一旦完结,它将康复装置。
Thread t = new Thread(() -> installApexPackagesTraced(apexInstallRequests),
"installApexPackages");
t.start();
} else {
// 非阶段性APEX装置在之前的某个当地失利了
// processInstallRequestAsync。在这种情况下,只需求告诉观察者失利
InstallRequest request = apexInstallRequests.get(0);
mPm.notifyInstallObserver(request.mInstallResult,
request.mArgs.mObserver);
}
return;
}
if (success) {
// 预装置,做一些查看,假如存在异常情况,就清楚复制的 apk 文件
for (InstallRequest request : apkInstallRequests) {
request.mArgs.doPreInstall(request.mInstallResult.mReturnCode);
}
// 真实的装置
synchronized (mPm.mInstallLock) {
installPackagesTracedLI(apkInstallRequests);
}
// 装置后的操作
for (InstallRequest request : apkInstallRequests) {
request.mArgs.doPostInstall(
request.mInstallResult.mReturnCode, request.mInstallResult.mUid);
}
}
for (InstallRequest request : apkInstallRequests) {
restoreAndPostInstall(request.mArgs.mUser.getIdentifier(),
request.mInstallResult,
new PostInstallData(request.mArgs,
request.mInstallResult, null));
}
}
processInstallRequests 便是真实装置的流程。它分为 4 个过程
- doPreInstall 装置预处理,判别校验的成果,假如不经过就清楚 apk 文件。
- installPackagesTracedLI 真实的装置逻辑。
- doPostInstall 装置后的处理操作。
十四 PMS
14.1 doPreInstall
[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
int doPreInstall(int status) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
cleanUp();
}
return status;
}
假如校验状况不经过,就经过 cleanUp 清除装置文件。
14.2 installPackagesTracedLI
[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
private void installPackagesTracedLI(List<InstallRequest> requests) {
...
installPackagesLI(requests);
}
14.3 installPackagesLI
[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
private void installPackagesLI(List<InstallRequest> requests) {
...
for (InstallRequest request : requests) {
// 获取一切的恳求,并扫描、校对或提交
final PrepareResult prepareResult;
try {
// 先预处理
prepareResult =
preparePackageLI(request.mArgs, request.mInstallResult);
} ...
...
try {
// 扫描
final ScanResult result = scanPackageTracedLI(
prepareResult.mPackageToScan, prepareResult.mParseFlags,
prepareResult.mScanFlags, System.currentTimeMillis(),
request.mArgs.mUser, request.mArgs.mAbiOverride);
...
}
...
try {
// 调停装置包
reconciledPackages = ReconcilePackageUtils.reconcilePackages(
reconcileRequest, mSharedLibraries,
mPm.mSettings.getKeySetManagerService(), mPm.mSettings);
} ...
try {
// 提交装置包
commitRequest = new CommitRequest(reconciledPackages,
mPm.mUserManager.getUserIds());
commitPackagesLocked(commitRequest);
success = true;
} ...
}
// 提交
executePostCommitSteps(commitRequest);
} finally {
if (success) {
for (InstallRequest request : requests) {
final InstallArgs args = request.mArgs;
if (args.mDataLoaderType != DataLoaderType.INCREMENTAL) {
continue;
}
if (args.mSigningDetails.getSignatureSchemeVersion() != SIGNING_BLOCK_V4) {
continue;
}
// 假如是增量装置,咱们在装置前绕过验证器。
// 在验证了软件包是有效的后,向验证器发送一个告诉,
// 其中包含 base.apk的根哈希值
...
VerificationUtils.broadcastPackageVerified(verificationId, originUri,
PackageManager.VERIFICATION_ALLOW, rootHashString,
args.mDataLoaderType, args.getUser(), mContext);
}
} else {
for (ScanResult result : preparedScans.values()) {
if (createdAppId.getOrDefault(result.mRequest.mParsedPackage.getPackageName(),
false)) {
cleanUpAppIdCreation(result);
}
}
// 创立一个装置失利的描述性的原因。
for (InstallRequest request : requests) {
if (request.mInstallResult.mFreezer != null) {
request.mInstallResult.mFreezer.close();
}
if (request.mInstallResult.mReturnCode == PackageManager.INSTALL_SUCCEEDED) {
request.mInstallResult.mReturnCode = PackageManager.INSTALL_UNKNOWN;
}
}
}
}
}
installPackagesLI 便是装置的首要流程,它分为 4 步
- preparePackageLI:预处理装置包
- scanPackageTracedLI:扫描装置包
- reconcilePackages:调停装置包
- commitPackagesLocked:提交装置包
14.4 preparePackageLI
preparePackageLI 是装置前的预处理,它里边会对装置包做各种判别,例如版别校验,签名校验等等。
private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
throws PrepareFailure {
...
// PackageParser2 解析装置包,咱们在 PMS 解析装置使用中现已讲过它的原理了
// 它可以解析装置使用的四大组件
final ParsedPackage parsedPackage;
try (PackageParser2 pp = mPm.mInjector.getPreparingPackageParser()) {
parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
} ...
...
// 假如有现成的就使用,否则从APK中解析
if (args.mSigningDetails != SigningDetails.UNKNOWN) {
parsedPackage.setSigningDetails(args.mSigningDetails);
} else {
// 解析
final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
final ParseResult<SigningDetails> result = ParsingPackageUtils.getSigningDetails(
input, parsedPackage, false /*skipVerify*/);
parsedPackage.setSigningDetails(result.getResult());
}
boolean systemApp = false;
boolean replace = false;
synchronized (mPm.mLock) {
// 查看是否存在相同的装置包
if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
String oldName = mPm.mSettings.getRenamedPackageLPr(pkgName);
if (parsedPackage.getOriginalPackages().contains(oldName)
&& mPm.mPackages.containsKey(oldName)) {
...
} else if (mPm.mPackages.containsKey(pkgName)) {
//存在软件包,就替换
replace = true;
if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing package: " + pkgName);
}
if (replace) {
// 避免使用程序退出运行时权限的版别,
// 所以新的 targetSdk 不能小于旧的
AndroidPackage oldPackage = mPm.mPackages.get(pkgName);
final int oldTargetSdk = oldPackage.getTargetSdkVersion();
final int newTargetSdk = parsedPackage.getTargetSdkVersion();
if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1
&& newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) {
...
}
...
}
}
...
if (signatureCheckPs != null) {
// 签名查看
final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService();
final SharedUserSetting signatureCheckSus = mPm.mSettings.getSharedUserSettingLPr(
signatureCheckPs);
if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, signatureCheckSus,
scanFlags)) {
if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, parsedPackage)) {
throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
+ parsedPackage.getPackageName() + " upgrade keys do not match the "
+ "previously installed version");
}
} else {
...
}
}
...
// 将查看权限兼容性的逻辑移到PermissionManagerService中
final int n = ArrayUtils.size(parsedPackage.getPermissions());
for (int i = n - 1; i >= 0; i--) {
final ParsedPermission perm = parsedPackage.getPermissions().get(i);
final Permission bp = mPm.mPermissionManager.getPermissionTEMP(perm.getName());
// 除了体系,不要答应任何人界说短暂的权限
if ((perm.getProtectionLevel() & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0
&& !systemApp) {
ComponentMutateUtils.setProtectionLevel(perm,
perm.getProtectionLevel() & ~PermissionInfo.PROTECTION_FLAG_INSTANT);
}
...
}
}
if (systemApp) {
if (onExternal) {
// 体系app不能装置到sd卡
throw new PrepareFailure(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
"Cannot install updates to system apps on sdcard");
} else if (instantApp) {
// 体系使用不能被即时使用取代
throw new PrepareFailure(INSTALL_FAILED_SESSION_INVALID,
"Cannot update a system app with an instant app");
}
}
if (args.mMoveInfo != null) {
// 假如现已做过一次移动,就符号Dex现已预备好
scanFlags |= SCAN_NO_DEX;
scanFlags |= SCAN_MOVE;
synchronized (mPm.mLock) {
final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
if (ps == null) {
res.setError(INSTALL_FAILED_INTERNAL_ERROR,
"Missing settings for moved package " + pkgName);
}
// We moved the entire application as-is, so bring over the
// previously derived ABI information.
parsedPackage.setPrimaryCpuAbi(ps.getPrimaryCpuAbi())
.setSecondaryCpuAbi(ps.getSecondaryCpuAbi());
}
} else {
// 启用SCAN_NO_DEX标志,以便在以后阶段越过dexopt
scanFlags |= SCAN_NO_DEX;
...
}
final PackageFreezer freezer =
freezePackageForInstall(pkgName, installFlags, "installPackageLI");
boolean shouldCloseFreezerBeforeReturn = true;
try {
final AndroidPackage oldPackage;
String renamedPackage;
boolean sysPkg = false;
int targetScanFlags = scanFlags;
int targetParseFlags = parseFlags;
final PackageSetting ps;
final PackageSetting disabledPs;
final SharedUserSetting sharedUserSetting;
if (replace) {
// 假如 replace 是 true,表明存在一个旧的装置包
// 那么就要要验证新装置包是否可用,而且还有先备份一下旧的装置包
// 假如装置失利,旧需求回滚
... //
synchronized (mPm.mLock) {
if (DEBUG_INSTALL) {
Slog.d(TAG,
"replacePackageLI: new=" + parsedPackage + ", old=" + oldPackage);
}
ps = mPm.mSettings.getPackageLPr(pkgName11);
disabledPs = mPm.mSettings.getDisabledSystemPkgLPr(ps);
sharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(ps);
// 验证签名是否有效
final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService();
if (ksms.shouldCheckUpgradeKeySetLocked(ps, sharedUserSetting, scanFlags)) {
if (!ksms.checkUpgradeKeySetLocked(ps, parsedPackage)) {
throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
"New package not signed by keys specified by upgrade-keysets: "
+ pkgName11);
}
} ...
// 不答应体系晋级,除非晋级的哈希值匹配
if (oldPackage.getRestrictUpdateHash() != null && oldPackage.isSystem()) {
...
}
... // 各种不答应晋级的情况判别
}
// 更新被删去的内容
res.mRemovedInfo = new PackageRemovedInfo(mPm);
res.mRemovedInfo.mUid = oldPackage.getUid();
res.mRemovedInfo.mRemovedPackage = oldPackage.getPackageName();
res.mRemovedInfo.mInstallerPackageName = ps.getInstallSource().installerPackageName;
res.mRemovedInfo.mIsStaticSharedLib =
parsedPackage.getStaticSharedLibName() != null;
...
sysPkg = oldPackage.isSystem();
if (sysPkg) {
// 根据需求设置体系/特权/oem/供货商/产品的标志
final boolean privileged = oldPackage.isPrivileged();
final boolean oem = oldPackage.isOem();
final boolean vendor = oldPackage.isVendor();
final boolean product = oldPackage.isProduct();
final boolean odm = oldPackage.isOdm();
final boolean systemExt = oldPackage.isSystemExt();
...
targetParseFlags = systemParseFlags;
targetScanFlags = systemScanFlags;
} else { // non system replace
replace = true;
if (DEBUG_INSTALL) {
Slog.d(TAG,
"replaceNonSystemPackageLI: new=" + parsedPackage + ", old="
+ oldPackage);
}
}
} else { // 新软件包的装置
ps = null;
disabledPs = null;
replace = false;
oldPackage = null;
// Remember this for later, in case we need to rollback this install
String pkgName1 = parsedPackage.getPackageName();
...
// 返回
return new PrepareResult(replace, targetScanFlags, targetParseFlags,
oldPackage, parsedPackage, replace /* clearCodeCache */, sysPkg,
ps, disabledPs);
} finally {
res.mFreezer = freezer;
if (shouldCloseFreezerBeforeReturn) {
freezer.close();
}
}
}
接下来扫描 apk 的代码十分长,这儿就不列举了,只大概说一下它的作用吧。扫描的首要作用便是为了获取 PackageParser.Package 和 PackageSetting。然后经过 reconcilePackages 对成果进行谐和。最终才是 commitPackagesLocked 的提交。
14.5 commitPackagesLocked
private void commitPackagesLocked(final CommitRequest request) {
// 这个办法中只或许IO失利而导致失利
for (ReconciledPackage reconciledPkg : request.mReconciledPackages.values()) {
...
if (reconciledPkg.mPrepareResult.mReplace) {
AndroidPackage oldPackage = mPm.mPackages.get(packageName);
// 设置更新和装置时间
PackageStateInternal deletedPkgSetting = mPm.snapshotComputer()
.getPackageStateInternal(oldPackage.getPackageName());
reconciledPkg.mPkgSetting
.setFirstInstallTimeFromReplaced(deletedPkgSetting, request.mAllUsers)
.setLastUpdateTime(System.currentTimeMillis());
res.mRemovedInfo.mBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList(
mPm.snapshotComputer(), reconciledPkg.mPkgSetting, request.mAllUsers,
mPm.mSettings.getPackagesLocked());
if (reconciledPkg.mPrepareResult.mSystem) {
// 假如装置的是体系使用
// 移除旧的装置包
removePackageHelper.removePackageLI(oldPackage, true);
if (!disableSystemPackageLPw(oldPackage)) {
// 不需求禁用旧的软件包,直接删去即可
res.mRemovedInfo.mArgs = new FileInstallArgs(
oldPackage.getPath(),
getAppDexInstructionSets(
AndroidPackageUtils.getPrimaryCpuAbi(oldPackage,
deletedPkgSetting),
AndroidPackageUtils.getSecondaryCpuAbi(oldPackage,
deletedPkgSetting)), mPm);
} else {
res.mRemovedInfo.mArgs = null;
}
} else {
try {
// 设置将在调用updateSettingsLI()时被写入
deletePackageHelper.executeDeletePackageLIF(
reconciledPkg.mDeletePackageAction, packageName,
true, request.mAllUsers, false);
} catch (SystemDeleteException e) {
...
}
// 成功地删去了旧包;继续进行替换。
// 更新前先将代码途径的内存复制
PackageSetting ps1 = mPm.mSettings.getPackageLPr(
reconciledPkg.mPrepareResult.mExistingPackage.getPackageName());
if ((reconciledPkg.mInstallArgs.mInstallFlags & PackageManager.DONT_KILL_APP)
== 0) {
Set<String> oldCodePaths = ps1.getOldCodePaths();
if (oldCodePaths == null) {
oldCodePaths = new ArraySet<>();
}
Collections.addAll(oldCodePaths, oldPackage.getBaseApkPath());
Collections.addAll(oldCodePaths, oldPackage.getSplitCodePaths());
ps1.setOldCodePaths(oldCodePaths);
} else {
ps1.setOldCodePaths(null);
}
...
}
}
// 正式提交
AndroidPackage pkg = commitReconciledScanResultLocked(
reconciledPkg, request.mAllUsers);
...
}
ApplicationPackageManager.invalidateGetPackagesForUidCache();
}
commitPackagesLocked 便是正式提交装置的 apk 了,里边的代码虽然许多,但是做的工作其实很简略猜到。
- 修改装置时间
- 移除旧的装置包
接下来咱们回到 [14.3] 看看装置的四个过程中的最终一个,执行装置指令executePostCommitSteps。
14.6 executePostCommitSteps
[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
private void executePostCommitSteps(CommitRequest commitRequest) {
final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();
for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
...
// 装置后预备app数据
prepareAppDataAfterInstallLIF(pkg);
if (reconciledPkg.prepareResult.clearCodeCache) {
clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
| FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
...
// dex 优化
if (performDexopt) {
...
mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
null /* instructionSets */,
getOrCreateCompilerPackageStats(pkg),
mDexManager.getPackageUseInfoOrDefault(packageName),
dexoptOptions);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
// 告诉BackgroundDexOptService该软件包现已被改变
BackgroundDexOptService.notifyPackageChanged(packageName);
// 告诉观察者广播
notifyPackageChangeObserversOnUpdate(reconciledPkg);
}
waitForNativeBinariesExtraction(incrementalStorages);
}
到现在,咱们装置的 apk 现现已历了如下过程
- 复制到 /data/app
- 各种校验
- 预处理的扫描和解析装置文件
- 移除了旧的装置包
在接下来的 executePostCommitSteps 中,体系则首要做了三件事
- 预备装置后的 App 数据 AppData
- 对装置包做 dex 优化
- 装置完结,告诉观察者,并把装置包显现到桌面中。
14.7 doPostInstall
[frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]
int doPostInstall(int status, int uid) {
if (status == PackageManager.INSTALL_SUCCEEDED) {
cleanUp(move.fromUuid);
} else {
cleanUp(move.toUuid);
}
return status;
}
十五 总结
到这儿,PMS 装置使用的流程咱们就整理完毕了,最终再来做一个简略的概括总结。
PMS 作为 Android 中的包办理服务,装置使用的流程如下。
- 首要发动一个装置使用的界面 Activity。用户可用在这个界面挑选是否装置,而且这个界面还有此刻装置的使用的信息(图标,姓名,权限等等)。
- 假如用户挑选赞同,就会经过 PMS 创立一个 session,这个 session 的 id 是体系仅有的。
- PMS 会经过 Handler 的消息机制,最终调用到 handleInstall 这个函数,它便是使用装置的开端。
- 使用的装置会分为两种,一种是 Stage 为 true,这种会在下次发动发动时装置,一种则是普通使用的装置。
- 装置的流程大致分为以下几步
- 校验装置包
- 复制 apk
- 扫描 apk 解析装置文件
- 对装置包做 dex 优化
- 告诉观察者。
最终用一张全体的UML图结束吧。