Android 从源码解读 Apk 的安装过程

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移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

总结:

各行各样都会淘汰一些能力差的,不仅仅是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)]

  • 20
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值