2014世界杯决赛_国足进过世界杯吗 - hntink.com

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对象中,再初始化安装界面,如果安装应用有安装权限,那么这时用户就可以看到安装界面了

//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界面

//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

//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函数来触发安装流程。

//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 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 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 install() {

List> futures = installNonStaged();

...

}

//frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java

private List> 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 installRequests) {

...

processApkInstallRequests(success, installRequests);

}

//frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java

private void processApkInstallRequests(boolean success, List 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 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 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 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 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 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));

}

}

};

邱立东脂肪填充怎么样?改良脸型效果好不好?技术优势大pk
小米手机recovery模式退出步骤:详细教程及简易操作指南
2025-05-16 11:31:49

友情链接