❤️Android 从源码解读 Apk 的安装过程 ❤️
Posted 帅次
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了❤️Android 从源码解读 Apk 的安装过程 ❤️相关的知识,希望对你有一定的参考价值。
目录
dispatchStreamValidateAndCommit()
handleStreamValidateAndCommit()
PackageManagerServiceUtils.copyPackage()
prepareAppDataAfterInstallLIF()
App安装过程
源码:Android SDK 30
当我们点击某一个 App 安装包进行安装时,首先会弹出一个系统界面指示我们进行安装操作。这个界面是 Android Framework 中预置的一个 Activity>PackageInstallerActivity.java。
PackageInstallerActivity
frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
/**
* This activity is launched when a new application is installed via side loading
* The package is first parsed and the user is notified of parse errors via a dialog.
* If the package is successfully parsed, the user is notified to turn on the install unknown
* applications setting. A memory check is made at this point and the user is notified of out
* of memory conditions if any. If the package is already existing on the device,
* a confirmation dialog (to replace the existing package) is presented to the user.
* Based on the user response the package is then installed by launching InstallAppConfirm
* sub activity. All state transitions are handled in this activity
*/
public class PackageInstallerActivity extends AlertActivity {
...
}
看到 Activity 当然是先从 onCreate() 开始了
onCreat()
public class PackageInstallerActivity extends AlertActivity {
@Override
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);
}
//mPm = PackageManagerService
mPm = getPackageManager();
//mIpm = IPackageManager
//将原始接口返回给包管理器。
mIpm = AppGlobals.getPackageManager();
//AppOpsManager 涵盖了从帮助运行时权限访问控制和跟踪到电池消耗跟踪的各种功能。
mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
//提供在设备上安装、升级和删除应用程序的能力。
mInstaller = mPm.getPackageInstaller();
//在多用户系统上管理用户和用户详细信息
mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
final Intent intent = getIntent();
...
//安装包Uri
final Uri packageUri;
if (PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction())) {
//获取android.content.pm.extra.SESSION_ID
final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1);
//获取安装Session的详细信息
final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId);
if (info == null || !info.sealed || info.resolvedBaseCodePath == null) {
//获取SessionInfo失败退出安装
finish();
return;
}
mSessionId = sessionId;
packageUri = Uri.fromFile(new File(info.resolvedBaseCodePath));
mOriginatingURI = null;
mReferrerURI = null;
} else {
mSessionId = -1;
packageUri = intent.getData();
mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
}
if (packageUri == null) {
//获取packageUri失败退出安装
setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI);
finish();
return;
}
//解析 Uri 并为此包设置安装程序。
boolean wasSetUp = processPackageUri(packageUri);
if (!wasSetUp) {
return;
}
}
}
在 onCreate() 方法中,首先执行一些初始化操作,获取PackageManager和PackageInstaller、UserManager等对象,根据当前Intent的信息最一些逻辑判断并弹出消息弹窗,然后获取一些安装包信息。接下来咱们安装 Activity 的生命周期往下看 onStart() 没有重写,咱继续往下看
onResume()
@Override
protected void onResume() {
super.onResume();
//processPackageUri已拿到mAppSnippet
if (mAppSnippet != null) {
// 在禁用确定按钮的情况下加载虚拟布局,直到我们覆盖此布局
// 开始安装确认
bindUi();
// 检查是否允许安装包,如果允许则启动安装。
//如果不允许显示适当的对话框。
checkIfAllowedAndInitiateInstall();
}
if (mOk != null) {
mOk.setEnabled(mEnableOk);
}
}
bindUi()
private void bindUi() {
...
mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
(ignored, ignored2) -> {
if (mOk.isEnabled()) {
...
startInstall();
...
}
}, null);
...
}
这里点击安装按钮进去 startInstall() 方法,失败的情况咱就不看了,继续往下走着。
startInstall()
private void startInstall() {
// 启动子Activity,安装应用程序
Intent newIntent = new Intent();
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
mPkgInfo.applicationInfo);
newIntent.setData(mPackageURI);
newIntent.setClass(this, InstallInstalling.class);
...
newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
startActivity(newIntent);
finish();
}
startInstall 调用即使启用了一个新的Activity–>InstallInstalling。会把安装包的信息通过 Intent 传递到 InstallInstalling 这个 Activity。
InstallInstalling
frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
/**
* Send package to the package manager and handle results from package manager. Once the
* installation succeeds, start {@link InstallSuccess} or {@link InstallFailed}.
* <p>This has two phases: First send the data to the package manager, then wait until the package
* manager processed the result.</p>
*/
public class InstallInstalling extends AlertActivity {
...
}
在这个页面点击安装时,InstallInstalling 的作用主要是向 PMS 发送包信息以及处理回调。 这有两个阶段:
-
首先将数据发送给 PackageManager ;
-
等待 PackageManager 处理结果(InstallSuccess 或 InstallFailed)。
看到 Activity 当然是先从 onCreate() 开始了
onCreat()
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ApplicationInfo appInfo = getIntent()
.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
//要安装的包的 URI
mPackageURI = getIntent().getData();
if ("package".equals(mPackageURI.getScheme())) {
try {
//注释1:安装现有包
getPackageManager().installExistingPackage(appInfo.packageName);
//安装成功页面
launchSuccess();
} catch (PackageManager.NameNotFoundException e) {
//安装失败页面
launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
} else {
//注释2:没有现有包
//根据 mPackageURI 创建一个对应的 File
final File sourceFile = new File(mPackageURI.getPath());
//显示应用信息 icon,应用名
PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
mAlert.setIcon(as.icon);
...
if (savedInstanceState != null) {
//咱们第一次仅savedInstanceState==null
//安装包的会话 ID
mSessionId = savedInstanceState.getInt(SESSION_ID);
//我们等待的安装事件的 ID
mInstallId = savedInstanceState.getInt(INSTALL_ID);
//重新登记结果;如果结果是在 Activtiy 被销毁时交付的,则可能会立即回调
try {
//添加一个观察者。如果此id已存在事件,请在此调用内回调。
// 向 InstallEventReceiver 注册一个观察者
// InstallEventReceiver 是一个 BroadcastReceiver,可以通过 EventResultPersister 接收到所有的安装事件
// 这里事件会回调给 this::launchFinishBasedOnResult
InstallEventReceiver.addObserver(this, mInstallId,
this::launchFinishBasedOnResult);
} catch (EventResultPersister.OutOfIdsException e) {
// Does not happen
}
} else {
//咱们第一次仅savedInstanceState==null
//创建 SessionParams,它用来携带会话的参数
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
params.setInstallAsInstantApp(false);
...
params.setInstallReason(PackageManager.INSTALL_REASON_USER);
File file = new File(mPackageURI.getPath());
try {
// 对 APK 进行轻量级的解析,并将解析的结果赋值给 SessionParams 相关字段
PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);
params.setAppPackageName(pkg.packageName);
params.setInstallLocation(pkg.installLocation);
params.setSize(
PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
} catch (PackageParser.PackageParserException e) {
...
} catch (IOException e) {
...
}
try {
// 向 InstallEventReceiver 注册一个观察者返回一个新的 mInstallId
// InstallEventReceiver 是一个 BroadcastReceiver,可以通过 EventResultPersister 接收到所有的安装事件
// 这里事件会回调给 this::launchFinishBasedOnResult
mInstallId = InstallEventReceiver
.addObserver(this, EventResultPersister.GENERATE_NEW_ID,
this::launchFinishBasedOnResult);
} catch (EventResultPersister.OutOfIdsException e) {
launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
try {
//PackageInstaller 的 createSession
//方法内部会通过 IPackageInstaller 与 PackageInstallerService进行进程间通信,
//最终调用的是 PackageInstallerService 的 createSession 方法来创建并返回 mSessionId
mSessionId = getPackageManager().getPackageInstaller().createSession(params);
} catch (IOException e) {
launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
}
mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);
//监听会话的更改并更新进度条
mSessionCallback = new InstallSessionCallback();
}
}
NameNotFoundException:当找不到给定的包、应用程序或组件名称时,将引发此异常。
在 onCreate() 方法中,首先执行一些初始化操作,比如获取 mInstallId、mSessionId以及监听回调 mSessionCallback 。接下来看看 onStart() 。
onStart()
@Override
protected void onStart() {
super.onStart();
//设置回话监听回调
getPackageManager().getPackageInstaller().registerSessionCallback(mSessionCallback);
}
onResume()
@Override
protected void onResume() {
super.onResume();
//This is the first onResume in a single life of the activity
if (mInstallingTask == null) {
//PackageInstaller:提供在设备上安装、升级和删除应用程序的能力。
//这包括支持打包为单个“整体”APK 的应用程序或打包为多个“拆分”APK 的应用程序。
PackageInstaller installer = getPackageManager().getPackageInstaller();
//安装Session的详细信息
PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);
if (sessionInfo != null && !sessionInfo.isActive()) {
//创建mInstallingTask并启动
mInstallingTask = new InstallingAsyncTask();
mInstallingTask.execute();
} else {
// 安装完成后我们会收到广播
//mCancelButton不允许点击
mCancelButton.setEnabled(false);
//Activity.setFinishOnTouchOutside():设置此活动在其窗口边界外触摸
setFinishOnTouchOutside(false);
}
}
}
InstallingAsyncTask
/**
* Send the package to the package installer and then register a event result observer that
* will call {@link #launchFinishBasedOnResult(int, int, String)}
*/
private final class InstallingAsyncTask extends AsyncTask<Void, Void,
PackageInstaller.Session> {
volatile boolean isDone;
@Override
protected PackageInstaller.Session doInBackground(Void... params) {
PackageInstaller.Session session;
try {
//打开现有Session
session = getPackageManager().getPackageInstaller().openSession(mSessionId);
} catch (IOException e) {
synchronized (this) {
isDone = true;
notifyAll();
}
return null;
}
//设置暂存此会话的当前进度(0-1z之间)。
session.setStagingProgress(0);
try {
File file = new File(mPackageURI.getPath());
//输入流in
try (InputStream in = new FileInputStream(file)) {
long sizeBytes = file.length();
//打开一个流以将 APK 文件写入会话。
try (OutputStream out = session
.openWrite("PackageInstaller", 0, sizeBytes)) {
byte[] buffer = new byte[1024 * 1024];
//写入文件
while (true) {
int numRead = in.read(buffer);
if (numRead == -1) {
session.fsync(out);
break;
}
if (isCancelled()) {
session.close();
break;
}
//将 APK 文件通过 IO 流的形式写入到 PackageInstaller.Session 中
out.write(buffer, 0, numRead);
if (sizeBytes > 0) {
float fraction = ((float) numRead / (float) sizeBytes);
session.addProgress(fraction);
}
}
}
}
return session;
} catch (IOException | SecurityException e) {
Log.e(LOG_TAG, "Could not write package", e);
session.close();
return null;
} finally {
synchronized (this) {
isDone = true;
notifyAll();
}
}
}
@Override
protected void onPostExecute(PackageInstaller.Session session) {
if (session != null) {
//包已下载好,设置安装提交广播
Intent broadcastIntent = new Intent(BROADCAST_ACTION);
broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
broadcastIntent.setPackage(getPackageName());
broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
InstallInstalling.this,
mInstallId,
broadcastIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
// 调用 PackageInstaller.Session 的 commit 方法,进行安装
session.commit(pendingIntent.getIntentSender());
mCancelButton.setEnabled(false);
setFinishOnTouchOutside(false);
} else {
getPackageManager().getPackageInstaller().abandonSession(mSessionId);
if (!isCancelled()) {
launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
}
}
}
}
其他没啥好看的,咱么看看具体的session.commit
PackageInstaller.commit()
public void commit(@NonNull IntentSender statusReceiver) {
try {
mSession.commit(statusReceiver, false);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
mSession 就是 IPackageInstallerSession 。这说明要通过 IPackageInstallerSession 来进行进程间的通信,最终会调用PackageInstallerSession 的 commit 方法
PackageInstallerSession
frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
...
}
commit()
@Override
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
if (hasParentSessionId()) {
throw new IllegalStateException(
"Session " + sessionId + " is a child of multi-package session "
+ mParentSessionId + " and may not be committed directly.");
}
if (!markAsSealed(statusReceiver, forTransfer)) {
return;
}
//return true 多个包
if (isMultiPackage()) {
...
}
dispatchStreamValidateAndCommit();
}
dispatchStreamValidateAndCommit()
private void dispatchStreamValidateAndCommit() {
// 通过 Handler 处理消息事件
mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget();
}
mHandler()
Handler mHandler = new Handler(looper, mHandlerCallback);
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;
...
}
return true;
}
};
handleStreamValidateAndCommit()
private void handleStreamValidateAndCommit() {
PackageManagerException unrecoverableFailure = null;
// 这将跟踪会话和任何子项是否已通过验证并准备好进入下一安装阶段
boolean allSessionsReady = false;
try {
allSessionsReady = streamValidateAndCommit();
} catch (PackageManagerException e) {
unrecoverableFailure = e;
}
//多包,不是多包直接过
if (isMultiPackage()) {
....
}
if (!allSessionsReady) {
return;
}
// 通过 Handler 处理MSG_INSTALL消息事件
mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
}
mHandler()
Handler mHandler = new Handler(looper, mHandlerCallback);
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
...
case MSG_INSTALL:
handleInstall();
break;
...
}
return true;
}
};
handleInstall()
private void handleInstall() {
...
//return true 会话被再次启用。
if (params.isStaged) {
mStagingManager.commitSession(this);
destroyInternal();
dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null);
return;
}
//安装 APEX 包,则返回 true。
if (isApexInstallation()) {
destroyInternal();
dispatchSessionFinished(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
"APEX packages can only be installed using staged sessions.", null);
return;
}
// 对于 multiPackage 会话,读取锁外的子会话,
// 因为读取持有锁的子会话可能会导致死锁 (b/123391593)。
List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
try {
synchronized (mLock) {
//接下来咱们就看看这个方法。
installNonStagedLocked(childSessions);
}
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
destroyInternal();
dispatchSessionFinished(e.error, completeMsg, null);
}
}
installNonStagedLocked()
@GuardedBy("mLock")
private void installNonStagedLocked(List<PackageInstallerSession> childSessions)
throws PackageManagerException {
final PackageManagerService.ActiveInstallSession installingSession =
makeSessionActiveLocked();
if (installingSession == null) {
return;
}
//return true 多个包
if (isMultiPackage()) {
List<PackageManagerService.ActiveInstallSession> installingChildSessions =
new ArrayList<>(childSessions.size());
...
mPm.installStage(installingChildSessions);
} else {
mPm.installStage(installingSession);
}
}
这里不管不管怎么样都会调用 mPm.installStage(installingChildSessions);
mPm 就是系统服务 PackageManagerService。
PackageManagerService
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender {
}
installStage()
installStage 方法就是正式开始 apk 的安装过程。这个过程包括两大步:
1、拷贝安装包;
2、装载代码。
void installStage(ActiveInstallSession activeInstallSession) {
...
final Message msg = mHandler.obtainMessage(INIT_COPY);
//把之前传入的 sessionParams 安装信息,及其它信息封装成 InstallParams
final InstallParams params = new InstallParams(activeInstallSession);
params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage",
System.identityHashCode(msg.obj));
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(msg.obj));
mHandler.sendMessage(msg);
}
void installStage(List<ActiveInstallSession> children)
throws PackageManagerException {
final Message msg = mHandler.obtainMessage(INIT_COPY);
final MultiPackageInstallParams params =
new MultiPackageInstallParams(UserHandle.ALL, children);
params.setTraceMethod("installStageMultiPackage")
.setTraceCookie(System.identityHashCode(params));
msg.obj = params;
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStageMultiPackage",
System.identityHashCode(msg.obj));
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(msg.obj));
mHandler.sendMessage(msg);
}
MultiPackageInstallParams:多包安装的容器,指的是一起提交的所有安装会话和参数。
这两个方法很详细就是把之前传入的 sessionParams 安装信息及其它信息封装成 InstallParams(MultiPackageInstallParams)。
mHandler 发送的消息 INIT_COPY 从名字上就知道是去初始化复制。
mHandler()
class PackageHandler extends Handler {
PackageHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
try {
doHandleMessage(msg);
} finally {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
}
}
void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj;
if (params != null) {
if (DEBUG_INSTALL) Slog.i(TAG, "init_copy: " + params);
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(params));
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
params.startCopy();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
break;
}
...
}
}
}
HandlerParams.startCopy()
private abstract class HandlerParams {
/** User handle for the user requesting the information or installation. */
private final UserHandle mUser;
String traceMethod;
int traceCookie;
...
final void startCopy() {
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
handleStartCopy();
handleReturnCode();
}
abstract void handleStartCopy();
abstract void handleReturnCode();
}
startCopy(),里面有两个抽象方法,咱只能去找他的实现类 InstallParams 里面的这两个方法了。
InstallParams
class InstallParams extends HandlerParams {
...
/*
* 调用远程方法来获取包信息和安装位置值。
* 如果需要,根据默认策略覆盖安装位置,然后根据安装位置创建安装参数。
*/
public void handleStartCopy() {
int ret = PackageManager.INSTALL_SUCCEEDED;
// 表示文件已下载,不需要再次下载。
if (origin.staged) {
// 设置安装标志位,决定是安装在手机内部存储空间还是 sdcard 中
if (origin.file != null) {
installFlags |= PackageManager.INSTALL_INTERNAL;
} else {
throw new IllegalStateException("Invalid stage location");
}
}
// 判断安装位置
final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
PackageInfoLite pkgLite = null;
//解析给定的包并返回最少的细节。
pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
origin.resolvedPath, installFlags, packageAbiOverride);
if (DEBUG_INSTANT && ephemeral) {
Slog.v(TAG, "pkgLite for install: " + pkgLite);
}
/*
* 如果我们的可用空间太少,请在放弃之前尝试释放缓存。
*/
if (!origin.staged && pkgLite.recommendedInstallLocation
== PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
// TODO: 释放目标设备上的磁盘空间
final StorageManager storage = StorageManager.from(mContext);
//返回给定路径被(Environment.getDataDirectory())认为存储空间不足的可用字节数。
final long lowThreshold = storage.getStorageLowBytes(
Environment.getDataDirectory());
//返回:-1 计算安装包大小有错误
//返回其他:安装包大小。
final long sizeBytes = PackageManagerServiceUtils.calculateInstalledSize(
origin.resolvedPath, packageAbiOverride);
if (sizeBytes >= 0) {
try {
//用于权限提升。
mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);
pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
origin.resolvedPath, installFlags, packageAbiOverride);
} catch (InstallerException e) {
Slog.w(TAG, "Failed to free cache", e);
}
}
/*
* 缓存删除了我们下载安装的文件。
* 用于存储错误
*/
if (pkgLite.recommendedInstallLocation
== PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
pkgLite.recommendedInstallLocation
= PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
}
}
//安装返回码
if (ret == PackageManager.INSTALL_SUCCEEDED) {
//指定推荐的安装位置。 可以是其中之一
//RECOMMEND_INSTALL_INTERNAL 安装在内部存储上,
//RECOMMEND_INSTALL_EXTERNAL 安装在外部媒体上,
//RECOMMEND_FAILED_INSUFFICIENT_STORAGE 用于存储错误,
//或 RECOMMEND_FAILED_INVALID_APK 解析错误。
int loc = pkgLite.recommendedInstallLocation;
...
}
//创建安装参数
final InstallArgs args = createInstallArgs(this);
mVerificationCompleted = true;
mIntegrityVerificationCompleted = true;
mEnableRollbackCompleted = true;
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
final int verificationId = mPendingVerificationToken++;
// 执行安装包验证(除非我们只是简单地移动装包)。
if (!origin.existing) {
...
}
//INSTALL_ENABLE_ROLLBACK 的标志参数以指示应为此安装启用回滚。
if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
// TODO(ruhler) b/112431924: 在“move”的情况下不要这样做?
final int enableRollbackToken = mPendingEnableRollbackToken++;
Trace.asyncTraceBegin(
TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken);
mPendingEnableRollback.append(enableRollbackToken, this);
Intent enableRollbackIntent = new Intent(Intent.ACTION_PACKAGE_ENABLE_ROLLBACK);
enableRollbackIntent.putExtra(
PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN,
enableRollbackToken);
enableRollbackIntent.putExtra(
PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_SESSION_ID,
mSessionId);
enableRollbackIntent.setType(PACKAGE_MIME_TYPE);
enableRollbackIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//允许在启动完成前发送广播。 在早期启动中提交分阶段会话的 apk 部分时需要这样做。 回滚管理器在启动过程中足够早地注册其接收器,以免错过广播。
// 在早期启动中提交分阶段会话的 apk 部分时需要这样做。
// 回滚管理器在启动过程中足够早地注册其接收器,以免错过广播。
enableRollbackIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendOrderedBroadcastAsUser(enableRollbackIntent, UserHandle.SYSTEM,
android.Manifest.permission.PACKAGE_ROLLBACK_AGENT,
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 等待回滚启用的持续时间,以毫秒为单位
long rollbackTimeout = DeviceConfig.getLong(
DeviceConfig.NAMESPACE_ROLLBACK,
PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS);
if (rollbackTimeout < 0) {
rollbackTimeout = DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS;
}
final Message msg = mHandler.obtainMessage(
ENABLE_ROLLBACK_TIMEOUT);
msg.arg1 = enableRollbackToken;
msg.arg2 = mSessionId;
mHandler.sendMessageDelayed(msg, rollbackTimeout);
}
}, null, 0, null, null);
mEnableRollbackCompleted = false;
}
}
mRet = ret;
}
@Override
void handleReturnCode() {
if (mVerificationCompleted
&& mIntegrityVerificationCompleted && mEnableRollbackCompleted) {
//INSTALL_DRY_RUN :installPackage 的标志参数,指示只应验证包而不应安装包。
if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) {
...
}
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
//注释1
mRet = mArgs.copyApk();
}
//注释2
processPendingInstall(mArgs, mRet);
}
}
}
}
注释1:mArgs 其实就是 InstallArgs ,而 InstallArgs 则是通过 createInstallArgs(this); 创建如下代码: createInstallArgs(this)
private InstallArgs createInstallArgs(InstallParams params) {
if (params.move != null) {
//处理现有已安装应用程序移动的逻辑。
return new MoveInstallArgs(params);
} else {
//处理新应用程序安装的逻辑,包括复制和重命名逻辑。
return new FileInstallArgs(params);
}
}
这里createInstallArgs 返回的是 FileInstallArgs 对象。
FileInstallArgs.copyApk()
拷贝部分
class FileInstallArgs extends InstallArgs {
private File codeFile;
private File resourceFile;
// Example topology:
// /data/app/com.example/base.apk
// /data/app/com.example/split_foo.apk
// /data/app/com.example/lib/arm/libfoo.so
// /data/app/com.example/lib/arm64/libfoo.so
// /data/app/com.example/dalvik/arm/base.apk@classes.dex
/** New install */
FileInstallArgs(InstallParams params) {
super(params);
}
/** Existing install */
FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY,
null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0,
PackageParser.SigningDetails.UNKNOWN,
PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.INSTALL_SCENARIO_DEFAULT,
false, null /* parent */, DataLoaderType.NONE);
this.codeFile = (codePath != null) ? new File(codePath) : null;
this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
}
//执行此处方法
int copyApk() {
try {
//就调用个doCopyApk(),接着往下看
return doCopyApk();
} finally {
}
}
private int doCopyApk() {
//表示文件已下载
if (origin.staged) {
...
if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy");
//获取安装包路径
codeFile = origin.file;
resourceFile = origin.file;
return PackageManager.INSTALL_SUCCEEDED;
}
try {
final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
//创建路径
final File tempDir =
mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
codeFile = tempDir;
resourceFile = tempDir;
} catch (IOException e) {
Slog.w(TAG, "Failed to create copy file: " + e);
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
//将包复制到目标位置(origin.file.getAbsolutePath())。
//返回状态码。注释3
int ret = PackageManagerServiceUtils.copyPackage(
origin.file.getAbsolutePath(), codeFile);
if (ret != PackageManager.INSTALL_SUCCEEDED) {
Slog.e(TAG, "无法复制安装包");
return ret;
}
final boolean isIncremental = isIncrementalPath(codeFile.getAbsolutePath());
final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(codeFile);
// 将 apk 中的动态库 .so 文件也拷贝到目标路径中。
ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
abiOverride, isIncremental);
} catch (IOException e) {
Slog.e(TAG, "Copying native libraries failed", e);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
} finally {
IoUtils.closeQui以上是关于❤️Android 从源码解读 Apk 的安装过程 ❤️的主要内容,如果未能解决你的问题,请参考以下文章