前言
本篇介绍第三方apk安装的过程,重点放在dex的优化部分
分析
uml图:
1.触发安装部分
启动代码:
|
|
启动packageinstaller应用:InstallStart-Activity->PackageInstallerActivity-Activity->InstallInstalling-Activity
|
|
- 获取PackageManager,然后获取其中的PackageInstaller对象
- 在PackageInstaller中创建用于传输APK安装包以及安装信息的Session,并返回SessionId
- 创建异步任务,并在异步任务中根据之前返回的SessionId打开PackageInstaller端Session
- 通过Session将APK安装包以及相关信息传递
- 在异步任务中onPostExecute方法中执行session.commit(pendingIntent.getIntentSender())
PackageInstaller.Session是记录安装信息的,保证可以继续安装。
调用到PackageInstallerSession的commit。
mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
commitLocked();
|
|
mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,mInstallerPackageName, mInstallerUid, user, mCertificates);
4.installStage
PackageManagerServices开始
frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java
PackageManagerServices.installStage:
|
|
发送INIT_COPY消息
5.INIT_COPY
PackageManagerServices.PackageHandler.doHandleMessage:
|
|
最后发送了一个MCS_BOUND
6.MCS_BOUND
PackageManagerServices.PackageHandler.doHandleMessage:
|
|
7.startCopy
PackageManagerServices.HandlerParams.startCopy
|
|
重点俩步操作handleStartCopy与handleReturnCode。
8.handleStartCopy
PackageManagerServices.InstallParams.handleStartCopy
|
|
handleStartCopy的核心是copyApk,其他的都是些存储空间检查,权限检查等等安全校验。
9.handleReturnCode
PackageManagerServices.InstallParams.handleReturnCode
|
|
调回PackageManagerServices
10.processPendingInstall
PackageManagerServices.processPendingInstall
|
|
调用installPackageTracedLI
最后发送POST_INSTALL消息表示安装成功。
11.installPackageTracedLI
|
|
installPackageTracedLI方法将apk进行解析,然后进行dex到opt文件操作,之后安装apk
这个方法先是解析了package包,然后做了大量签名和权限校验的工作。
12.installNewPackageLIF
PackageManagerServices.installNewPackageLIF:
|
|
scanPackageTracedLI调用到参数为5且首为package的scanPackageLI。
scanPackageLI负责安装,而updateSettingLI则是完成安装后的设置信息更新
|
|
这里与系统安装一样了。
13.performDexOpt
接下来到看installPackageLI内的
mPackageDexOptimizer.performDexOpt()调用。这里与系统扫描时的优化相同了。
注意PackageDexOptimizer.performDexOpt->performDexOptLI->dexOptPath->Installer.dexopt->InstalldNativeService.dexopt->dexopt.dexopt
在frameworks\base\services\core\java\com\android\server\pm\PackageDexOptimizer.java类中。
|
|
performDexOptLI调用dexOptPath传入每个dex文件与指令集。
14.dexOptPath
|
|
调用核心 mInstaller.dexopt(path, uid, pkg.packageName, isa, dexoptNeeded, oatDir, dexoptFlags,compilerFilter, pkg.volumeUuid, sharedLibrariesPath, pkg.applicationInfo.seInfo);
15.Installer.dexopt
加下来进入frameworks\base\services\core\java\com\android\server\pm\Installer.java类。
|
|
调用了mInstalld的dexopt。
PackageManagerServcie负责应用的安装,卸载等相关工作。但是installd才是负责干活的,通过PackageManagerService来访问的installd服务来执行程序包的安装与卸载。
PackageManagerService只有system权限。installd却是具有root权限,installd启动是在init进程解析init.rc时。
|
|
在:
frameworks\native\cmds\installd\installd.cpp
|
|
InstalldNativeService是通过binder实现的nativeserver
其在frameworks\native\cmds\installd\InstalldNativeService.cpp
|
|
BinderService在frameworks\native\libs\binder\include\binder\BinderService.h
|
|
可见InstalldNativeService将自己注册到servicemanager。用的是BinderService的模板类方法。加入到ServiceManager中的名字正是installd。
16.InstalldNativeService.dexopt
因此最后dex优化调用到:InstalldNativeService.dexopt
|
|
17.dexopt
android::installd::dexopt的实现在:frameworks\native\cmds\installd\dexopt.cpp
|
|
创建输出文件,调用run_dex2oat执行优化。
跟踪发现第三方安装的生成位置并不在delvik-cache,该目录下仅有系统自带文件的优化。
自己的优化应该是放在了data/app下。
|
|
最后通过execv执行/system/bin/dex2oat 完成oat
有关oat的具体生成研究加固时再分析。