该系列,我们将学习PMS如何处理apk的安装
一、PackageHandler处理安装消息APK的信息交由PMS后,PMS通过向PackageHandler发送消息来驱动APK的复制和安装工作。先来查看PackageHandler处理安装消息的调用时序图。
1.1 PMS的installStage方法frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
void installStage(String packageName, File stagedDir,
IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
String installerPackageName, int installerUid, UserHandle user,
PackageParser.SigningDetails signingDetails) {
...
final VerificationInfo verificationInfo = new VerificationInfo(
sessionParams.originatingUri, sessionParams.referrerUri,
sessionParams.originatingUid, installerUid);
final OriginInfo origin = OriginInfo.fromStagedFile(stagedDir);
final Message msg = mHandler.obtainMessage(INIT_COPY);
final int installReason = fixUpInstallReason(installerPackageName, installerUid,
sessionParams.installReason);
//创建InstallParams,它对应于包的安装数据
final InstallParams params = new InstallParams(origin, null, observer,
sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
verificationInfo, user, sessionParams.abiOverride,
sessionParams.grantedRuntimePermissions, signingDetails, installReason);
params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
...
mHandler.sendMessage(msg);
}
PackageManagerService.java#InstallParams
class InstallParams extends HandlerParams {
final OriginInfo origin;
final MoveInfo move;
final IPackageInstallObserver2 observer;
int installFlags;
final String installerPackageName;
final String volumeUuid;
private InstallArgs mArgs;
private int mRet;
final String packageAbiOverride;
final String[] grantedRuntimePermissions;
final VerificationInfo verificationInfo;
final PackageParser.SigningDetails signingDetails;
final int installReason;
...
}
1.2 对INIT_COPY的消息的处理
PackageManagerService.java#PackageHandler
public static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
DEFAULT_CONTAINER_PACKAGE,
"com.android.defcontainer.DefaultContainerService");
final private DefaultContainerConnection mDefContainerConn =
new DefaultContainerConnection();
class DefaultContainerConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
final IMediaContainerService imcs = IMediaContainerService.Stub
.asInterface(Binder.allowBlocking(service));
//注释1
mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
}
public void onServiceDisconnected(ComponentName name) {
if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
}
}
class PackageHandler extends Handler {
private boolean mBound = false;
final ArrayList mPendingInstalls =
new ArrayList();
...
private boolean connectToService() {
if (DEBUG_INSTALL) Log.i(TAG, "Trying to bind to DefaultContainerService");
Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
if (mContext.bindServiceAsUser(service, mDefContainerConn,
Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
mBound = true;
return true;
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return false;
}
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;
int idx = mPendingInstalls.size();
// If a bind was already initiated we dont really
// need to do anything. The pending install
// will be processed later on.
//mBound用于标识是否绑定了服务,默认值为false
if (!mBound) {
// If this is the only one pending we might
// have to bind to the service again.
//如果没有绑定服务,重新绑定,connectToService方法内部如果绑定成功会将mBound置为true
if (!connectToService()) {
params.serviceError();
//绑定服务失败则return
return;
} else {
// Once we bind to the service, the first
// pending request will be processed.
//绑定服务成功,将请求添加到ArrayList类型的mPendingInstalls中,等待处理
mPendingInstalls.add(idx, params);
}
} else {
//已经绑定服务
mPendingInstalls.add(idx, params);
// Already bound to the service. Just make
// sure we trigger off processing the first request.
if (idx == 0) {
//注释2
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
break;
}
}
}
}
PackageHandler继承自Handler,它定义在PMS中,doHandleMessage方法用于处理各个类型的消息,mBound用于标识是否绑定了DefaultContainerService,默认值为false。DefaultContainerService是用于检查和复制可移动文件的服务,这是一个比较耗时的操作,因此DefaultContainerService没有和PMS运行在同一进程中,它运行在com.android.defcontainer进程,通过IMediaContainerService和PMS进行IPC通信,如下图所示。
注释1处发送了MCS_BOUND类型的消息,与PackageHandler.doHandleMessage方法的注释2处不同的是,这里发送消息带了Object类型的参数,这里会对这两种情况来进行讲解,一种是消息不带Object类型的参数,一种是消息带Object类型的参数。
1.3 对MCS_BOUND类型的消息的处理
1.3.1 消息不带Object类型的参数
class PackageHandler extends Handler {
...
void doHandleMessage(Message msg) {
switch (msg.what) {
...
case MCS_BOUND: {
if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
if (msg.obj != null) {
mContainerService = (IMediaContainerService) msg.obj;
...
}
//消息不带Object类型的参数进入该分支
if (mContainerService == null) {
//注释1
if (!mBound) {
// Something seriously wrong since we are not bound and we are not
// waiting for connection. Bail out.
Slog.e(TAG, "Cannot bind to media container service");
for (HandlerParams params : mPendingInstalls) {
// Indicate service bind error
params.serviceError();
...
}
//绑定失败,清空安装请求队列
mPendingInstalls.clear();
} else {
//继续等待绑定服务
Slog.w(TAG, "Waiting to connect to media container service");
}
} else if (mPendingInstalls.size() > 0) {
...
} else {
// Should never happen ideally.
Slog.w(TAG, "Empty queue");
}
break;
}
}
}
}
class PackageHandler extends Handler {
...
void doHandleMessage(Message msg) {
switch (msg.what) {
...
case MCS_BOUND: {
if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
if (msg.obj != null) {
mContainerService = (IMediaContainerService) msg.obj;
...
}
//消息不带Object类型的参数进入该分支
if (mContainerService == null) {
//注释1
if (!mBound) {
// Something seriously wrong since we are not bound and we are not
// waiting for connection. Bail out.
Slog.e(TAG, "Cannot bind to media container service");
for (HandlerParams params : mPendingInstalls) {
// Indicate service bind error
params.serviceError();
...
}
//绑定失败,清空安装请求队列
mPendingInstalls.clear();
} else {
//继续等待绑定服务
Slog.w(TAG, "Waiting to connect to media container service");
}
} else if (mPendingInstalls.size() > 0) {
...
} else {
// Should never happen ideally.
Slog.w(TAG, "Empty queue");
}
break;
}
}
}
}
如果满足注释1处的条件,说明还没有绑定服务,而此前已经在PackageHandler.doHandleMessage方法的INIT_COPY处调用绑定服务的方法了,这显然是不正常的,因此处理服务发生错误的情况。如果不满足注释1处的条件,说明已经绑定服务了,就会打印出系统log,告知用户等待系统绑定服务。
1.3.2 消息带Object类型的参数class PackageHandler extends Handler {
...
void doHandleMessage(Message msg) {
switch (msg.what) {
...
case MCS_BOUND: {
if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
if (msg.obj != null) {
mContainerService = (IMediaContainerService) msg.obj;
...
}
if (mContainerService == null) {
...
} else if (mPendingInstalls.size() > 0) { //消息带Object类型的参数进入该分支
//得到安装请求队列第一个请求HandlerParams
HandlerParams params = mPendingInstalls.get(0);
if (params != null) {
//调用HandlerParams的startCopy方法,用于开始复制APK的流程
if (params.startCopy()) {
// We are done... look for more work or to
// go idle.
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Checking for more work or unbind...");
// Delete pending install
//如果APK安装成功,删除本次安装请求
if (mPendingInstalls.size() > 0) {
mPendingInstalls.remove(0);
}
if (mPendingInstalls.size() == 0) {
if (mBound) {
//如果没有安装请求了,发送解绑服务的请求
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Posting delayed MCS_UNBIND");
removeMessages(MCS_UNBIND);
Message ubmsg = obtainMessage(MCS_UNBIND);
// Unbind after a little delay, to avoid
// continual thrashing.
sendMessageDelayed(ubmsg, 10000);
}
} else {
// There are more pending requests in queue.
// Just post MCS_BOUND message to trigger processing
// of next pending install.
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Posting MCS_BOUND for next work");
//如果还有其他的安装请求,接着发送MCS_BOUND消息继续处理剩余的安装请求
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
} else {
// Should never happen ideally.
Slog.w(TAG, "Empty queue");
}
break;
}
}
}
}
二、复制apk
复制APK的时序图
HandlerParams是PMS中的抽象类,它的实现类为PMS的内部类InstallParams。
PackageManagerService.java#HandlerParams
private abstract class HandlerParams {
//startCopy方法尝试的次数,超过了4次,就放弃这个安装请求
private static final int MAX_RETRIES = 4;
private int mRetries = 0;
private final UserHandle mUser;
String traceMethod;
int traceCookie;
...
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;
}
//处理复制APK后的安装APK逻辑
handleReturnCode();
return res;
}
...
abstract void handleStartCopy() throws RemoteException;
abstract void handleServiceError();
abstract void handleReturnCode();
}
PackageManagerService.java#InstallParams
public void handleStartCopy() throws RemoteException {
int ret = PackageManager.INSTALL_SUCCEEDED;
...
//确定APK的安装位置 onSd:安装到SD卡 onInt:内部存储即Data分区 ephemeral:安装到临时存储(Instant Apps安装)
final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
PackageInfoLite pkgLite = null;
if (onInt && onSd) {
// APK不能同时安装在SD卡和Data分区
// 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) {
//安装标志冲突,Instant Apps不能安装到SD卡中
Slog.w(TAG, "Conflicting flags specified for installing ephemeral on external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else {
//注释1 获取APK的少量的信息
pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
packageAbiOverride);
if (!origin.staged && pkgLite.recommendedInstallLocation
== PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
// TODO: focus freeing disk space on the target device
final StorageManager storage = StorageManager.from(mContext);
final long lowThreshold = storage.getStorageLowBytes(
Environment.getDataDirectory());
final long sizeBytes = mContainerService.calculateInstalledSize(
origin.resolvedPath, 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;
}
}
}
if (ret == PackageManager.INSTALL_SUCCEEDED) {
//判断安装的位置
int loc = pkgLite.recommendedInstallLocation;
if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
} else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
} else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
ret = PackageManager.INSTALL_FAILED_INVALID_APK;
} else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
ret = PackageManager.INSTALL_FAILED_INVALID_URI;
} else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
} else {
// Override with defaults if needed.
//注释2
loc = installLocationPolicy(pkgLite);
if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
} else if (!onSd && !onInt) {
// Override install location with flags
if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
// Set the flag to install on external media.
installFlags |= PackageManager.INSTALL_EXTERNAL;
installFlags &= ~PackageManager.INSTALL_INTERNAL;
} else if (loc == PackageHelper.RECOMMEND_INSTALL_EPHEMERAL) {
if (DEBUG_INSTANT) {
Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag");
}
installFlags |= PackageManager.INSTALL_INSTANT_APP;
installFlags &= ~(PackageManager.INSTALL_EXTERNAL
|PackageManager.INSTALL_INTERNAL);
} else {
// Make sure the flag for installing on external
// media is unset
installFlags |= PackageManager.INSTALL_INTERNAL;
installFlags &= ~PackageManager.INSTALL_EXTERNAL;
}
}
}
}
//注释3 根据InstallParams创建InstallArgs对象
final InstallArgs args = createInstallArgs(this);
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
// TODO: http://b/22976637
// Apps installed for "all" users use the device owner to verify the app
UserHandle verifierUser = getUser();
if (verifierUser == UserHandle.ALL) {
verifierUser = UserHandle.SYSTEM;
}
final int requiredUid = mRequiredVerifierPackage == null ? -1
: getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
verifierUser.getIdentifier());
final int installerUid =
verificationInfo == null ? -1 : verificationInfo.installerUid;
if (!origin.existing && requiredUid != -1
&& isVerificationEnabled(
verifierUser.getIdentifier(), installFlags, installerUid)) {
...
} else {
//注释4
ret = args.copyApk(mContainerService, true);
}
}
mRet = ret;
}
InstallParamshandleStartCopy方法的代码很多,这里截取关键的部分:
(1) 注释1处通过IMediaContainerService跨进程调用DefaultContainerService的getMinimalPackageInfo方法,该方法轻量解析APK并得到APK的少量信息,轻量解析的原因是这里不需要得到APK的全部信息,APK的少量信息会封装到PackageInfoLite中
(2) 注释2处确定APK的安装位置。
(3) 注释3处创建了InstallArgs,InstallArgs 是一个抽象类,定义了APK的安装逻辑,比如复制和重命名APK等,它有3个子类,都被定义在PMS中,如下图所示。
其中FileInstallArgs用于处理安装到非ASEC的存储空间的APK,也就是内部存储空间(Data分区),AsecInstallArgs用于处理安装到ASEC中(mnt/asec)即SD卡中的APK。MoveInstallArgs用于处理已安装APK的移动的逻辑。对APK进行检查后就会在注释4处调用InstallArgs的copyApk方法进行安装。不同的InstallArgs子类会有着不同的处理,这里以FileInstallArgs为例。FileInstallArgs的copyApk方法中会直接return FileInstallArgs的doCopyApk方法。
PackageManagerService.java#FileInstallArgs
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
try {
return doCopyApk(imcs, temp);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
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;
//注释1 创建临时文件存储目录
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;
}
final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
@Override
public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
if (!FileUtils.isValidExtFilename(name)) {
throw new IllegalArgumentException("Invalid filename: " + name);
}
try {
final File file = new File(codeFile, name);
final FileDescriptor fd = Os.open(file.getAbsolutePath(),
O_RDWR | O_CREAT, 0644);
Os.chmod(file.getAbsolutePath(), 0644);
return new ParcelFileDescriptor(fd);
} catch (ErrnoException e) {
throw new RemoteException("Failed to open: " + e.getMessage());
}
}
};
int ret = PackageManager.INSTALL_SUCCEEDED;
//注释2
ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
if (ret != PackageManager.INSTALL_SUCCEEDED) {
Slog.e(TAG, "Failed to copy package");
return ret;
}
final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(codeFile);
ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
abiOverride);
} catch (IOException e) {
Slog.e(TAG, "Copying native libraries failed", e);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
} finally {
IoUtils.closeQuietly(handle);
}
return ret;
}
注释1处用于创建临时存储目录,比如/data/app/vmdl18300388.tmp,其中18300388是安装的sessionId。注释2处通过IMediaContainerService跨进程调用DefaultContainerService的copyPackage方法,这个方法会在DefaultContainerService所在的进程中将APK复制到临时存储目录,比如/data/app/vmdl18300388.tmp/base.apk。目前为止APK的复制工作就完成了,接着就是APK的安装过程了。
三、安装apk我们回到APK的复制调用链的头部方法:HandlerParams的startCopy方法会调用handleReturnCode方法,它的实现在InstallParams中,如下所示:
PackageManagerService.java#InstallParams
@Override
void handleReturnCode() {
// If mArgs is null, then MCS couldn't be reached. When it
// reconnects, it will try again to install. At that point, this
// will succeed.
if (mArgs != null) {
processPendingInstall(mArgs, mRet);
}
}
PackageManagerService.java
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
// Queue up an async operation since the package installation may take a little while.
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
// Result object to be returned
PackageInstalledInfo res = new PackageInstalledInfo();
res.setReturnCode(currentStatus);
res.uid = -1;
res.pkg = null;
res.removedInfo = null;
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
//注释1 安装前处理
args.doPreInstall(res.returnCode);
synchronized (mInstallLock) {
//注释2
installPackageTracedLI(args, res);
}
//注释3 安装后收尾
args.doPostInstall(res.returnCode, res.uid);
}
...
}
});
}
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);
}
}
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
...
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 {
//注释1 解析APK
pkg = pp.parsePackage(tmpPackageFile, parseFlags);
DexMetadataHelper.validatePackageDexMetadata(pkg);
} catch (PackageParserException e) {
res.setError("Failed parse during installPackageLI", e);
return;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
...
// Get rid of all references to package scan path via parser.
pp = null;
String oldCodePath = null;
boolean systemApp = false;
synchronized (mPackages) {
// Check if installing already existing package
// 检查APK是否存在
if ((installFlags & PackageManager.INSTALL_REPLACe_EXISTING) != 0) {
//获取没被改名前的包名
String oldName = mSettings.getRenamedPackageLPr(pkgName);
if (pkg.mOriginalPackages != null
&& pkg.mOriginalPackages.contains(oldName)
&& mPackages.containsKey(oldName)) {
// This package is derived from an original package,
// and this device has been updating from that original
// name. We must continue using the original name, so
// rename the new package here.
//注释2
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)) {
// This package, under its official name, already exists
// on the device; we should replace it.
replace = true;
if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName);
}
...
}
PackageSetting ps = mSettings.mPackages.get(pkgName);
//注释3 查看Settings中是否存有要安装的APK的信息,如果有就获取签名信息
if (ps != null) {
if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
// Static shared libs have same package with different versions where
// we internally use a synthetic package name to allow multiple versions
// of the same package, therefore we need to compare signatures against
// the package setting for the latest library version.
PackageSetting signatureCheckPs = ps;
if (pkg.applicationInfo.isStaticSharedLibrary()) {
SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
if (libraryEntry != null) {
signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
}
}
// Quick sanity check that we're signed correctly if updating;
// we'll check this again later when scanning, but we want to
// bail early here before tripping over redefined permissions.
final KeySetManagerService ksms = mSettings.mKeySetManagerService;
//检查签名的正确性
if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) {
if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) {
res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
+ pkg.packageName + " upgrade keys do not match the "
+ "previously installed version");
return;
}
} else {
...
}
...
}
int N = pkg.permissions.size();
for (int i = N-1; i >= 0; i--) {
//遍历每个权限,对权限进行处理
final PackageParser.Permission perm = pkg.permissions.get(i);
final BasePermission bp =
(BasePermission) mPermissionManager.getPermissionTEMP(perm.info.name);
...
}
}
if (systemApp) {
if (onExternal) {
//系统APP不能在SD卡上替换安装
// Abort update; system app can't be replaced with app on sdcard
res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
"Cannot install updates to system apps on sdcard");
return;
} else if (instantApp) {
//系统APP不能被Instant App替换
// Abort update; system app can't be replaced with an instant app
res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
"Cannot update a system app with an instant app");
return;
}
}
...
//注释4 重命名临时文件
if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");
return;
}
...
try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
"installPackageLI")) {
if (replace) {
//注释5 替换安装
if (pkg.applicationInfo.isStaticSharedLibrary()) {
// Static libs have a synthetic package name containing the version
// and cannot be updated as an update would get a new package name,
// unless this is the exact same version code which is useful for
// development.
PackageParser.Package existingPkg = mPackages.get(pkg.packageName);
if (existingPkg != null &&
existingPkg.getLongVersionCode() != pkg.getLongVersionCode()) {
res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring "
+ "static-shared libs cannot be updated");
return;
}
}
replacePackageLIF(pkg, parseFlags, scanFlags, args.user,
installerPackageName, res, args.installReason);
} else {
//安装新的APK
installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
args.user, installerPackageName, volumeUuid, res, args.installReason);
}
}
...
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
//更新应用程序所属的用户
res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
ps.setUpdateAvailable(false );
}
...
}
}
installPackageLI方法的代码有将近500行,这里截取主要的部分,主要做了几件事:
(1) 创建PackageParser解析APK
(2) 检查APK是否存在,如果存在就获取此前没被改名前的包名并在注释2处赋值给PackageParser.Package类型的pkg,在注释3处将标志位replace置为true表示是替换安装
(3) 注释3处,如果Settings中保存有要安装的APK的信息,说明此前安装过该APK,则需要校验APK的签名信息,确保安全的进行替换
(4) 在注释4处将临时文件重新命名,比如前面提到的/data/app/vmdl18300388.tmp/base.apk,重命名为/data/app/包名-1/base.apk。这个新命名的包名会带上一个数字后缀1,每次升级一个已有的App,这个数字会不断的累加。系统APP的更新安装会有两个限制,一个是系统APP不能在SD卡上替换安装,另一个是系统APP不能被Instant App替换
(5) 注释5处根据replace来做区分,如果是替换安装就会调用replacePackageLIF方法,其方法内部还会对系统APP和非系统APP进行区分处理,如果是新安装APK会调用installNewPackageLIF方法。
这里我们以新安装APK为例,会调用PMS的installNewPackageLIF方法。
private void installNewPackageLIF(PackageParser.Package pkg, final @ParseFlags int parseFlags,
final @ScanFlags int scanFlags, UserHandle user, String installerPackageName,
String volumeUuid, PackageInstalledInfo res, int installReason) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");
// Remember this for later, in case we need to rollback this install
String pkgName = pkg.packageName;
if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
synchronized(mPackages) {
final String renamedPackage = mSettings.getRenamedPackageLPr(pkgName);
if (renamedPackage != null) {
// A package with the same name is already installed, though
// it has been renamed to an older name. The package we
// are trying to install should be installed as an update to
// the existing one, but that has not been requested, so bail.
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 {
//扫描APK
PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags, scanFlags,
System.currentTimeMillis(), user);
//更新Settings信息
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
//安装失败则删除APK
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);
}
installNewPackageLIF主要做了以下3件事:
(1) 扫描APK,将APK的信息存储在PackageParser.Package类型的newPackage中,一个Package的信息包含了1个base APK以及0个或者多个split APK。
(2) 更新该APK对应的Settings信息,Settings用于保存所有包的动态设置。
(3) 如果安装成功就为新安装的应用程序准备数据,安装失败就删除APK。



