Android之静默安装接口对比分析
2022-01-15 本文已影响0人
锄禾豆
简介
分析静默安装新老接口的对比。
源码:
7.1
分析
老接口A:
PackageManager.installPackage(
Uri packageURI,
PackageInstallObserver observer,
@InstallFlags int flags,
String installerPackageName);
新接口B:
PackageInstaller packageInstaller = PackageManager.getPackageInstaller();
SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);
int sessionId = packageInstaller.createSession(sessionParams);//创建会话id
PackageInstaller.Session session = packageInstaller.openSession(sessionId);//创建会话
final InputStream in = new FileInputStream(file);
final long sizeBytes = file.length();
final OutputStream out = session.openWrite("PackageInstaller", 0, sizeBytes);//打开会话写操作
try {
int c;
while ((c = in.read(buffer)) != -1) {
out.write(buffer, 0, c);//往会话中写数据
if (sizeBytes > 0) {
final float fraction = ((float) c / (float) sizeBytes);
session.addProgress(fraction);
}
}
session.fsync(out);//会话数据同步
} finally {
IoUtils.closeQuietly(in);
IoUtils.closeQuietly(out);
}
Intent broadcastIntent = new Intent(BROADCAST_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
InstallAppProgress.this /*context*/,
sessionId,
broadcastIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
session.commit(pendingIntent.getIntentSender());//提交数据
对比:
A 实现简单 结果监听直接采用observer 数据通过系统直接写到data/app/包名/base.apk
B 实现复杂 结果监听通过PendingIntent 数据先保存在/data/app/vmt{sessiondi}.tmp,再写到/data/app/包名/base.apk
注:
B 涉及了委托模式和会话模式的运用
A 写入base.apk采用了DefaultContainerService.apk拷贝业务
SessionParams需要一个模式参数:
MODE_FULL_INSTALL:新的apk会替换旧的apk的模式。
MODE_INHERIT_EXISTING:新的apk继承旧的apk.
原理
老接口A:
PackageManager.installPackage --> PackageManagerService.installPackageAsUser
新接口B:
PackageManager --> PackageInstaller (PackageInstaller.Session.commmit) --> PackageInstallSession --> PackageManagerService.installStage
对比AMS实现:原理一样,只是传进来的参数B比A更加丰富
A: mHandler INIT_COPY
final Message msg = mHandler.obtainMessage(INIT_COPY);
final VerificationInfo verificationInfo = new VerificationInfo(
null /*originatingUri*/, null /*referrer*/, -1 /*originatingUid*/, callingUid);
final InstallParams params = new InstallParams(origin, null /*moveInfo*/, observer,
installFlags, installerPackageName, null /*volumeUuid*/, verificationInfo, user,
null /*packageAbiOverride*/, null /*grantedPermissions*/,
null /*certificates*/);
params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installAsUser",
System.identityHashCode(msg.obj));
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(msg.obj));
mHandler.sendMessage(msg);
B: mHandler INIT_COPY
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);
}
final Message msg = mHandler.obtainMessage(INIT_COPY);
final InstallParams params = new InstallParams(origin, null, observer,
sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
verificationInfo, user, sessionParams.abiOverride,
sessionParams.grantedRuntimePermissions, certificates);
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);
adb查询
adb shell dumpsys package installs
采用新接口安装的业务,通过此命令可查询apk安装的相关信息