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 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 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 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.closeQuietly(handle);
}
return ret;
}
}
注释3:PackageManagerServiceUtils.copyPackage() 这个看名字 就是调用 工具类 的 copyPackage 方法拷贝安装包。具体咱们往下看。
PackageManagerServiceUtils.copyPackage()
frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
/**
* 将包复制到目标位置。
* @param packagePath 要复制的包的绝对路径。
* 可以是单个单一的 APK 文件,也可以是包含一个或多个 APK 的集群目录。
* @return 根据PackageManager 中的状态返回状态码
*/
public static int copyPackage(String packagePath, File targetDir) {
if (packagePath == null) {
return PackageManager.INSTALL_FAILED_INVALID_URI;
}
try {
final File packageFile = new File(packagePath);
final PackageParser.PackageLite pkg = PackageParser.parsePackageLite(packageFile, 0);
//下面有copyFile的源码,咱一起看
copyFile(pkg.baseCodePath, targetDir, “base.apk”);
if (!ArrayUtils.isEmpty(pkg.splitNames)) {
for (int i = 0; i < pkg.splitNames.length; i++) {
copyFile(pkg.splitCodePaths[i], targetDir,
“split_” + pkg.splitNames[i] + “.apk”);
}
}
return PackageManager.INSTALL_SUCCEEDED;
} catch (PackageParserException | IOException | ErrnoException e) {
Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e);
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
}
private static void copyFile(String sourcePath, File targetDir, String targetName)
throws ErrnoException, IOException {
if (!FileUtils.isValidExtFilename(targetName)) {
throw new IllegalArgumentException("Invalid filename: " + targetName);
}
Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);
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);
//将 source.getFD() 的内容复制到targetFd。
//FileUtils:frameworks/base/core/java/android/os/FileUtils.java
FileUtils.copy(source.getFD(), targetFd);
} finally {
IoUtils.closeQuietly(source);
}
}
看到这里 最终安装包在 data/app 目录下以 base.apk 的方式保存,至此安装包拷贝工作就已经完成。
例:/data/app/com.example/base.apk
InstallParams
接下来咱们看看 InstallParams 中 的 注释2 processPendingInstall(mArgs, mRet); 也就是装载部分。
class InstallParams extends HandlerParams {
…
@Override
void handleReturnCode() {
if (mVerificationCompleted
&& mIntegrityVerificationCompleted && mEnableRollbackCompleted) {
…
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
//注释1
mRet = mArgs.copyApk();
}
//注释2
processPendingInstall(mArgs, mRet);
}
}
}
}
processPendingInstall()
装载部分
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
//分包
if (args.mMultiPackageInstallParams != null) {
args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
} else {
//
PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
//异步操作,因为包安装可能需要一段时间。
processInstallRequestsAsync(
res.returnCode == PackageManager.INSTALL_SUCCEEDED,
Collections.singletonList(new InstallRequest(args, res)));
}
}
processInstallRequestsAsync()
private void processInstallRequestsAsync(boolean success,
List installRequests) {
mHandler.post(() -> {
if (success) {
for (InstallRequest request : installRequests) {
// 预安装操作,主要是检查安装包的状态,确保安装环境正常,如果安装环境有问题会清理拷贝文件
request.args.doPreInstall(request.installResult.returnCode);
}
synchronized (mInstallLock) {
//真正的安装阶段
installPackagesTracedLI(installRequests);
}
for (InstallRequest request : installRequests) {
request.args.doPostInstall(
request.installResult.returnCode, request.installResult.uid);
}
}
for (InstallRequest request : installRequests) {
restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
new PostInstallData(request.args, request.installResult, null));
}
});
}
installPackagesTracedLI()
@GuardedBy({“mInstallLock”, “mLock”})
private void installPackagesTracedLI(List requests) {
try {
//添加跟踪 Trace。
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, “installPackages”);
//调用 installPackageLI 方法进行安装。咱们接着看
installPackagesLI(requests);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
installPackagesLI()
@GuardedBy(“mInstallLock”)
private void installPackagesLI(List requests) {
…
boolean success = false;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, “installPackagesLI”);
for (InstallRequest request : requests) {
final PrepareResult prepareResult;
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, “preparePackage”);
//注释1
//成功准备好的安装软件包所需的数据集。这包括将用于扫描和协调包的数据。
prepareResult =
preparePackageLI(request.args, request.installResult);
} catch (PrepareFailure prepareFailure) {
…
return;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
…
}
}
}
注释1:preparePackageLI() 包含内容过多咱们开始逐步讲解。
preparePackageLI()
@GuardedBy(“mInstallLock”)
private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
throws PrepareFailure {
final int installFlags = args.installFlags;
final File tmpPackageFile = new File(args.getCodePath());
final boolean onExternal = args.volumeUuid != null;
final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
final boolean virtualPreload =
((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
@ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
…
ParsedPackage parsedPackage;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
总结:
各行各样都会淘汰一些能力差的,不仅仅是IT这个行业,所以,不要被程序猿是吃青春饭等等这类话题所吓倒,也不要觉得,找到一份工作,就享受安逸的生活,你在安逸的同时,别人正在奋力的向前跑,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。
文件夹有以下学习笔记,自行下载!
-
BAT大厂面试题、独家面试工具包,
-
资料免费领取,包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter,
lure prepareFailure) {
…
return;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
…
}
}
}
注释1:preparePackageLI() 包含内容过多咱们开始逐步讲解。
preparePackageLI()
@GuardedBy(“mInstallLock”)
private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
throws PrepareFailure {
final int installFlags = args.installFlags;
final File tmpPackageFile = new File(args.getCodePath());
final boolean onExternal = args.volumeUuid != null;
final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
final boolean virtualPreload =
((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
@ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
…
ParsedPackage parsedPackage;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-aBO4y7yP-1710763688120)]
[外链图片转存中…(img-OgzHnsfH-1710763688120)]
[外链图片转存中…(img-6suGZ9dY-1710763688121)]
[外链图片转存中…(img-mR9JfcOd-1710763688121)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-eBKE4T1M-1710763688121)]
总结:
各行各样都会淘汰一些能力差的,不仅仅是IT这个行业,所以,不要被程序猿是吃青春饭等等这类话题所吓倒,也不要觉得,找到一份工作,就享受安逸的生活,你在安逸的同时,别人正在奋力的向前跑,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。
文件夹有以下学习笔记,自行下载!
-
BAT大厂面试题、独家面试工具包,
-
资料免费领取,包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter,
[外链图片转存中…(img-wzhy07nM-1710763688122)]