引言
最近手上有银联商务招标的需求,涉及到apk的验签策略,梳理一遍adb install的流程。
每次看完源码,做完需求,后面就慢慢忘记代码流程了,遂写成博客记录下来。
流程图
开始写博客,不太会使用Flowchart流程图,从博友那借用了一张。
c++到java的流程没看懂,流程图有点对不上android9.x的流程,将就着看吧。
出处:https://blog.csdn.net/chishi199433/article/details/103925833
(侵权必删)
adb inatsll ***.apk 命令对应的代码在/system/core/adb/commandline.cpp里面
int adb_commandline(int argc, const char** argv) {
.......
//adb其他命令,pull,push,shell,ls...
.......
else if (!strcmp(argv[0], "install")) {
if (argc < 2) return syntax_error("install requires an argument");
if (_use_legacy_install()) {
return install_app_legacy(argc, argv);
}
return install_app(argc, argv);
}
}
调用到install_app_legacy()函数
static int install_app_legacy(int argc, const char** argv) {
.......
.......
return pm_command(argc, argv);
}
调用到pm_command()函数
2045 static int pm_command(int argc, const char** argv) {
2046 std::string cmd = "pm";
2047
2048 while (argc-- > 0) {
2049 cmd += " " + escape_arg(*argv++);
2050 }
2051
2052 return send_shell_command(cmd, false);
2053 }
调用到send_shell_command()函数,看了下里面的逻辑,没看懂怎么调用到java层。
不死心想要弄清楚c++到java的流程,从java层开始逆向分析。
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
+ Thread.dumpStack();
(new PackageManagerShellCommand(this)).exec(
this, in, out, err, args, callback, resultReceiver);
}
通过Thread.dumpStack()打印调用方法栈,编译,push Service.jar之后查看log
03-04 16:40:27.204 907 1021 W System.err: java.lang.Exception: Stack trace
03-04 16:40:27.205 907 1021 W System.err: at java.lang.Thread.dumpStack(Thread.java:1348)
03-04 16:40:27.205 907 1021 W System.err: at com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:21781)
03-04 16:40:27.205 907 1021 W System.err: at android.os.Binder.shellCommand(Binder.java:634)
03-04 16:40:27.205 907 1021 W System.err: at android.os.Binder.onTransact(Binder.java:532)
03-04 16:40:27.205 907 1021 W System.err: at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:2796)
03-04 16:40:27.205 907 1021 W System.err: at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:3964)
03-04 16:40:27.205 907 1021 W System.err: at android.os.Binder.execTransact(Binder.java:731)
看到熟悉的android.os.Binder和onTransact(),恍然大悟,原来是用的Binder机制,不懂的同学建议学习Binder的相关知识
继续从PackageManagerService.java的onShellCommand()方法开始分析,exec()调用的是父类ShellCommand.java的方法
frameworks/base/core/java/android/os/ShellCommand.java
79 public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
80 String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
81 String cmd;
82 int start;
83 if (args != null && args.length > 0) {
84 cmd = args[0];
85 start = 1;
86 } else {
87 cmd = null;
88 start = 0;
89 }
90 init(target, in, out, err, args, callback, start);
91 mCmd = cmd;
92 mResultReceiver = resultReceiver;
93 .......
.......
101 int res = -1;
102 try {
103 res = onCommand(mCmd);
104 if (DEBUG) Slog.d(TAG, "Executed command " + mCmd + " on " + mTarget);
105 } catch (SecurityException e) {
106 PrintWriter eout = getErrPrintWriter();
107 eout.println("Security exception: " + e.getMessage());
108 eout.println();
109 e.printStackTrace(eout);
110 } catch (Throwable e) {
111 .......
.......
119 } finally {
120 .......
.......
130 }
131 }
132 if (DEBUG) Slog.d(TAG, "Finished command " + mCmd + " on " + mTarget);
133 return res;
134 }
调用到onCommand()方法
public abstract int onCommand(String cmd);
看到abstract字段,就知道是子类继承,重写方法
frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@Override
public int onCommand(String cmd) {
if (cmd == null) {
return handleDefaultCommands(cmd);
}
final PrintWriter pw = getOutPrintWriter();
try {
switch(cmd) {
..........
..........
case "install":
return runInstall();
..........
..........
}
} catch (RemoteException e) {
pw.println("Remote exception: " + e);
}
return -1;
}
调用到runInstall()方法,主要流程是doCreateSession(),doWriteSplit(),doCommitSession()这三个方法
901 private int runInstall() throws RemoteException {
902 final PrintWriter pw = getOutPrintWriter();
903 final InstallParams params = makeInstallParams();
904 final String inPath = getNextArg();
905
906 setParamsSize(params, inPath);
//创建sessionId
907 final int sessionId = doCreateSession(params.sessionParams,
908 params.installerPackageName, params.userId);
909 boolean abandonSession = true;
910 try {
911 if (inPath == null && params.sessionParams.sizeBytes == -1) {
912 pw.println("Error: must either specify a package size or an APK file");
913 return 1;
914 }
915 if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
916 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
917 return 1;
918 }
919 if (doCommitSession(sessionId, false /*logSuccess*/)
920 != PackageInstaller.STATUS_SUCCESS) {
921 return 1;
922 }
923 abandonSession = false;
924 pw.println("Success");
925 return 0;
926 } finally {
927 if (abandonSession) {
928 try {
929 doAbandonSession(sessionId, false /*logSuccess*/);
930 } catch (Exception ignore) {
931 }
932 }
933 }
934 }
doCreateSession()
doCreateSession()方法去创建PackageInstallerSession对象,返回sessionId。
final IPackageManager mInterface;
2406 private int doCreateSession(SessionParams params, String installerPackageName, int userId)
2407 throws RemoteException {
2408 userId = translateUserId(userId, true /*allowAll*/, "runInstallCreate");
2409 if (userId == UserHandle.USER_ALL) {
2410 userId = UserHandle.USER_SYSTEM;
2411 params.installFlags |= PackageManager.INSTALL_ALL_USERS;
2412 }
2413
2414 final int sessionId = mInterface.getPackageInstaller()
2415 .createSession(params, installerPackageName, userId);
2416 return sessionId;
2417 }
看到IPackageManager mInterface,Binder机制,找IPackageManager 的实现类
/frameworks/base/core/java/android/app/ApplicationPackageManager.java
2454 @Override
2455 public PackageInstaller getPackageInstaller() {
2456 synchronized (mLock) {
2457 if (mInstaller == null) {
2458 try {
2459 mInstaller = new PackageInstaller(mPM.getPackageInstaller(),
2460 mContext.getPackageName(), mContext.getUserId());
2461 } catch (RemoteException e) {
2462 throw e.rethrowFromSystemServer();
2463 }
2464 }
2465 return mInstaller;
2466 }
2467 }
mInterface.getPackageInstaller()返回PackageInstaller对象
/frameworks/base/core/java/android/content/pm/PackageInstaller.java
private final IPackageInstaller mInstaller;
public int createSession(@NonNull SessionParams params) throws IOException {
326 try {
327 final String installerPackage;
328 if (params.installerPackageName == null) {
329 installerPackage = mInstallerPackageName;
330 } else {
331 installerPackage = params.installerPackageName;
332 }
333
334 return mInstaller.createSession(params, installerPackage, mUserId);
335 } catch (RuntimeException e) {
336 ExceptionUtils.maybeUnwrapIOException(e);
337 throw e;
338 } catch (RemoteException e) {
339 throw e.rethrowFromSystemServer();
340 }
341 }
看到IPackageInstaller mInstaller,Binder机制,找IPackageInstaller 的实现类
/frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
401 @Override
402 public int createSession(SessionParams params, String installerPackageName, int userId) {
403 try {
404 return createSessionInternal(params, installerPackageName, userId);
405 } catch (IOException e) {
406 throw ExceptionUtils.wrap(e);
407 }
408 }
409
410 private int createSessionInternal(SessionParams params, String installerPackageName, int userId)
411 throws IOException {
412 ..........
//权限检查
//根据调用者的UID调整installFlags
//安装位置处理,不能安装在外部存储
//设置app图标大小
440 ..........
508 final int sessionId;
509 final PackageInstallerSession session;
510 synchronized (mSessions) {
511 // Sanity check that installer isn't going crazy
//检查mSessions数组里面PackageInstallerSession对象的数量,最大数量1024
512 final int activeCount = getSessionCount(mSessions, callingUid);
513 if (activeCount >= MAX_ACTIVE_SESSIONS) {
514 throw new IllegalStateException(
515 "Too many active sessions for UID " + callingUid);
516 }
517 final int historicalCount = mHistoricalSessionsByInstaller.get(callingUid);
518 if (historicalCount >= MAX_HISTORICAL_SESSIONS) {
519 throw new IllegalStateException(
520 "Too many historical sessions for UID " + callingUid);
521 }
//生成sessionId
523 sessionId = allocateSessionIdLocked();
524 }
525
526 final long createdMillis = System.currentTimeMillis();
527 // We're staging to exactly one location
528 File stageDir = null;
529 String stageCid = null;
530 if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
531 final boolean isInstant =
532 (params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
//data下面新建vmdl0123456789.tmp临时目录
533 stageDir = buildStageDir(params.volumeUuid, sessionId, isInstant);
534 } else {
535 stageCid = buildExternalStageCid(sessionId);
536 }
537 //构建PackageInstallerSession对象
538 session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
539 mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
540 params, createdMillis, stageDir, stageCid, false, false);
541
542 synchronized (mSessions) {
//使用数组来存放sessionId和PackageInstallerSession对象
543 mSessions.put(sessionId, session);
544 }
545 //创建成功回调,回调给实现了IPackageInstallerCallback接口的类
546 mCallbacks.notifySessionCreated(session.sessionId, session.userId);
547 writeSessionsAsync();
548 return sessionId;
549 }
allocateSessionIdLocked()方法里面去生成sessionId,我们可以写成自己想要sessionId。
private File buildStageDir(String volumeUuid, int sessionId, boolean isEphemeral) {
final File stagingDir = buildStagingDir(volumeUuid, isEphemeral);
return new File(stagingDir, "vmdl" + sessionId + ".tmp");
}
这里生成/data/app/vmdl01234567890.tmp文件夹,用来存放临时apk文件
再来看writeSessionsAsync()方法,将PackageInstallerSession信息写入mSessionsFile文件
mSessionsFile = new AtomicFile(
new File(Environment.getDataSystemDirectory(), "install_sessions.xml"),
"package-session");
mSessionsDir = new File(Environment.getDataSystemDirectory(), "install_sessions");
mSessionsDir.mkdirs();
..........
..........
private void writeSessionsAsync() {
IoThread.getHandler().post(new Runnable() {
@Override
public void run() {
synchronized (mSessions) {
writeSessionsLocked();
}
}
});
}
.........
.........
@GuardedBy("mSessions")
private void writeSessionsLocked() {
if (LOGD) Slog.v(TAG, "writeSessionsLocked()");
FileOutputStream fos = null;
try {
fos = mSessionsFile.startWrite();
XmlSerializer out = new FastXmlSerializer();
out.setOutput(fos, StandardCharsets.UTF_8.name());
out.startDocument(null, true);
out.startTag(null, TAG_SESSIONS);
final int size = mSessions.size();
for (int i = 0; i < size; i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
session.write(out, mSessionsDir);
}
out.endTag(null, TAG_SESSIONS);
out.endDocument();
mSessionsFile.finishWrite(fos);
} catch (IOException e) {
if (fos != null) {
mSessionsFile.failWrite(fos);
}
}
}
文件路径是data/system/install_sessions.xml,里面的内容:
*******:/ # cat data/system/install_sessions.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<sessions>
<session sessionId="1234567890" userId="0" installerUid="0" createdMillis="1614864398329" sessionStageDir="/data/app/vmdl1234567890.tmp" prepared="true" sealed="false" mode="1" installFlags="114" installLocation="1" sizeBytes="4737146" originatingUid="-1" installRason="0" />
</sessions>
/data/app/vmdl1234567890.tmp里面的1234567890就是我写死的sessionId
doWriteSplit()
继续往下看,来到doWriteSplit()方法,将apk的数据写入到/data/app/vmdl1234567890.tmp/base.apk中
private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
boolean logSuccess) throws RemoteException {
..........
..........
PackageInstaller.Session session = null;
try {
session = new PackageInstaller.Session(
mInterface.getPackageInstaller().openSession(sessionId));
session.write(splitName, 0, sizeBytes, fd);
if (logSuccess) {
pw.println("Success: streamed " + sizeBytes + " bytes");
}
return 0;
} catch (IOException e) {
getErrPrintWriter().println("Error: failed to write; " + e.getMessage());
return 1;
} finally {
IoUtils.closeQuietly(session);
}
}
doCommitSession()
继续往下看,来到doCommitSession()方法
private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
PackageInstaller.Session session = null;
try {
//通过sessionId获取Session对象
session = new PackageInstaller.Session(
mInterface.getPackageInstaller().openSession(sessionId));
// 仔细检查所有.dm文件是否均匹配apk。
//(安装程序不支持独立的.dm文件,因此不会对其进行处理。)
try {
DexMetadataHelper.validateDexPaths(session.getNames());
} catch (IllegalStateException | IOException e) {
pw.println("Warning [Could not validate the dex paths: " + e.getMessage() + "]");
}
final LocalIntentReceiver receiver = new LocalIntentReceiver();
//调用PackageInstaller的commit()方法,receiver是获取安装结果的句柄
session.commit(receiver.getIntentSender());
// 等待300秒获取安装结果
final Intent result = receiver.getResult(300);
if (result == null) {
pw.println("Failure [install timeout]");
return PackageInstaller.STATUS_FAILURE;
}
int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
if (status == PackageInstaller.STATUS_SUCCESS) {
if (logSuccess) {
pw.println("Success");
}
} else {
pw.println("Failure ["
+ result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
status = result.getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS,
PackageManager.INSTALL_FAILED_ABORTED);
}
return status;
} finally {
IoUtils.closeQuietly(session);
}
}
result.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE);获取安装结果,结果是在哪里put进去的呢
继续往下看,session.commit()调用PackageInstaller的commit()方法
public void commit(@NonNull IntentSender statusReceiver) {
try {
mSession.commit(statusReceiver, false);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
实际上调用到PackageInstallerSession类里面的commit()方法
@Override
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
Preconditions.checkNotNull(statusReceiver);
final boolean wasSealed;
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
assertPreparedAndNotDestroyedLocked("commit");
final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(
mContext, statusReceiver, sessionId,
isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId);
mRemoteObserver = adapter.getBinder();
..........
.........
wasSealed = mSealed;
if (!mSealed) {
try {
sealAndValidateLocked();
} catch (IOException e) {
throw new IllegalArgumentException(e);
} catch (PackageManagerException e) {
// Do now throw an exception here to stay compatible with O and older
destroyInternal();
dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);
return;
}
}
// Client staging is fully done at this point
mClientProgress = 1f;
computeProgressLocked(true);
// This ongoing commit should keep session active, even though client
// will probably close their end.
mActiveCount.incrementAndGet();
mCommitted = true;
mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
}
if (!wasSealed) {
// Persist the fact that we've sealed ourselves to prevent
// mutations of any hard links we create. We do this without holding
// the session lock, since otherwise it's a lock inversion.
mCallback.onSessionSealedBlocking(this);
}
}
statusReceiver对象用来初始化PackageInstallObserverAdapter对象
/frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
//apk临时文件删除回调,从PackageManagerService.java的deletePackageVersioned()方法回调过来的
847 @Override
848 public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
849 if (PackageManager.DELETE_SUCCEEDED == returnCode && mNotification != null) {
850 NotificationManager notificationManager = (NotificationManager)
851 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
852 notificationManager.notify(basePackageName,
853 SystemMessage.NOTE_PACKAGE_STATE,
854 mNotification);
855 }
856 final Intent fillIn = new Intent();
857 fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName);
858 fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
859 PackageManager.deleteStatusToPublicStatus(returnCode));
860 fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
861 PackageManager.deleteStatusToString(returnCode, msg));
862 fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
863 try {
864 mTarget.sendIntent(mContext, 0, fillIn, null, null);
865 } catch (SendIntentException ignored) {
866 }
867 }
.........
.........
877 public PackageInstallObserverAdapter(Context context, IntentSender target, int sessionId,
878 boolean showNotification, int userId) {
879 mContext = context;
880 mTarget = target;
881 mSessionId = sessionId;
882 mShowNotification = showNotification;
883 mUserId = userId;
884 }
statusReceiver用来初始化mTarget, mTarget.sendIntent()方法里面放入Intent对象,PackageInstaller.EXTRA_STATUS的值就是在这里put的(PackageInstallerService.java的其他方法里面也有put这个值)。
继续往下看,来到PackageInstallerSession类里面commit()的sealAndValidateLocked()方法,锁定会话防止被修改,并进行apk的验签,流程后面再写博客分析
882 @GuardedBy("mLock")
883 private void sealAndValidateLocked() throws PackageManagerException, IOException {
884 assertNoWriteFileTransfersOpenLocked();
885 assertPreparedAndNotDestroyedLocked("sealing of session");
886 //获取安装包信息
887 final PackageInfo pkgInfo = mPm.getPackageInfo(
888 params.appPackageName, PackageManager.GET_SIGNATURES
889 | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
890
891 resolveStageDirLocked();
893 mSealed = true;
894
895 // 验证packageName,versionCode和证书的一致性。
//初始化预处理文件列表, mResolvedInstructionSets,mResolvedNativeLibPaths,mResolvedInstructionSets, mResolvedInheritedFiles等。
898 try {
899 validateInstallLocked(pkgInfo);
900 } catch (PackageManagerException e) {
901 throw e;
902 } catch (Throwable e) {
903 // Convert all exceptions into package manager exceptions as only those are handled
904 // in the code above
905 throw new PackageManagerException(e);
906 }
908 // Read transfers from the original owner stay open, but as the session's data
909 // cannot be modified anymore, there is no leak of information.
910 }
继续往下看,来到PackageInstallerSession类里面commit()里的这段代码,mHandler.obtainMessage(MSG_COMMIT).sendToTarget(),handler发送MSG_COMMIT消息,找到接收处理消息的地方
291 case MSG_COMMIT:
292 synchronized (mLock) {
293 try {
294 commitLocked();
295 } catch (PackageManagerException e) {
296 final String completeMsg = ExceptionUtils.getCompleteMessage(e);
297 Slog.e(TAG,
298 "Commit of session " + sessionId + " failed: " + completeMsg);
299 destroyInternal();// 删除文件描述符,删除文件桥接
//mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath());删除安装包
//最后调用到native服务InstalldNativeService.cpp里面的rmPackageDir()方法
//Session派发完成,通过注册的监听回调
//PackageInstallerService.java:
//PackageInstallerService.InternalCallback的onSessionFinished()方法
//
//IPackageInstallObserver2的onPackageInstalled()方法
300 dispatchSessionFinished(e.error, completeMsg, null);
301 }
302 }
304 break;
主要来看看commitLocked()方法
@GuardedBy("mLock")
private void commitLocked()
throws PackageManagerException {
..........
..........
//运行时权限确认弹窗
if (needToAskForPermissionsLocked()) {
// 用户需要接受权限; 向安装人员提供可以使用户参与的意图。
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) {
}
// Commit was keeping session marked as active until now; release
// that extra refcount so session appears idle.
closeInternal(false);
return;
}
// 从现有安装继承未覆盖的所有程序包和本机库。
if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
try {
final List<File> fromFiles = mResolvedInheritedFiles;
final File toDir = resolveStageDirLocked();
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包,最后调用到InstalldNativeService.cpp的createOatDir()方法
createOatDirs(mResolvedInstructionSets, oatDir);
}
// 预创建lib dirs以在必要时进行链接,mResolvedNativeLibPaths在validateInstallLocked(pkgInfo)中初始化完成
if (!mResolvedNativeLibPaths.isEmpty()) {
for (String libPath : mResolvedNativeLibPaths) {
// "/lib/arm64" -> ["lib", "arm64"]
final int splitIndex = libPath.lastIndexOf('/');
if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
Slog.e(TAG, "Skipping native library creation for linking due to "
+ "invalid path: " + libPath);
continue;
}
final String libDirPath = libPath.substring(1, splitIndex);
final File libDir = new File(toDir, libDirPath);
if (!libDir.exists()) {
NativeLibraryHelper.createNativeLibrarySubdir(libDir);
}
final String archDirPath = libPath.substring(splitIndex + 1);
NativeLibraryHelper.createNativeLibrarySubdir(
new File(libDir, archDirPath));
}
}
//建立软链接
linkFiles(fromFiles, toDir, mInheritedFilesBase);
} else {
// TODO: this should delegate to DCS so the system process
// avoids holding open FDs into containers.
copyFiles(fromFiles, toDir);
}
} catch (IOException e) {
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
"Failed to inherit existing install", e);
}
}
// 更新安装进度
mInternalProgress = 0.5f;
computeProgressLocked(true);
// 解压本地库
extractNativeLibraries(mResolvedStageDir, params.abiOverride, mayInheritNativeLibs());
final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
@Override
public void onUserActionRequired(Intent intent) {
throw new IllegalStateException();
}
@Override
public void onPackageInstalled(String basePackageName, int returnCode, String msg,
Bundle extras) {
destroyInternal();
dispatchSessionFinished(returnCode, msg, extras);
}
};
........
........
//调用PackageManagerService服务的installStage()方法进行安装
mRelinquished = true;
mPm.installStage(mPackageName, stageDir, localObserver, params,
mInstallerPackageName, mInstallerUid, user, mSigningDetails);
}
又回到PackageManagerService服务里面,继续看installStage()方法
void installStage(String packageName, File stagedDir,
IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
String installerPackageName, int installerUid, UserHandle user,
PackageParser.SigningDetails signingDetails) {
if (DEBUG_INSTANT) {
if ((sessionParams.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
Slog.d(TAG, "Ephemeral install of " + packageName);
}
}
//签名信息
final VerificationInfo verificationInfo = new VerificationInfo(
sessionParams.originatingUri, sessionParams.referrerUri,
sessionParams.originatingUid, installerUid);
//初始化OriginInfo对象,成员变量staged为true
final OriginInfo origin = OriginInfo.fromStagedFile(stagedDir);
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, signingDetails, 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);
}
构建HandlerParams对象,然后通过handler发送INIT_COPY消息,记住这里发送的是InstallParams
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj;
int idx = mPendingInstalls.size();
if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
//是否绑定DefaultContainerService服务,该服务属于独立的进程
if (!mBound) {
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
System.identityHashCode(mHandler));
if (!connectToService()) {
//绑定服务失败,通知绑定失败
Slog.e(TAG, "Failed to bind to media container service");
params.serviceError();
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
System.identityHashCode(mHandler));
if (params.traceMethod != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod,
params.traceCookie);
}
return;
} else {
//绑定服务成功,将安装信息add进待安装列表
mPendingInstalls.add(idx, params);
}
} else {
mPendingInstalls.add(idx, params);
//如果mPendingInstalls的长度为0,发送MCS_BOUND消息
if (idx == 0) {
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
break;
}
继续看MCS_BOUND消息的处理过程
case MCS_BOUND: {
if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
if (msg.obj != null) {
//初始化mContainerService
mContainerService = (IMediaContainerService) msg.obj;
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
System.identityHashCode(mHandler));
}
if (mContainerService == null) {
if (!mBound) {
//没有绑定DefaultContainerService服务
Slog.e(TAG, "Cannot bind to media container service");
for (HandlerParams params : mPendingInstalls) {
// Indicate service bind error
params.serviceError();
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(params));
if (params.traceMethod != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER,
params.traceMethod, params.traceCookie);
}
}
mPendingInstalls.clear();
} else {
Slog.w(TAG, "Waiting to connect to media container service");
}
} else if (mPendingInstalls.size() > 0) {
HandlerParams params = mPendingInstalls.get(0);
if (params != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(params));
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
进行APK文件的拷贝
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) {
if (mBound) {
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Posting delayed MCS_UNBIND");
removeMessages(MCS_UNBIND);
Message ubmsg = obtainMessage(MCS_UNBIND);
//延迟10秒解绑DefaultContainerService服务
sendMessageDelayed(ubmsg, 10000);
}
} else {
//mPendingInstalls队列中还有其他请求,发送MCS_BOUND消息触发下一次安装的处理
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;
}
来看params.startCopy()这行代码,调用到HandlerParams.java的startCopy方法
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()方法,调用到InstallParams.java覆写的handleStartCopy()方法
public void handleStartCopy() throws RemoteException {
int ret = PackageManager.INSTALL_SUCCEEDED;
//前面是通过Session拷贝的apk,这里为true
if (origin.staged) {
if (origin.file != null) {
installFlags |= PackageManager.INSTALL_INTERNAL;
installFlags &= ~PackageManager.INSTALL_EXTERNAL;
} else {
throw new IllegalStateException("Invalid stage location");
}
}
//这里onSd=false,onInt=true
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) {
// 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_INSTANT && ephemeral) {
Slog.v(TAG, "pkgLite for install: " + pkgLite);
}
.........
//空间不足时,尝试释放空间,删除不必要的文件
.........
}
........
........
//创建用于实际拷贝apk文件的InstallArgs对象
final InstallArgs args = createInstallArgs(this);
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
// TODO: http://b/22976637
// 使用system user来验证应用程序
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 {
//没有启用包验证,因此请立即启动远程调用以使用临时文件启动复制。
ret = args.copyApk(mContainerService, true);
}
}
mRet = ret;
}
从这里我们可以看到APK的拷贝工作又交给InstallArgs对象进行处理,根据InstallParams中的参数来创建不同的对象,直接看FileInstallArgs中的copyApk()方法
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) {//true,直接返回
if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy");
codeFile = origin.file;
resourceFile = origin.file;
return PackageManager.INSTALL_SUCCEEDED;
}
........
........
}
9.0版本中通过Session拷贝apk,在doCopyApk()之前,apk就已经拷贝完成。
接下来看apk拷贝之后的操作handleReturnCode()
@Override
void handleReturnCode() {
// 如果mArgs为null,则无法访问MCS。 重新连接时,它将再次尝试安装
if (mArgs != null) {
processPendingInstall(mArgs, mRet);
}
}
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
// 子线程操作操作,安装需要一些时间。
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
//构造PackageInstalledInfo对象解析currentStatus参数
PackageInstalledInfo res = new PackageInstalledInfo();
res.setReturnCode(currentStatus);
res.uid = -1;
res.pkg = null;
res.removedInfo = null;
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
//安装前,res.returnCode不等于PackageManager.INSTALL_SUCCEEDED时,清理残留文件
args.doPreInstall(res.returnCode);
synchronized (mInstallLock) {
//apk安装
installPackageTracedLI(args, res);
}
//安装后,res.returnCode不等于PackageManager.INSTALL_SUCCEEDED时,清理残留文件
args.doPostInstall(res.returnCode, res.uid);
}
//如果a安装成功,b该安装操作不是更新,且c新软件包未选择退出备份,则应该执行还原。
//update:false,doRestore:false
final boolean update = res.removedInfo != null
&& res.removedInfo.removedPackage != null;
final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags;
boolean doRestore = !update
&& ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);
.........
.........
//看名字,是正在运行的安装列表,put操作
PostInstallData data = new PostInstallData(args, res);
mRunningInstalls.put(token, data);
//apk安装成功并且允许还原时,调用BackupManagerService服务备份
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
IBackupManager bm = IBackupManager.Stub.asInterface(
ServiceManager.getService(Context.BACKUP_SERVICE));
.........
try {
// TODO: http://b/22388012
if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
} else {
doRestore = false;
}
..........
}
if (!doRestore) {
//无需备份,发送POST_INSTALL消息执行安装完成后的工作
if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
mHandler.sendMessage(msg);
}
}
});
}
installPackageTracedLI()方法将apk进行解析,然后进行dex到opt文件操作。最后发送POST_INSTALL消息。
case POST_INSTALL: {
if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
PostInstallData data = mRunningInstalls.get(msg.arg1);
final boolean didRestore = (msg.arg2 != 0);
//正在运行的安装列表,移除安装完成的
mRunningInstalls.delete(msg.arg1);
if (data != null) {
InstallArgs args = data.args;
PackageInstalledInfo parentRes = data.res;
..........
// Handle the parent package
handlePackagePostInstall(parentRes, grantPermissions, killApp,
virtualPreload, grantedPermissions, didRestore,
args.installerPackageName, args.observer);
// Handle the child packages
final int childCount = (parentRes.addedChildPackages != null)
? parentRes.addedChildPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
handlePackagePostInstall(childRes, grantPermissions, killApp,
virtualPreload, grantedPermissions, false /*didRestore*/,
args.installerPackageName, args.observer);
}
..........
} break;
这里主要看handlePackagePosetInstall()方法
private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
boolean killApp, boolean virtualPreload, String[] grantedPermissions,
boolean launchedForRestore, String installerPackage,
IPackageInstallObserver2 installObserver) {
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
// Send the removed broadcasts
if (res.removedInfo != null) {
res.removedInfo.sendPackageRemovedBroadcasts(killApp);
}
//已经安装成功,是否需要在发送广播之前赋予运行权限
if (grantPermissions) {
grantRequestedRuntimePermissions(res.pkg, res.newUsers, grantedPermissions);
}
.........
// 如果程序包不是静态共享库,则发送已安装的广播。
if (res.pkg.staticSharedLibName == null) {
mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash(res.pkg.baseCodePath);
//为新用户发送APK安装成功的消息
int appId = UserHandle.getAppId(res.uid);
boolean isSystem = res.pkg.applicationInfo.isSystemApp();
sendPackageAddedForNewUsers(packageName, isSystem || virtualPreload,
virtualPreload /*startReceiver*/, appId, firstUsers);
//为老用户发送APK安装成功的消息
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, res.uid);
if (update) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
null /*targetPackage*/, null /*finishedReceiver*/, updateUsers);//发送APK安装成功的消息
......
for (int userId : firstUsers) {
PackageInfo info = getPackageInfo(packageName, /*flags*/ 0, userId);
//处理安装过程中可能的卸载操作导致包信息为null的异常
if (info != null) {
mDexManager.notifyPackageInstalled(info, userId);
}
}
}
//回调到PackageInstallerSession,告知apk安装完成
if (installObserver != null) {
try {
Bundle extras = extrasForInstallResult(res);
installObserver.onPackageInstalled(res.name, res.returnCode,
res.returnMsg, extras);
} catch (RemoteException e) {
Slog.i(TAG, "Observer no longer exists.");
}
}
}
至此,adb install 安装apk过程完成。