Android应用安装流程(AndroidU)
一:背景应用下载安装是用户很常用的场景之一,如果有两个同范例的应用A和B,功能、UI相差不多,但是A应用安装必要3s,B应用安装只必要1s,那么无疑B应用会更受用户欢迎。怎样减少应用安装时间,那就必须要了解应用安装过程中必要做哪些事变,耗时点在哪里。
那么应用安装过程中体系到底做了哪些事变呢,且看下文。
二:安装方式
应用安装有4种方式
1. 体系预置应用:包罗体系应用和预置应用。在开机过程中完成安装,静默安装,没有安装界面,用户无法感知。
2. 使用adb安装:adb install A.apk,静默安装,没有安装界面,如果安装失败会有具体的报错信息显示。
3. 应用商店下载安装:静默安装,没有安装界面,下载完成后会自动安装。
4. 用户点击存储里的apk安装包进行安装:有安装界面及安装进度显示,必要触发安装apk动作的应用有安装权限。
下面将从第四种安装方式来剖析安装流程
三:PackageInstaller安装应用
当用户点击存储里的apk安装包时,体系辨认到这是一个apk,会启动PackageInstaller进程的InstallStart Activity来触发apk的安装流程
3.1 InstallStart.onCreate
InstallStart启动后,会根据传进来的intent判定是否是install范例的session,如果是则启动PackageInstallerActivity来显示安装界面。
//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
protected void onCreate(@Nullable Bundle savedInstanceState) {
...
//这里传入的action是android.content.pm.action.CONFIRM_INSTALL,所以isSessionInstall为true
final boolean isSessionInstall =
PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL.equals(intent.getAction())
|| PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction());
...
Intent nextActivity = new Intent(intent);
...
//isSessionInstall为true,启动PackageInstallerActivity
if (isSessionInstall) {
nextActivity.setClass(this, PackageInstallerActivity.class);
}
...
if (nextActivity != null) {
try {
startActivity(nextActivity);
} catch (SecurityException e) {
...
}
}
finish();
} 3.2 PackageInstallerActivity.bindUi
PackageInstallerActivity启动后,会先解析被安装应用的AndroidManifest,获取应用的安装名和icon等信息,生存在AppSinppet对象中,再初始化安装界面,如果安装应用有安装权限,那么这时用户就可以看到安装界面了
https://i-blog.csdnimg.cn/direct/2cad2afd0c194d1a8a45fc77860a18dc.png
//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
protected void onCreate(Bundle icicle) {
...
if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(action)) {
final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID,
-1 /* defaultValue */);
final SessionInfo info = mInstaller.getSessionInfo(sessionId);
String resolvedPath = info != null ? info.getResolvedBaseApkPath() : null;
...
//初始化mSessionId和packageSource
mSessionId = sessionId;
packageSource = Uri.fromFile(new File(resolvedPath));
...
}
...
final boolean wasSetUp = processAppSnippet(packageSource);
...
}
private boolean processAppSnippet(@NonNull Object source) {
if (source instanceof Uri) {
return processPackageUri((Uri) source);
}
...
}
private boolean processPackageUri(final Uri packageUri) {
...
switch (scheme) {
case ContentResolver.SCHEME_FILE: {
File sourceFile = new File(packageUri.getPath());
//PackageUtil解析应用的AndroidManifest,获取应用的包名、版本号等信息
mPkgInfo = PackageUtil.getPackageInfo(this, sourceFile,
PackageManager.GET_PERMISSIONS);
...
//获取应用的安装名和icon,保存在AppSnippet对象中
mAppSnippet = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile);
} break;
}
}
protected void onResume() {
...
if (mAppSnippet != null) {
//初始化弹框UI
bindUi();
//检查是否有安装权限,如果有则初始化安装UI
checkIfAllowedAndInitiateInstall();
}
...
} 3.3 PackageInstallerActivity.checkIfAllowedAndInitiateInstall
如果安装应用的应用没有安装未知泉源的权限,会启动提供用户开启允许安装来自未知应用的Dialog,用户点击Settings按钮,会注册UnknownSourcesListener的监听回调并启动体系-设置模块内里的Install unknown apps界面
https://i-blog.csdnimg.cn/direct/ef8104523ce641cfa8ca35d9d92ee26c.png
https://i-blog.csdnimg.cn/direct/a271260c7f4e47cfa388b6757e004df3.png
//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
private void checkIfAllowedAndInitiateInstall() {
...
//检查应用是否有安装未知应用权限
handleUnknownSources();
}
private void handleUnknownSources() {
...
//获取应用的AppOps权限,默认是MODE_DEFAULT
final int appOpMode = mAppOpsManager.noteOpNoThrow(...);
switch (appOpMode) {
case AppOpsManager.MODE_DEFAULT:
mAppOpsManager.setMode(appOpStr, mOriginatingUid,
mOriginatingPackage, AppOpsManager.MODE_ERRORED);
case AppOpsManager.MODE_ERRORED:
showDialogInner(DLG_EXTERNAL_SOURCE_BLOCKED);
break;
...
}
}
private void showDialogInner(int id) {
...
//根据传进来的id,判断要创建哪种dialog
DialogFragment newDialog = createDialog(id);
...
}
private void showDialogInner(int id) {
...
//根据传进来的id,判断要创建哪种dialog
DialogFragment newDialog = createDialog(id);
...
}
private DialogFragment createDialog(int id) {
switch (id) {
...
case DLG_EXTERNAL_SOURCE_BLOCKED:
return ExternalSourcesBlockedDialog.newInstance(mOriginatingPackage);
...
}
...
}
//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.ExternalSourcesBlockedDialog.java
public static class ExternalSourcesBlockedDialog extends AppErrorDialog {
...
protected Dialog createDialog(@NonNull CharSequence argument) {
...
try {
...
return new AlertDialog.Builder(activity)
...
.setPositiveButton(R.string.external_sources_settings,
(dialog, which) -> {
...
try {
//注册UnknownSourcesListener的监听回调
activity.register(activity.new UnknownSourcesListener());
//启动Settings里面的Install unknown apps界面,由用户选择是否要打开Allow from this source开关。开关打开后,会调用UnknownSourcesListener的onOpChanged回调函数
activity.startActivityForResult(settingsIntent,
REQUEST_TRUST_EXTERNAL_SOURCE);
}
...
})
.setNegativeButton(R.string.cancel,
(dialog, which) -> activity.finish())
.create();
}
...
}
} 3.4 PackageInstallerActivity.initiateInstall
当用户在设置模块的允许安装未知泉源界面点击允许时,PackageInstallerActivity会收到onOpChanged的回调,再次启动PackageInstallerActivity,初始化安装UI
https://i-blog.csdnimg.cn/direct/e3acfef9fb184682bc9fa0b696059fa5.png
//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.UnknownSourcesListener.java
private class UnknownSourcesListener implements AppOpsManager.OnOpChangedListener {
@Override
public void onOpChanged(String op, String packageName) {
...
//解绑监听
unregister(this);
...
new Handler(Looper.getMainLooper()).postDelayed(() -> {
if (!isDestroyed()) {
//启动PackageInstallerActivity
startActivity(getIntent().addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT));
}
}, 500);
}
}
//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
private void checkIfAllowedAndInitiateInstall() {
if (mAllowUnknownSources || !isInstallRequestFromUnknownSource(getIntent())) {
//初始化安装UI
initiateInstall();
}
...
}
//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
private void initiateInstall() {
...
startInstallConfirm();
}
//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
private void startInstallConfirm() {
TextView viewToEnable;
if (mAppInfo != null) {
...
} else {
// This is a new application with no permissions.
viewToEnable = requireViewById(R.id.install_confirm_question);
}
viewToEnable.setVisibility(View.VISIBLE);
mEnableOk = true;
//设置mOk为可点击的状态
mOk.setEnabled(true);
mOk.setFilterTouchesWhenObscured(true);
}
//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
private void bindUi() {
...
mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
(ignored, ignored2) -> {
if (mOk.isEnabled()) {
if (mSessionId != -1) {
setActivityResult(RESULT_OK);
finish();
}
...
}
}, null);
...
} 3.5 PackageInstallerSession.handleInstall
当用户点击Install按钮后,安装界面的Dialog会消失,终极会调用到PackageInstallerSession的handleInstall函数来触发安装流程。
https://i-blog.csdnimg.cn/direct/48f34a308edd4354adaafa14b0624d9b.png
//frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
public void finish() {
if (mSessionId != -1) {
if (mActivityResultCode == Activity.RESULT_OK) {
mInstaller.setPermissionsResult(mSessionId, true);
}
...
}
...
}
//frameworks/base/core/java/android/content/pm/PackageInstaller.java
public void setPermissionsResult(int sessionId, boolean accepted) {
try {
mInstaller.setPermissionsResult(sessionId, accepted);
}
...
}
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
public void setPermissionsResult(int sessionId, boolean accepted) {
//检查应用是否有INSTALL_PACKAGES权限
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG);
synchronized (mSessions) {
PackageInstallerSession session = mSessions.get(sessionId);
if (session != null) {
session.setPermissionsResult(accepted);
}
}
}
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
void setPermissionsResult(boolean accepted) {
...
if (accepted) {
...
//isCommitted()为true,这里会发送MSG_INSTALL类型的message
root.mHandler.obtainMessage(
isCommitted() ? MSG_INSTALL : MSG_PRE_APPROVAL_REQUEST).sendToTarget();
}
...
}
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
...
case MSG_INSTALL:
//触发安装流程
handleInstall();
break;
...
}
...
}
};
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
private void handleInstall() {
...
//校验
verify();
} 3.6 PackageInstallerSession.verify
安装第一步:校验。
[*]解析apk,并把apk信息生存在PackageLite对象中
[*]盘算安装进度条
[*]提取native lib库
[*]检查是新安装还是升级安装还是降级安装
[*]进行完备性验证
[*]进行签名验证
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
private void verify() {
try {
List<PackageInstallerSession> children = getChildSessions();
if (isMultiPackage()) {
...
} else {
//准备继承的文件
prepareInheritedFiles();
//解析apk和native库
parseApkAndExtractNativeLibraries();
}
verifyNonStaged();
} catch (PackageManagerException e) {
...
}
}
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
private void prepareInheritedFiles() throws PackageManagerException {
//新安装的应用,mode不等于MODE_INHERIT_EXISTING,会直接return
if (isApexSession() || params.mode != SessionParams.MODE_INHERIT_EXISTING) {
return;
}
}
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
private void parseApkAndExtractNativeLibraries() throws PackageManagerException {
synchronized (mLock) {
...
//
if (!isApexSession()) {
...
//解析apk,并把apk信息保存在PackageLite对象中返回
result = getOrParsePackageLiteLocked(stageDir, /* flags */ 0);
}
...
if (result != null) {
...
if (!isApexSession()) {
synchronized (mProgressLock) {
mInternalProgress = 0.5f;
//计算安装进度条
computeProgressLocked(true);
}
//提取native lib库
extractNativeLibraries(
mPackageLite, stageDir, params.abiOverride, mayInheritNativeLibs());
}
}
}
}
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
private void verifyNonStaged()
throws PackageManagerException {
synchronized (mLock) {
markStageDirInUseLocked();
}
mSessionProvider.getSessionVerifier().verify(this, (error, msg) -> {
mHandler.post(() -> {
if (dispatchPendingAbandonCallback()) {
// No need to continue if abandoned
return;
}
Log.d(TAG, "verifyNonStaged error : " + error);
if (error == INSTALL_SUCCEEDED) {
onVerificationComplete();
} else {
onSessionVerificationFailure(error, msg);
}
});
});
}
//frameworks/base/services/core/java/com/android/server/pm/PackageSessionVerifier.java
public void verify(PackageInstallerSession session, Callback callback) {
mHandler.post(() -> {
try {
...
if (session.isMultiPackage()) {
...
} else {
//检查是否允许更新Apex
checkApexUpdateAllowed(session);
//检查是否是重新启动的Apex会话
checkRebootlessApex(session);
//检查Apex签名
checkApexSignature(session);
}
//校验apk
verifyAPK(session, callback);
} catch (PackageManagerException e) {
...
}
});
}
//frameworks/base/services/core/java/com/android/server/pm/PackageSessionVerifier.java
private void verifyAPK(PackageInstallerSession session, Callback callback)
throws PackageManagerException {
...
verifyingSession.verifyStage();
}
//frameworks/base/services/core/java/com/android/server/pm/VerifyingSession.java
public void verifyStage() {
...
mPm.mHandler.post(this::start);
}
//frameworks/base/services/core/java/com/android/server/pm/VerifyingSession.java
private void start() {
...
//开始验证
handleStartVerify();
//返回结果
handleReturnCode();
...
}
//frameworks/base/services/core/java/com/android/server/pm/VerifyingSession.java
public void handleStartVerify() {
...
//校验是升级还是降级
Pair<Integer, String> ret = mInstallPackageHelper.verifyReplacingVersionCode(
pkgLite, mRequiredInstalledVersionCode, mInstallFlags);
...
if (!mOriginInfo.mExisting) {
if (!isApex()) {
//完整性和签名验证
sendApkVerificationRequest(pkgLite);
}
if ((mInstallFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
//防回滚验证
sendEnableRollbackRequest();
}
}
}
//frameworks/base/services/core/java/com/android/server/pm/VerifyingSession.java
private void sendApkVerificationRequest(PackageInfoLite pkgLite) {
...
//进行完整性验证,验证metadata、versioncode、签名等信息是否完整
sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
//进行签名验证
sendPackageVerificationRequest(
verificationId, pkgLite, verificationState);
...
}
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
private void onVerificationComplete() {
...
install();
} 3.7 InstallingSession.copyApk
安装第二步:拷贝
[*]拷贝codeFile
[*]拷贝native lib库
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
private CompletableFuture<Void> install() {
List<CompletableFuture<InstallResult>> futures = installNonStaged();
...
}
//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
private List<CompletableFuture<InstallResult>> installNonStaged() {
try {
...
//创建安装会话
final InstallingSession installingSession = createInstallingSession(future);
if (isMultiPackage()) {
...
} else if (installingSession != null) {
installingSession.installStage();
}
...
} catch (PackageManagerException e) {
...
}
}
//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
public void installStage() {
...
mPm.mHandler.post(this::start);
}
//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
private void start() {
...
InstallRequest installRequest = new InstallRequest(this);
handleStartCopy(installRequest);
handleReturnCode(installRequest);
...
}
//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
private void handleStartCopy(InstallRequest request) {
...
if (!mOriginInfo.mStaged && pkgLite.recommendedInstallLocation
== InstallLocationUtils.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
//如果剩余存储空间很少,不够安装使用,则做一次清理cache的动作
pkgLite.recommendedInstallLocation = mPm.freeCacheForInstallation(
pkgLite.recommendedInstallLocation, mPackageLite,
mOriginInfo.mResolvedPath, mPackageAbiOverride, mInstallFlags);
}
//更新mInstallFlags
mRet = overrideInstallLocation(pkgLite.packageName, pkgLite.recommendedInstallLocation,
pkgLite.installLocation);
...
}
//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
private void handleReturnCode(InstallRequest installRequest) {
processPendingInstall(installRequest);
}
//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
private void processPendingInstall(InstallRequest installRequest) {
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
//拷贝apk
mRet = copyApk(installRequest);
}
...
if (mParentInstallingSession != null) {
...
} else {
//异步进行安装工作
mPm.mHandler.post(() -> processInstallRequests(
mRet == PackageManager.INSTALL_SUCCEEDED /* success */,
Collections.singletonList(installRequest)));
}
}
//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
private int copyApk(InstallRequest request) {
if (mMoveInfo == null) {
return copyApkForFileInstall(request);
} else {
...
}
}
//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
private int copyApkForFileInstall(InstallRequest request) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
try {
...
//拷贝codeFile
ret = PackageManagerServiceUtils.copyPackage(
mOriginInfo.mFile.getAbsolutePath(), request.getCodeFile());
...
try {
//拷贝native lib库
ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
request.getAbiOverride(), isIncremental);
...
}
...
}
...
} 3.8 AppDataHelper.prepareAppDataPostCommitLIF
安装第三步:安装应用
[*]解析apk,把结果生存在ParsedPakcage中
[*]将包重定名为终极存放位置
[*]冻结进程
[*]判定包是否有用
[*]检索包名判定是否合法
[*]调用Installd进程进行安装工作
//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
private void processInstallRequests(boolean success, List<InstallRequest> installRequests) {
...
processApkInstallRequests(success, installRequests);
}
//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java
private void processApkInstallRequests(boolean success, List<InstallRequest> installRequests) {
if (!success) {
...
} else {
mInstallPackageHelper.installPackagesTraced(installRequests);
for (InstallRequest request : installRequests) {
request.onInstallCompleted();
doPostInstall(request);
}
}
for (InstallRequest request : installRequests) {
mInstallPackageHelper.restoreAndPostInstall(request);
}
}
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
void installPackagesTraced(List<InstallRequest> requests) {
synchronized (mPm.mInstallLock) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
installPackagesLI(requests);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
}
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
private void installPackagesLI(List<InstallRequest> requests) {
...
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
for (InstallRequest request : requests) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
...
preparePackageLI(request);
} catch (PrepareFailure prepareFailure) {
...
} finally {
...
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
...
try {
request.onScanStarted();
final ScanResult scanResult = scanPackageTracedLI(...);
}
}
...
synchronized (mPm.mLock) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
//对多个apk进行一致性处理
reconciledPackages = ReconcilePackageUtils.reconcilePackages(...);
} catch (ReconcileFailure e) {
...
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
commitPackagesLocked(reconciledPackages, mPm.mUserManager.getUserIds());
success = true;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
executePostCommitStepsLIF(reconciledPackages);
}
}
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
private void preparePackageLI(InstallRequest request) throws PrepareFailure {
...
//解析apk,主要是解析apk的AndroidManifest.xml,并把结果保存在ParsedPackage中
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final ParsedPackage parsedPackage;
try (PackageParser2 pp = mPm.mInjector.getPreparingPackageParser()) {
parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
} catch (PackageManagerException e) {
...
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
...
//如果有静态共享库,则重命名静态共享库的名字,拼接上应用包名
if (parsedPackage.isStaticSharedLibrary()) {
// Static shared libraries have synthetic package names
PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage);
}
...
synchronized (mPm.mLock) {
//如果是安装已有应用,进行sdk和persistent判断
if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
...
}
//从现有PackageSetting列表中尝试通过包名获取PackageSetting,安装新应用时,ps为空
PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
PackageSetting signatureCheckPs = ps;
...
//检查申明权限的合法性,权限是否已经被其他应用申明
final int numGroups = ArrayUtils.size(parsedPackage.getPermissionGroups());
for (int groupNum = 0; groupNum < numGroups; groupNum++) {
...
}
...
//在PermissionManagerService进行权限兼容性的检查
final int n = ArrayUtils.size(parsedPackage.getPermissions());
for (int i = n - 1; i >= 0; i--) {
...
}
...
}
...
if (!isApex) {
//将包重命名为最终存放位置
doRenameLI(request, parsedPackage);
...
} else {
...
}
//应用安装期间,冻结进程
final PackageFreezer freezer =
freezePackageForInstall(pkgName, UserHandle.USER_ALL, installFlags,
"installPackageLI", ApplicationExitInfo.REASON_PACKAGE_UPDATED);
...
try {
...
//更新信息到InstallRequest
request.setPrepareResult(replace, targetScanFlags, targetParseFlags,
oldPackage, parsedPackage, replace /* clearCodeCache */, sysPkg,
ps, disabledPs);
}
...
}
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
private ScanResult scanPackageTracedLI(...) throws PackageManagerException {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
try {
return scanPackageNewLI(...);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
private ScanResult scanPackageNewLI(...)
throws PackageManagerException {
...
synchronized (mPm.mLock) {
//判断包是否是有效的
assertPackageIsValid(parsedPackage, parseFlags, newScanFlags);
final ScanRequest request = new ScanRequest(...);
//检索包名,判断合法性
return ScanPackageUtils.scanPackageOnlyLI(request, mPm.mInjector, mPm.mFactoryTest,
currentTime);
}
}
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
private void commitPackagesLocked(List<ReconciledPackage> reconciledPackages,
@NonNull int[] allUsers) {
for (ReconciledPackage reconciledPkg : reconciledPackages) {
...
//非第一次安装
if (installRequest.isInstallReplace()) {...}
...
//更新应用信息到PackageSetting中
AndroidPackage pkg = commitReconciledScanResultLocked(reconciledPkg, allUsers);
//更新应用信息到PMS.Settings中
updateSettingsLI(pkg, allUsers, installRequest);
...
}
}
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
private void executePostCommitStepsLIF(List<ReconciledPackage> reconciledPackages) {
for (ReconciledPackage reconciledPkg : reconciledPackages) {
...
//安装应用
mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0);
...
}
//frameworks/base/services/core/java/com/android/server/pm/AppDataHelper.java
public void prepareAppDataPostCommitLIF(AndroidPackage pkg, int previousAppId) {
...
for (UserInfo user : umInternal.getUsers(false /*excludeDying*/)) {
final int flags;
//判断安装路径
if (StorageManager.isUserKeyUnlocked(user.id)
&& smInternal.isCeStoragePrepared(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
} else if (umInternal.isUserRunning(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE;
} else {
continue;
}
if (ps.getInstalled(user.id)) {
//准备应用数据
prepareAppData(batch, pkg, previousAppId, user.id, flags).thenRun(() -> {
...
});
}
}
//以阻塞方式执行此批收集的所有待处理操作
executeBatchLI(batch);
} 3.9 ArtManagerLocal.dexoptPackage
安装第四步:dex优化
调用AndroidRuntime进程dex优化工作
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
private void executePostCommitStepsLIF(List<ReconciledPackage> reconciledPackages) {
for (ReconciledPackage reconciledPkg : reconciledPackages) {
...
//安装应用
mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0);
...
//判断是否需要做dex优化
final boolean performDexopt =
(!instantApp || android.provider.Settings.Global.getInt(
mContext.getContentResolver(),
android.provider.Settings.Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
&& !pkg.isDebuggable()
&& (!onIncremental)
&& dexoptOptions.isCompilationEnabled()
&& !isApex;
//需要做dex优化
if (performDexopt) {
...
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
...
//使用AndroidRuntime服务
if (useArtService()) {
PackageManagerLocal packageManagerLocal =
LocalManagerRegistry.getManager(PackageManagerLocal.class);
try (PackageManagerLocal.FilteredSnapshot snapshot =
packageManagerLocal.withFilteredSnapshot()) {
DexoptParams params =
dexoptOptions.convertToDexoptParams(0 /* extraFlags */);
//在ART里做dex优化
DexoptResult dexOptResult = DexOptHelper.getArtManagerLocal().dexoptPackage(
snapshot, packageName, params);
installRequest.onDexoptFinished(dexOptResult);
}
} else {
...
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
...
} 3.10 PackageManagerService.finishPackageInstall
应用安装完成后,会发送ACTION_PACKAGE_ADDED/ACTION_PACKAGE_REPLACED/ACTION_PACKAGE_CHANGED广播,并触发PackageInstallObserver的onPackageInstalled函数回调
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
public void restoreAndPostInstall(InstallRequest request) {
...
if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED && doRestore) {
//解冻进程
request.closeFreezer();
//对给定的Request进行BackupManager还原
doRestore = performBackupManagerRestore(userId, token, request);
}
...
}
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
private boolean performBackupManagerRestore(int userId, int token, InstallRequest request) {
...
IBackupManager iBackupManager = mInjector.getIBackupManager();
if (iBackupManager != null) {
...
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
try {
if (iBackupManager.isUserReadyForBackup(userId)) {
iBackupManager.restoreAtInstallForUser(
userId, request.getPkg().getPackageName(), token);
} else {
...
}
}
...
}
...
}
//frameworks/base/services/backup/java/com/android/server/backup/BackupManagerService.java
public void restoreAtInstallForUser(int userId, String packageName, int token)
throws RemoteException {
if (isUserReadyForBackup(userId)) {
restoreAtInstall(userId, packageName, token);
}
}
//frameworks/base/services/backup/java/com/android/server/backup/BackupManagerService.java
public void restoreAtInstall(@UserIdInt int userId, String packageName, int token) {
UserBackupManagerService userBackupManagerService =
getServiceForUserIfCallerHasPermission(userId, "restoreAtInstall()");
if (userBackupManagerService != null) {
userBackupManagerService.restoreAtInstall(packageName, token);
}
}
//frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java
public void restoreAtInstall(String packageName, int token) {
...
boolean skip = false;
//这里获取到的restoreSet值是0
long restoreSet = getAvailableRestoreToken(packageName);
...
if (restoreSet == 0) {
skip = true;
}
...
if (skip) {
...
try {
mPackageManagerBinder.finishPackageInstall(token, false);
} catch (RemoteException e) { /* can't happen */ }
}
}
//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
void finishPackageInstall(int token, boolean didLaunch) {
...
final Message msg = mHandler.obtainMessage(PackageManagerService.POST_INSTALL, token,
didLaunch ? 1 : 0);
mHandler.sendMessage(msg);
}
//frameworks/base/services/core/java/com/android/server/pm/PackageHandler.java
void doHandleMessage(Message msg) {
switch (msg.what) {
case POST_INSTALL: {
...
request.closeFreezer();
request.runPostInstallRunnable();
if (!request.isInstallExistingForUser()) {
mInstallPackageHelper.handlePackagePostInstall(request, didRestore);
}
...
} break;
}
}
//frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java
void handlePackagePostInstall(InstallRequest request, boolean launchedForRestore) {
...
final boolean succeeded = request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED;
...
if (succeeded) {
//没有静态库
if (request.getPkg().getStaticSharedLibraryName() == null) {
...
} else if (!ArrayUtils.isEmpty(request.getLibraryConsumers())) {//有静态库
...
for (int i = 0; i < request.getLibraryConsumers().size(); i++) {
//发送package changed广播
mPm.sendPackageChangedBroadcast(...);
}
}
...
...
final boolean deferInstallObserver = succeeded && update;
if (deferInstallObserver) {
...
} else {
//触发安装完成的回调
mPm.notifyInstallObserver(request);
}
...
}
//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
void sendPackageChangedBroadcast(...) {
...
mHandler.post(() -> mBroadcastHelper.sendPackageChangedBroadcast(
packageName, dontKillApp, componentNames, packageUid, reason, userIds,
instantUserIds, broadcastAllowList));
}
//frameworks/base/services/core/java/com/android/server/pm/BroadcastHelper.java
public void sendPackageChangedBroadcast(...) {
...
sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, null, null,
userIds, instantUserIds, broadcastAllowList, null /* filterExtrasForReceiver */,
null /* bOptions */);
}
//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
void notifyInstallObserver(InstallRequest request) {
if (request.getObserver() != null) {
try {
Bundle extras = extrasForInstallResult(request);
//触发安装完成的回调
request.getObserver().onPackageInstalled(request.getName(),
request.getReturnCode(), request.getReturnMsg(), extras);
} catch (RemoteException e) {
Slog.i(TAG, "Observer no longer exists.");
}
}
}
四:小结
4.1 怎样在日志中检察应用安装各个阶段的耗时
把PMS内里的DEBUG_INSTALL改为true,日志中搜索PackageManager关键字,即可看到应用安装流程耗时
4.2 怎样优化应用安装速率
[*]减少应用安装包巨细,减少应用拷贝时间:去掉不须要的资源文件;如需须要不引用三方库,克制重复库的引用;动态加载.so文件;小图片使用矢量图等
[*]提前做dex优化:实用于体系预置应用,在编译时做dex优化,在应用安装时节省dex优化时间
[*]对Installd/dex2oat绑大核:原理相同,绑大核可以使Installd和dex2oat实行更快,节省安装时间。但是绑大核可能会出现抢占前台进程的CPU大核的使用,造成前台进程卡顿等现象,必要做完备评估、测试后再决定是否上此方案
4.3 怎样监听应用是否安装乐成以及何时安装乐成
可以通过PackageInstallObserver来监听安装是否乐成以及何时安装乐成。也可通过接收ACTION_PACKAGE_ADDED/ACTION_PACKAGE_REPLACED/ACTION_PACKAGE_CHANGED等体系广播来实现此功能,不外广播及时性较差。
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 (returnCode == INSTALL_SUCCEEDED) {
future.complete(new InstallResult(PackageInstallerSession.this, extras));
} else {
future.completeExceptionally(new PackageManagerException(returnCode, msg));
}
}
};
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]