Androidapk安装流程之adb安装

目录
app安装方式
Android应用程序安装有四种方式:
- 系统启动时安装,没有安装界面
- 第三方应用安装,有安装界面,也是我们最熟悉的方式
- ADB命令安装,没有安装界面
- 通过Google Play市场安装,没有安装界面
四种方式最后都是通过PackageManagerService服务来完成应用程序的安装。
PackageManagerService服务通过与Installd服务通信,发送具体的指令来执行应用程序的安装、卸载等工作。

使用路径
app在安装时涉及到如下几个重要目录:
目录 | 解释 |
---|---|
system/app | 系统应用程序的目录 |
data/app | 用户程序安装的目录 |
data/data | 存放应用程序数据的目录 |
data/dalvik-cache | 存放的是经过优化的dex文件 |
APK文件结构
目录 | 描述 |
---|---|
assert | 存放的原生资源文件,通过AssetManager类访问 |
lib | native库文件 |
META-INF | 存放签名信息,用来保证APK包的完整性和系统的安全。系统安装APK时,应用管理器会按照对应算法对包里文件做校验,如果校验结果与META-INF中内容不一致,则不会安装这个APK。 |
res | 种资源文件系统会在R.java里面自动生成该资源文件的ID,所以访问这种资源文件比较简单,通过R.XXX.ID即可 |
AndroidManifest.xml | 每个应用都必须定义和包含,描述应用的名字、版本权限、引用的库文件等信息。apk中的AndroidManifest.xml经过压缩,可以通过AXMLPrinter2工具解开。 |
classes.dex | 是JAVA源码编译后生成的JAVA字节码文件。但Android使用的dalvik虚拟机与标准的JAVA虚拟机不兼容,dex文件与class文件相比,不论是文件结构还是opcode都不一样。 |
resources.arsc | 编译后的二进制资源文件。 |
应用程序安装过程
-
adb install:
安装入口函数为Pm.runInstall
frameworks\base\cmds\pm\src\com\android\commands\pm\Pm.java -
网络下载应用安装和第三方应用安装:
安装入口函数为ApplicationPackageManager.installPackage
frameworks\base\core\java\android\app\ApplicationPackageManager.java
apk安装的四大步骤:
1. 拷贝apk到指定的目录:默认情况下,用户安装的apk首先会拷贝到/data/app下,用户有访问/data/app目录的权限,但系统出厂的apk文件会被放到/system分区下,包括/system/app,/system/vendor/app,以及/system/priv-app等,该分区需要root权限的用户才能访问。
2. 加载apk、拷贝文件、创建应用的数据目录:为了加快APP的启动速度,apk在安装的时候,会首先将APP的可执行文件(dex)拷贝到/data/dalvik-cache目录下,缓存起来。再在/data/data/目录下创建应用程序的数据目录(以应用包名命令),用来存放应用的数据库、xml文件、cache、二进制的so动态库等。
3. 解析apk的AndroidManifest.xml文件:在安装apk的过程中,会解析apk的AndroidManifest.xml文件,将apk的权限、应用包名、apk的安装位置、版本、userID等重要信息保存在/data/system/packages.xml文件中。这些操作都是在PackageManagerService中完成的。
4. 显示icon图标:应用程序经过PMS中的逻辑处理后,相当于已经注册好了,如果想要在Android桌面上看到icon图标,则需要Launcher将系统中已经安装的程序展现在桌面上。
adb install 的安装方式
adb install 的安装方式,会调用| commandline.cpp |
中的adb_commandline函数:
int adb_commandline(int argc, const char** argv) {
……
else if (!strcmp(argv[0], "install")) {
if (argc < 2) return usage("install requires an argument");
if (_use_legacy_install()) {
return install_app_legacy(transport_type, serial, argc, argv);
}
return install_app(transport_type, serial, argc, argv);
}
……
return 1;
}
adb会把apk文件copy到data/local/tmp/目录下,然后向shell服务发送pm命令安装apk,最后调用Pm.runInstall()方法来安装apk。
static int install_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
static const char *const DATA_DEST = "/data/local/tmp/%s";
static const char *const SD_DEST = "/sdcard/tmp/%s";
const char* where = DATA_DEST;
……
int result = -1;
std::vector<const char*> apk_file = {argv[last_apk]};
std::string apk_dest = android::base::StringPrintf(
where, android::base::Basename(argv[last_apk]).c_str());
// 复制app到/data/local/tmp/下
if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
argv[last_apk] = apk_dest.c_str();
//执行pm命令
result = pm_command(transport, serial, argc, argv);
cleanup_apk:
delete_file(transport, serial, apk_dest);
return result;
}
最后进入到Pm.runInstall()
函数来安装apk。
Pm.java中的runInstall函数:
private int runInstall() throws RemoteException {
long startedTime = SystemClock.elapsedRealtime();
final InstallParams params = makeInstallParams();
final String inPath = nextArg();
if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
File file = new File(inPath);
if (file.isFile()) {
try {
// 使用PackageParser解析apk包
ApkLite baseApk = PackageParser.parseApkLite(file, 0);
PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
null, null);
params.sessionParams.setSize(
PackageHelper.calculateInstalledSize(pkgLite, false,
params.sessionParams.abiOverride));
} catch (PackageParserException | IOException e) {
System.err.println("Error: Failed to parse APK file: " + e);
return 1;
}
} else {
System.err.println("Error: Can't open non-file: " + inPath);
return 1;
}
}
// 创建Session
final int sessionId = doCreateSession(params.sessionParams,
params.installerPackageName, params.userId);
try {
if (inPath == null && params.sessionParams.sizeBytes == -1) {
System.err.println("Error: must either specify a package size or an APK file");
return 1;
}
// 写入Session
if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
return 1;
}
// 提交Session
Pair<String, Integer> status = doCommitSession(sessionId, false /*logSuccess*/);
if (status.second != PackageInstaller.STATUS_SUCCESS) {
return 1;
}
Log.i(TAG, "Package " + status.first + " installed in " + (SystemClock.elapsedRealtime()
- startedTime) + " ms");
System.out.println("Success");
return 0;
} finally {
try {
mInstaller.abandonSession(sessionId);
} catch (Exception ignore) {
}
}
}
runInstall主要进行了三件事,创建session、对session进行写操作,最后提交session。
doCreateSession函数调用的是PackageInstallerService的createSession,这个过程主要是为APK安装做好准备工作,例如权限检查、目的临时文件的创建等, 最终创建出PackageInstallerSession对象。
PackageInstallerSession可以看做是”安装APK”这个请求的封装,其中包含了处理这个请求需要的一些信息。实际上PackageInstallerSession不仅是分装请求的对象,其自身还是个服务端。
doCreateSession函数:
private int doCreateSession(SessionParams params, String installerPackageName, int userId)
throws RemoteException {
userId = translateUserId(userId, "runInstallCreate");
if (userId == UserHandle.USER_ALL) {
userId = UserHandle.USER_SYSTEM;
params.installFlags |= PackageManager.INSTALL_ALL_USERS;
}
final int sessionId = mInstaller.createSession(params, installerPackageName, userId);
return sessionId;
}
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
mInstaller = mPm.getPackageInstaller();
进入PackageManagerService.java类看一下getPackageInstaller函数:
public IPackageInstaller getPackageInstaller() {
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
return null;
}
return mInstallerService;
}
final PackageInstallerService mInstallerService;
mInstallerService = new PackageInstallerService(context, this);
所以最后获取了PackageInstallerService对象,并执行createSession函数:
public int createSession(SessionParams params, String installerPackageName, int userId) {
try {
return createSessionInternal(params, installerPackageName, userId);
} catch (IOException e) {
throw ExceptionUtils.wrap(e);
}
}
private int createSessionInternal(SessionParams params, String installerPackageName, int userId)
throws IOException {
// 权限检查
final int callingUid = Binder.getCallingUid();
mPm.enforceCrossUserPermission(callingUid, userId, true, true, "createSession");
if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
throw new SecurityException("User restriction prevents installing");
}
……
// 获取图标数据
if (params.appIcon != null) {
final ActivityManager am = (ActivityManager) mContext.getSystemService(
Context.ACTIVITY_SERVICE);
final int iconSize = am.getLauncherLargeIconSize();
if ((params.appIcon.getWidth() > iconSize * 2)
|| (params.appIcon.getHeight() > iconSize * 2)) {
params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize,
true);
}
}
……
final long createdMillis = System.currentTimeMillis();
//创建文件夹
File stageDir = null;
String stageCid = null;
if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
final boolean isInstant =
(params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
stageDir = buildStageDir(params.volumeUuid, sessionId, isInstant);
} else {
stageCid = buildExternalStageCid(sessionId);
}
// 创建session
session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
params, createdMillis, stageDir, stageCid, false, false);
synchronized (mSessions) {
mSessions.put(sessionId, session);
}
mCallbacks.notifySessionCreated(session.sessionId, session.userId);
writeSessionsAsync();
return sessionId;
}
之后开始进入doWriteSession函数:
private int doWriteSession(int sessionId, String inPath, long sizeBytes, String splitName,
boolean logSuccess) throws RemoteException {
if (STDIN_PATH.equals(inPath)) {
inPath = null;
} else if (inPath != null) {
final File file = new File(inPath);
if (file.isFile()) {
sizeBytes = file.length();
}
}
final SessionInfo info = mInstaller.getSessionInfo(sessionId);
PackageInstaller.Session session = null;
InputStream in = null;
OutputStream out = null;
try {
session = new PackageInstaller.Session(
mInstaller.openSession(sessionId));
if (inPath != null) {
in = new FileInputStream(inPath);
} else {
in = new SizedInputStream(System.in, sizeBytes);
}
out = session.openWrite(splitName, 0, sizeBytes);
int total = 0;
byte[] buffer = new byte[65536];
int c;
while ((c = in.read(buffer)) != -1) {
total += c;
out.write(buffer, 0, c);
if (info.sizeBytes > 0) {
final float fraction = ((float) c / (float) info.sizeBytes);
session.addProgress(fraction);
}
}
session.fsync(out);
if (logSuccess) {
System.out.println("Success: streamed " + total + " bytes");
}
return PackageInstaller.STATUS_SUCCESS;
} catch (IOException e) {
System.err.println("Error: failed to write; " + e.getMessage());
return PackageInstaller.STATUS_FAILURE;
} finally {
IoUtils.closeQuietly(out);
IoUtils.closeQuietly(in);
IoUtils.closeQuietly(session);
}
}
该函数通过PackageInstallerSession将/data/local/tmp的apk拷贝到终端目录内
最后开始执行doCommitSession函数:
private Pair<String, Integer> doCommitSession(int sessionId, boolean logSuccess)
throws RemoteException {
PackageInstaller.Session session = null;
try {
// 获取session
session = new PackageInstaller.Session(
mInstaller.openSession(sessionId));
final LocalIntentReceiver receiver = new LocalIntentReceiver();
// 执行session的commit函数
session.commit(receiver.getIntentSender());
final Intent result = receiver.getResult();
final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
if (status == PackageInstaller.STATUS_SUCCESS) {
if (logSuccess) {
System.out.println("Success");
}
} else {
System.err.println("Failure ["
+ result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
}
return new Pair<>(result.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME), status);
} finally {
IoUtils.closeQuietly(session);
}
}
跟踪下PackageInstaller.java中的session的commit函数:
public static class Session implements Closeable {
private IPackageInstallerSession mSession;
public void commit(@NonNull IntentSender statusReceiver) {
try {
mSession.commit(statusReceiver);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
执行进入PackageInstallerSession.java类中的commit函数:
public void commit(IntentSender statusReceiver) {
Preconditions.checkNotNull(statusReceiver);
final boolean wasSealed;
synchronized (mLock) {
wasSealed = mSealed;
if (!mSealed) {
for (RevocableFileDescriptor fd : mFds) {
if (!fd.isRevoked()) {
throw new SecurityException("Files still open");
}
}
for (FileBridge bridge : mBridges) {
if (!bridge.isClosed()) {
throw new SecurityException("Files still open");
}
}
mSealed = true;
}
mClientProgress = 1f;
computeProgressLocked(true);
}
if (!wasSealed) {
mCallback.onSessionSealedBlocking(this);
}
mActiveCount.incrementAndGet();
final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
statusReceiver, sessionId, mIsInstallerDeviceOwner, userId);
mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
}
函数中发送消息MSG_COMMIT:
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
final PackageInfo pkgInfo = mPm.getPackageInfo(
params.appPackageName, PackageManager.GET_SIGNATURES
| PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
final ApplicationInfo appInfo = mPm.getApplicationInfo(
params.appPackageName, 0, userId);
synchronized (mLock) {
if (msg.obj != null) {
mRemoteObserver = (IPackageInstallObserver2) msg.obj;
}
try {
commitLocked(pkgInfo, appInfo);
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
destroyInternal();
dispatchSessionFinished(e.error, completeMsg, null);
}
return true;
}
}
};
之后执行了commitLocked函数:
private void commitLocked(PackageInfo pkgInfo, ApplicationInfo appInfo)
throws PackageManagerException {
……
try {
resolveStageDir();
} catch (IOException e) {
throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
"Failed to resolve stage location", e);
}
// 验证app是否正常
validateInstallLocked(pkgInfo, appInfo);
Preconditions.checkNotNull(mPackageName);
Preconditions.checkNotNull(mSignatures);
Preconditions.checkNotNull(mResolvedBaseFile);
if (!mPermissionsAccepted) {
// 安装权限获得
final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_PERMISSIONS);
intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName());
intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
try {
mRemoteObserver.onUserActionRequired(intent);
} catch (RemoteException ignored) {
}
close();
return;
}
……
if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
try {
final List<File> fromFiles = mResolvedInheritedFiles;
final File toDir = resolveStageDir();
if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
throw new IllegalStateException("mInheritedFilesBase == null");
}
if (isLinkPossible(fromFiles, toDir)) {
if (!mResolvedInstructionSets.isEmpty()) {
final File oatDir = new File(toDir, "oat");
// 创建oat文件夹
createOatDirs(mResolvedInstructionSets, oatDir);
}
linkFiles(fromFiles, toDir, mInheritedFilesBase);
} else {
copyFiles(fromFiles, toDir);
}
} catch (IOException e) {
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
"Failed to inherit existing install", e);
}
}
mInternalProgress = 0.5f;
computeProgressLocked(true);
// 解压native动态库
extractNativeLibraries(mResolvedStageDir, params.abiOverride);、
……
final UserHandle user;
if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
user = UserHandle.ALL;
} else {
user = new UserHandle(userId);
}
mRelinquished = true;
// 开始真正的安装
mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
installerPackageName, installerUid, user, mCertificates);
}
最后执行了PackageManagerService.java的installStage函数:
void installStage(String packageName, File stagedDir, String stagedCid,
IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
String installerPackageName, int installerUid, UserHandle user,
Certificate[][] certificates) {
……
final VerificationInfo verificationInfo = new VerificationInfo(
sessionParams.originatingUri, sessionParams.referrerUri,
sessionParams.originatingUid, installerUid);
final OriginInfo origin;
if (stagedDir != null) {
origin = OriginInfo.fromStagedFile(stagedDir);
} else {
origin = OriginInfo.fromStagedContainer(stagedCid);
}
// 发送INIT_COPY信息
final Message msg = mHandler.obtainMessage(INIT_COPY);
final int installReason = fixUpInstallReason(installerPackageName, installerUid,
sessionParams.installReason);
final InstallParams params = new InstallParams(origin, null, observer,
sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
verificationInfo, user, sessionParams.abiOverride,
sessionParams.grantedRuntimePermissions, certificates, installReason);
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);
}
其中发送了INIT_COPY信息:
final ArrayList<HandlerParams> mPendingInstalls =
new ArrayList<HandlerParams>();
case INIT_COPY: {
// 这里取出的其实就是InstallParams
HandlerParams params = (HandlerParams) msg.obj;
//idx为当前等待处理处理的安装请求的个数
int idx = mPendingInstalls.size();
if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
//初始时,mBound的值为false
if (!mBound) {
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
System.identityHashCode(mHandler));
//连接安装服务
if (!connectToService()) {
……
} else {
//绑定服务成功后,将新的请求加入到mPendingIntalls中,等待处理
mPendingInstalls.add(idx, params);
}
} else {
//如果是第一个请求,则直接发送事件MCS_BOUND,触发处理流程
mPendingInstalls.add(idx, params);
if (idx == 0) {
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
break;
}
INIT_COPY最后会发送MCS_BOUND消息触发接下来的流程:
case MCS_BOUND: {
if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
if (msg.obj != null) {
mContainerService = (IMediaContainerService) msg.obj;
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
System.identityHashCode(mHandler));
}
if (mContainerService == null) {
……
} else if (mPendingInstalls.size() > 0) {
HandlerParams params = mPendingInstalls.get(0);
if (params != null) {
……
if (params.startCopy()) {
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Checking for more work or unbind...");
// 从读了中删除
if (mPendingInstalls.size() > 0) {
mPendingInstalls.remove(0);
}
if (mPendingInstalls.size() == 0) {
……
} else {
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Posting MCS_BOUND for next work");
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
} else {
Slog.w(TAG, "Empty queue");
}
break;
}
代码中看主要执行了HandlerParams中的startCopy函数,也是在文件PackageManagerService.java中:
final boolean startCopy() {
boolean res;
try {
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
if (++mRetries > MAX_RETRIES) {
Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
mHandler.sendEmptyMessage(MCS_GIVE_UP);
handleServiceError();
return false;
} else {
handleStartCopy();
res = true;
}
} catch (RemoteException e) {
if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
mHandler.sendEmptyMessage(MCS_RECONNECT);
res = false;
}
handleReturnCode();
return res;
}
继`续执行handleStartCopy函数:
public void handleStartCopy() throws RemoteException {
int ret = PackageManager.INSTALL_SUCCEEDED;
// 决定是安装在手机内还是sdcard中,设置对应标志位
if (origin.staged) {
if (origin.file != null) {
installFlags |= PackageManager.INSTALL_INTERNAL;
installFlags &= ~PackageManager.INSTALL_EXTERNAL;
} else if (origin.cid != null) {
installFlags |= PackageManager.INSTALL_EXTERNAL;
installFlags &= ~PackageManager.INSTALL_INTERNAL;
} else {
throw new IllegalStateException("Invalid stage location");
}
}
……
// 检查APK的安装位置是否正确
if (onInt && onSd) {
// Check if both bits are set.
Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else if (onSd && ephemeral) {
Slog.w(TAG, "Conflicting flags specified for installing ephemeral on external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else {
pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
packageAbiOverride);
if (DEBUG_EPHEMERAL && ephemeral) {
Slog.v(TAG, "pkgLite for install: " + pkgLite);
}
if (!origin.staged && pkgLite.recommendedInstallLocation
== PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
final StorageManager storage = StorageManager.from(mContext);
final long lowThreshold = storage.getStorageLowBytes(
Environment.getDataDirectory());
final long sizeBytes = mContainerService.calculateInstalledSize(
origin.resolvedPath, isForwardLocked(), packageAbiOverride);
try {
mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);
pkgLite = mContainerService.getMinimalPackageInfo(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;
}
}
}
……
// createInstallArgs用于创建一个安装参数对象
final InstallArgs args = createInstallArgs(this);
mArgs = args;
……
// 调用InstallArgs的copyApk函数
ret = args.copyApk(mContainerService, true);
……
mRet = ret;
}
handleStartCopy主要功能是获取安装位置信息以及复制apk到指定位置。
InstallArgs中的copyApk负责复制APK文件,具体实现在子类FileInstallArgs和MoveInstallArgs里面:
private InstallArgs createInstallArgs(InstallParams params) {
if (params.move != null) {
return new MoveInstallArgs(params);
} else if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) {
return new AsecInstallArgs(params);
} else {
return new FileInstallArgs(params);
}
}
继续看下startCopy中的handleReturnCode函数:
void handleReturnCode() {
if (mArgs != null) {
processPendingInstall(mArgs, mRet);
}
}
主要的安装流程都在processPendingInstall函数:
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
PackageInstalledInfo res = new PackageInstalledInfo();
res.setReturnCode(currentStatus);
res.uid = -1;
res.pkg = null;
res.removedInfo = null;
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
//1、预安装,检查包状态,确保环境ok,如果环境不ok,那么会清理拷贝的文件
args.doPreInstall(res.returnCode);
synchronized (mInstallLock) {
//2、安装,调用installPackageTracedLI进行安装
installPackageTracedLI(args, res);
}
//3、安装收尾
args.doPostInstall(res.returnCode, res.uid);
}
……
if (!doRestore) {
// No restore possible, or the Backup Manager was mysteriously not
// available -- just fire the post-install work request directly.
if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
//4、生成一个POST_INSTALL消息给PackageHanlder
Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
mHandler.sendMessage(msg);
}
}
});
}
看一下installPackageTracedLI函数:
private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo res) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackage");
installPackageLI(args, res);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
继续跟踪installPackageLI函数:
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
……
// PackageParser对象
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setDisplayMetrics(mMetrics);
pp.setCallback(mPackageParserCallback);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final PackageParser.Package pkg;
try {
// 开始解析package
pkg = pp.parsePackage(tmpPackageFile, parseFlags);
} catch (PackageParserException e) {
res.setError("Failed parse during installPackageLI", e);
return;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
if (instantApp && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
Slog.w(TAG, "Instant app package " + pkg.packageName + " does not target O");
res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
"Instant app package must target O");
return;
}
if (instantApp && pkg.applicationInfo.targetSandboxVersion != 2) {
Slog.w(TAG, "Instant app package " + pkg.packageName
+ " does not target targetSandboxVersion 2");
res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
"Instant app package must use targetSanboxVersion 2");
return;
}
if (pkg.applicationInfo.isStaticSharedLibrary()) {
// 静态库
renameStaticSharedLibraryPackage(pkg);
// No static shared libs on external storage
if (onExternal) {
Slog.i(TAG, "Static shared libs can only be installed on internal storage.");
res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
"Packages declaring static-shared libs cannot be updated");
return;
}
}
try {
//2. 加载证书,获取签名信息
if (args.certificates != null) {
try {
PackageParser.populateCertificates(pkg, args.certificates);
} catch (PackageParserException e) {
PackageParser.collectCertificates(pkg, parseFlags);
}
} else {
PackageParser.collectCertificates(pkg, parseFlags);
}
} catch (PackageParserException e) {
res.setError("Failed collect during installPackageLI", e);
return;
}
pp = null;
String oldCodePath = null;
boolean systemApp = false;
synchronized (mPackages) {
// 3.检测packages是否已经存在
if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
String oldName = mSettings.getRenamedPackageLPr(pkgName);
if (pkg.mOriginalPackages != null
&& pkg.mOriginalPackages.contains(oldName)
&& mPackages.containsKey(oldName)) {
pkg.setPackageName(oldName);
pkgName = pkg.packageName;
replace = true;
if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName="
+ oldName + " pkgName=" + pkgName);
} else if (mPackages.containsKey(pkgName)) {
replace = true;
if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName);
}
……
if (replace) {
// 4.更新已经存在的packages
PackageParser.Package oldPackage = mPackages.get(pkgName);
final int oldTargetSdk = oldPackage.applicationInfo.targetSdkVersion;
final int newTargetSdk = pkg.applicationInfo.targetSdkVersion;
if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1
&& newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) {
res.setError(PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE,
"Package " + pkg.packageName + " new target SDK " + newTargetSdk
+ " doesn't support runtime permissions but the old"
+ " target SDK " + oldTargetSdk + " does.");
return;
}
final int oldTargetSandbox = oldPackage.applicationInfo.targetSandboxVersion;
final int newTargetSandbox = pkg.applicationInfo.targetSandboxVersion;
if (oldTargetSandbox == 2 && newTargetSandbox != 2) {
res.setError(PackageManager.INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
"Package " + pkg.packageName + " new target sandbox "
+ newTargetSandbox + " is incompatible with the previous value of"
+ oldTargetSandbox + ".");
return;
}
if (oldPackage.parentPackage != null) {
res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
"Package " + pkg.packageName + " is child of package "
+ oldPackage.parentPackage + ". Child packages "
+ "can be updated only through the parent package.");
return;
}
}
}
……
startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);
try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
"installPackageLI")) {
if (replace) {
if (pkg.applicationInfo.isStaticSharedLibrary()) {
// 4.更新已经存在的packages
PackageParser.Package existingPkg = mPackages.get(pkg.packageName);
if (existingPkg != null && existingPkg.mVersionCode != pkg.mVersionCode) {
res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring "
+ "static-shared libs cannot be updated");
return;
}
}
replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
installerPackageName, res, args.installReason);
} else {
// 5.安装新的packages
installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
args.user, installerPackageName, volumeUuid, res, args.installReason);
}
}
……
}
这一段代码比较多,主要解析APK的AndroidManifest.xml,将每个标签对应的信息添加到Package的相关列表中,如将下的信息添加到Package的activities列表等。
- 加载apk证书,获取签名信息
- 检查目前安装的APK是否在系统中已存在:
已存在,则调用replacePackageLIF进行替换安装。
不存在,否则调用installNewPackageLIF进行安装。
继续看一下installNewPackageLIF函数:
private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
PackageInstalledInfo res, int installReason) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");
String pkgName = pkg.packageName;
if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
synchronized(mPackages) {
final String renamedPackage = mSettings.getRenamedPackageLPr(pkgName);
if (renamedPackage != null) {
res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
+ " without first uninstalling package running as "
+ renamedPackage);
return;
}
if (mPackages.containsKey(pkgName)) {
// Don't allow installation over an existing package with the same name.
res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
+ " without first uninstalling.");
return;
}
}
try {
// 1. 安装apk
PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
System.currentTimeMillis(), user);
// 更新set
updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
prepareAppDataAfterInstallLIF(newPackage);
} else {
// Remove package from internal structures, but keep around any
// data that might have already existed
deletePackageLIF(pkgName, UserHandle.ALL, false, null,
PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
}
} catch (PackageManagerException e) {
res.setError("Package couldn't be installed in " + pkg.codePath, e);
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
scanPackageTracedL函数最后会安装apk:
private PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]");
try {
return scanPackageLI(scanFile, parseFlags, scanFlags, currentTime, user);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
继续执行scanPackageLI:
private PackageParser.Package scanPackageLI(PackageParser.Package pkg, final int policyFlags,
int scanFlags, long currentTime, @Nullable UserHandle user)
throws PackageManagerException {
boolean success = false;
try {
final PackageParser.Package res = scanPackageDirtyLI(pkg, policyFlags, scanFlags,
currentTime, user);
success = true;
return res;
} finally {
if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
// DELETE_DATA_ON_FAILURES is only used by frozen paths
destroyAppDataLIF(pkg, UserHandle.USER_ALL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
destroyAppProfilesLIF(pkg, UserHandle.USER_ALL);
}
}
}
scanPackageDirtyLI是apk安装的核心部分,下一篇文章继续介绍下。
到这里基本上安装就结束了。接下来看下流程图:

