一、何谓apk成功安装到系统
1.1、一个apk怎样才可以称作成功安装到了Android系统?
可以类比一下新生儿。一个刚出生的孩子怎么样才能算是一个完整的社会人呢?
婴儿刚从母亲体内分娩出来,他实际还不能称为一个"社会人",他需要向户籍管理单位进行注册,添加户口页,分配社保ID,完成一些列注册手续之后,才能称为一个完全意义上的“社会人”,并且可以享受国家社会的相关福利。
apk的安装也是类似的,不仅仅需要将apk的实体放到系统的特定目录(/data/app/),而且需要向PackageManagerService注册包名、以及apk声明的四大组件(Activity、Service、ContentProvider、BroadcastReceiver),该apk才能算是成功安装到了Android系统。
大概可分为两个方面:
- 1、安装apk到特定的目录
- 2、注册包名、四大组件到PackageManagerService
只有完成了第2步(向系统注册),Android系统才知道有这么一个apk存在,才可以管理(或者说启动)该apk
1.2、apk安装相关的目录
apk安装目录:
- 1、 /system/app: 系统自带的应用程序,获得adb root权限才能删除
- 2、 /data/app :用户程序安装的目录。安装时把apk文件复制到此目录
dex、odex保存目录:
- 3、/data/dalvik-cache:将apk中的dex文件安装到dalvik-cache目录下(dex文件是dalvik虚拟机的可执行文件,当然,ART–Android Runtime的可执行文件格式为oat,启用ART时,系统会执行dex文件转换至oat文件)
用户数据目录:
- 4、/data/data :存放应用程序的数据,无论是系统app还是普通app,app产生的用户数据都存放在/data/data/包名/目录下。
packages.xml注册表目录
- 5、/data/system :该目录下的packages.xml文件,类似于Windows的注册表。这个文件是在解析apk时由writeLP()创建的,里面记录了系统的permissions,以及每个apk的name,codePath,flags,ts,version,uesrid等信息,这些信息主要通apk的AndroidManifest.xml解析获取,解析完apk后将更新信息写入这个文件并保存到flash,下次开机直接从里面读取相关信息添加到内存相关列表中。当有apk升级,安装或删除时会更新这个文件。
二、PackageManagerService概述
2.1、PackageManagerService 有三大职责
PackageManagerService 是Android系统中所有包的大管家,其最简化的类结构如下:
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender{
//保存所有已安装的apckage信息
final Settings mSettings;
//保存 包名-Package的键值对
final ArrayMap<String, PackageParser.Package> mPackages =
new ArrayMap<String, PackageParser.Package>();
//保存所有已安装包中注册的Activity信息
// All available activities, for your resolving pleasure.
final ActivityIntentResolver mActivities =
new ActivityIntentResolver();
//保存所有已安装apk中注册的Receiver信息
// All available receivers, for your resolving pleasure.
final ActivityIntentResolver mReceivers =
new ActivityIntentResolver();
//保存所有已安装apk中注册的Service信息
// All available services, for your resolving pleasure.
final ServiceIntentResolver mServices = new ServiceIntentResolver();
//保存所有已安装apk中注册ContentProvider信息
// All available providers, for your resolving pleasure.
final ProviderIntentResolver mProviders = new ProviderIntentResolver();
//安装一个apk
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
}
}
PackageManagerService 有三大职责:
(1)开机扫描过程
开机后,加载/data/system/packages.xml文件,然后扫描特定安装目录:/system/app、/system/priv-app、/system/vendor/app、/data/app
解析里面的apk文件,将静态信息提取到PackageManagerService中的主要数据结构中。
(2)安装apk
将一个新的apk 安装到Android系统当中
(3)解析Intent
解析Intent意图,通过Intent获取到目的Activity、Provider、BroadCastReceiver 或Service。
2.2、Settings
上文提到 /data/system/package.xml 记录所有已安装的包信息,package.xml的内容如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<packages>
<permission-trees />
<permissions>
<item name="android.permission.REAL_GET_TASKS" package="android" protection="18" />
<item name="android.permission.ACCESS_CACHE_FILESYSTEM" package="android" protection="18" />
<item name="android.permission.REMOTE_AUDIO_PLAYBACK" package="android" protection="2" />
<item name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" package="com.android.providers.downloads" />
<item name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS" package="android" protection="2" />
<item name="android.permission.INTENT_FILTER_VERIFICATION_AGENT" package="android" protection="18" />
<item name="android.permission.BIND_INCALL_SERVICE" package="android" protection="18" />
<item name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE" package="android" protection="18" />
<item name="android.permission.WRITE_SETTINGS" package="android" protection="1218" />
<item name="sprd.permission.USE_FACE" package="android" />
</permissions>
<package name="com.sogou.iot.w3" codePath="/data/app/com.sogou.iot.w3-5DPtBZkfj2SzwPwTxissow==" nativeLibraryPath="/data/app/com.sogou.iot.w3-5DPtBZkfj2SzwPwTxissow==/lib" primaryCpuAbi="arm64-v8a" publicFlags="944291398" privateFlags="0" ft="176ff6c7290" it="176f63b830d" ut="176ff6c75f6" version="1" sharedUserId="1000">
<sigs count="1">
<cert index="0" key="308203e1308202c9a003020102020900d43b53a119e97dfa300d06092a864886f70d01010b0500308186310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310e300c060355040a0c05536f676f75310e300c060355040b0c05536f676f75310e300c06035504030c05536f676f753123302106092a864886f70d010" />
</sigs>
<perms>
<item name="android.permission.BIND_INCALL_SERVICE" granted="true" flags="0" />
<item name="android.permission.WRITE_SETTINGS" granted="true" flags="0" />
<item name="android.permission.CONFIGURE_WIFI_DISPLAY" granted="true" flags="0" />
<item name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE" granted="true" flags="0" />
</perms>
</package>
....
省略若干个package 声明
</packages>
(1)<package>记录了一个应用的基本信息,签名和声明的权限。
- name表示应用的包名
- codePath表示的是apk文件的路径
- nativeLibraryPath表示应用的native库的存储路径
- flags是指应用的属性,如FLAG_SYSTEM、FLAG_PERSISTENT等
- it表示应用安装的时间
- ut表示应用最后一次修改的时间
- version表示应用的版本号
- userId表示所属于的id
(2)<sign>表示应用的签名
- count表示标签中包含有多少个证书
- cert表示具体的证书的值
(3)<perms>表示应用声明使用的权限,每一个子标签代表一项权限
/data/system/package.xml,被PackageManagerService解析后会存储到mSettings 属性中。
public final class Settings {
/** Map from package name to settings */
final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();
}
Settings中持有一个以package为键,以PackageSetting为值的ArrayMap,一个PackageSetting 就对应packages.xml中的一个package。
public final class PackageSetting extends PackageSettingBase {
PackageParser.Package pkg;
SharedUserSetting sharedUser;
private int sharedUserId;
}
PackageSetting 继承自PackageSettingBase。
public final class PackageSetting extends PackageSettingBase {
PackageParser.Package pkg;
SharedUserSetting sharedUser;
private int sharedUserId;
}
2.3、mPackages
mPackages 维护了所有已安装apk的详细解析信息,包名为key,PackageParser.Package 为value
final ArrayMap<String, PackageParser.Package> mPackages =
new ArrayMap<String, PackageParser.Package>();
2.4、四大组件解析器
- ActivityIntentResolver mActivities 持有所有注册的activity信息,用于通过intent解析成合理的Activity
final class ActivityIntentResolver extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
// Keys are String (activity class name), values are Activity.
private final ArrayMap<ComponentName, PackageParser.Activity> mActivities
= new ArrayMap<ComponentName, PackageParser.Activity>();
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
int userId) {}
}
- ActivityIntentResolver mReceivers 用于解析BroadCastReceiver
- ServiceIntentResolver mServices 维护所有注册的Service,用于通过Intent解成目标Service
- ProviderIntentResolver mProviders 维护所有注册的ContentPrivider 用于将Intent解析成目标ContentProvider
三、apk安装具体安装过程:
3.1、apk安装的主要流程描述
本文主要阐述普通apk的安装流程,大概分为以下几个步骤:
- (1) 拷贝apk文件到指定目录
在Android系统中,apk安装有固定的目录,默认情况下,用户安装的apk首先会被拷贝到 /data/app 目录下,同时会创建/data/app/pkg/lib目录,将apk中的so文件解压到此目录
/data/app目录是用户有权限访问的目录,在安装apk的时候会自动选择该目录存放用户安装的文件。而系统出厂的apk文件则被放到了 /system 分区下,包括:/system/app,/system/vendor/app,以及 /system/priv-app 等等,该分区只有Root权限的用户才能访问。这也就是为什么在没有Root手机之前,我们无法删除系统出厂的app的原因了。
- (2) 扫描apk,解析AndroidManifest.xml文件,向PackagManagerService中注册该package、以及apk声明的四大组件。
- (3)创建apk的用户数据目录,即/data/data/pkg/目录
/data/data/pkg为应用程序的数据目录(以应用的包名命名),存放应用的相关数据,如数据库、xml文件、cache
- (4)为apk执行dexopt优化。
对于普通apk,dexopt优化后的文件保存在/data/app/oat目录
- (5)安装完成发送ACTION_PACKAGE_ADDED广播。
3.2、apk安装代码分析
网络上有很多apk安装流程分析,但是版本都比较老了(Android 6.0左右),和最新的代码有些地方对不上,本文以Android 9.0 代码为基准,分析一下apk的安装流程:
PagkageManagerService的安装apk的入口是installStage
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);
//(1)创建一个InstallParams对象,封装到INIT_COPY消息中
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;
//(2)发送INIT_COPY 消息
mHandler.sendMessage(msg);
}
installStage()方法主要目的是发送一个INIT_COPY Handler消息。
我们看下Handler的处理函数,比较重要的是INIT_COPY和MCS_BOUND 两个消息。
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.
if (!mBound) {
//连接DefaultContainerService,它负责具体的copy操作
if (!connectToService()) {
Slog.e(TAG, "Failed to bind to media container service");
params.serviceError();
return;
} else {
// Once we bind to the service, the first
// pending request will be processed.
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) {
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
break;
}
case MCS_BOUND: {
if (msg.obj != null) {
mContainerService = (IMediaContainerService) msg.obj;
}
if (mContainerService == null) {
//... 省略不重要的代码
} else if (mPendingInstalls.size() > 0) {
HandlerParams params = mPendingInstalls.get(0);
if (params != null) {
//(2)执行copy操作
if (params.startCopy()) {
if (mPendingInstalls.size() > 0) {
mPendingInstalls.remove(0);
}
if (mPendingInstalls.size() == 0) { //空闲时,解绑mContainerService
if (mBound) {
removeMessages(MCS_UNBIND);
Message ubmsg = obtainMessage(MCS_UNBIND);
sendMessageDelayed(ubmsg, 10000);
}
} else {
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
}
}
break;
}
- INIT_COPY 的主要作用是connectToService()连接DefaultContainerService,copyapk的操作是借助DefaultContainerService来完成的。connectToService成功之后,会发送MCS_BOUND消息
- MCS_BOUND 消息主要负责完成apk的拷贝 以及apk中so文件的提取
private abstract class HandlerParams {
final boolean startCopy() {
boolean res;
try {
//...省略不重要的信息
//(1)开始copy
handleStartCopy();
res = true;
} catch (RemoteException e) {
if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
mHandler.sendEmptyMessage(MCS_RECONNECT);
res = false;
}
//(2) copy完成后的操作
handleReturnCode();
return res;
}
}
startCopy 主要做了两件事情:
- handleStartCopy() 完成拷贝apk的过程
- handleReturnCode() 拷贝之后的后续操作
handleStartCopy 主要生成了一个InstallArgs对象,然后调用copyApk方法
public void handleStartCopy(){
final InstallArgs args = createInstallArgs(this);
ret = args.copyApk(mContainerService, false);
}
copyApk->doCopyApk
private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
//(1) copy文件到安装目录:系统app 安装到/system/app/ 普通app安装到/data/app
int ret = PackageManager.INSTALL_SUCCEEDED;
ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
if (ret != PackageManager.INSTALL_SUCCEEDED) {
Slog.e(TAG, "Failed to copy package");
return ret;
}
//(2) 将apk中的so文件复制出来,保存到安装目录。如:/datap/app/lib/
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);
}
}
我们再看看拷贝完apk之后调用的handleReturnCode()
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);
}
}
processPendingInstall 完成后续的安装任务
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() {
PackageInstalledInfo res = new PackageInstalledInfo();
res.setReturnCode(currentStatus);
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
args.doPreInstall(res.returnCode);
synchronized (mInstallLock) {
installPackageTracedLI(args, res);
}
args.doPostInstall(res.returnCode, res.uid);
}
//...省略不重要的代码
}
}
processPendingInstall->installPackageTracedLI->installPackageLI
installPackageLI 是安装的核心操作
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
//(1)利用PackageParser解析apk
final PackageParser.Package pkg;
try {
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);
}
//(2) 执行installNewPackageLIF 或者replacePackageLIF()
try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
"installPackageLI")) {
if (replace) {
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 {
installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
args.user, installerPackageName, volumeUuid, res, args.installReason);
}
}
//(3) 对apk就行dexopt优化
mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,null /* instructionSets */,getOrCreateCompilerPackageStats(pkg),
}
- (1) 利用PackageParser解析该apk
- (2) 如果apk第一安装,则执行installNewPackageLIF 否则执行替换操作replacePackageLIF() ,我们主要分析首次安装的操作。
- (3) 对apk就行dexopt优化
我们重点看下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) {
try {
//此处仅保留了核心的代码,省略了不重要的代码
//(1)扫描package,向PackageManagerService中注册该package
PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags, scanFlags,
System.currentTimeMillis(), user);
updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
//(2)创建/data/data/包名 app数据目录
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);
}
}
重要的操作由两个:scanPackageTracedLI 和prepareAppDataAfterInstallLIF()
- scanPackageTracedLI
scanPackageTracedLI()最终会调用commitPackageSettings()
scanPackageTracedLI->scanPackageNewLI->commitScanResultsLocked-> commitPackageSettings
commitPackageSettings 是真正完成向PackageManagerService注册pkg和四大组件的方法,调用此方法之后,Android系统就可以查询该apk的信息了。
/**
* 该方法是 将pkg和四大组件 注册到PackageManagerService的地方
* Adds a scanned package to the system. When this method is finished, the package will
* be available for query, resolution, etc...
*/
private void commitPackageSettings(PackageParser.Package pkg,
@Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting, UserHandle user,
final @ScanFlags int scanFlags, boolean chatty) {
synchronized (mPackages) {
// Add the new setting to mSettings
//将pkg 插入到mSettings
mSettings.insertPackageSettingLPw(pkgSetting, pkg);
// Add the new setting to mPackages
//将当前包pkg 插入到mPackages
mPackages.put(pkg.applicationInfo.packageName, pkg);
// Make sure we don't accidentally delete its data.
final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
while (iter.hasNext()) {
PackageCleanItem item = iter.next();
if (pkgName.equals(item.packageName)) {
iter.remove();
}
}
int N = pkg.providers.size();
StringBuilder r = null;
int i;
for (i=0; i<N; i++) {
PackageParser.Provider p = pkg.providers.get(i);
p.info.processName = fixProcessName(pkg.applicationInfo.processName,
p.info.processName);
mProviders.addProvider(p);
//...省略不重要的代码
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Providers: " + r);
}
// 注册pkg中的service到mServices
N = pkg.services.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Service s = pkg.services.get(i);
s.info.processName = fixProcessName(pkg.applicationInfo.processName,
s.info.processName);
mServices.addService(s);
//...省略不重要的代码
}
//注册pkg.receivers到mReceivers
N = pkg.receivers.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.receivers.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName);
mReceivers.addActivity(a, "receiver");
//...省略不重要的代码
}
//注册pkg.activities 到 mActivities
N = pkg.activities.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.activities.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName);
mActivities.addActivity(a, "activity");
//...省略不重要的代码
}
//...省略不重要的代码
}
}
- prepareAppDataAfterInstallLIF
我们再看prepareAppDataAfterInstallLIF,经过多次调用,最终进入到prepareAppDataLeafLIF
prepareAppDataAfterInstallLIF->prepareAppDataLIF->prepareAppDataLeafLIF
prepareAppDataLeafLIF方法内,利用mInstaller完成了app用户数据目录的创建.
private void prepareAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
//...省略不重要的代码
try {
ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
appId, seInfo, app.targetSdkVersion);
} catch (InstallerException e) {
}
}
- handlePackagePostInstall
执行完上述安装操作之后,会发送POST_INSTALL 消息,进入到handlePackagePostInstall方法
handlePackagePostInstall 会发送ACTION_PACKAGE_ADDED广播给监听者。
private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
boolean killApp, boolean virtualPreload, String[] grantedPermissions,
boolean launchedForRestore, String installerPackage,
IPackageInstallObserver2 installObserver) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
null /*targetPackage*/, null /*finishedReceiver*/,
updateUserIds, instantUserIds);
}
至此一个新apk的安装完成。
3.3、Android 6.0 下的完整调用流程
下面 Android 6.0 源码 apk安装的完成调用过程,虽然最新的android sdk一些方法已经发生了变化,但是多少也可以做一些参考。
├── PMS.installPackage()
└── PMS.installPackageAsUser()
|传递 InstallParams 参数
PackageHandler.doHandleMessage().INIT_COPY
|
PackageHandler.doHandleMessage().MCS_BOUND
├── HandlerParams.startCopy()
│ ├── InstallParams.handleStartCopy()
│ │ └──InstallArgs.copyApk()
│ └── InstallParams.handleReturnCode()
│ └── PMS.processPendingInstall()
│ ├── InstallArgs.doPreInstall()
│ ├── PMS.installPackageLI()
│ │ ├── PackageParser.parsePackage()
│ │ ├── PackageParser.collectCertificates()
│ │ ├── PackageParser.collectManifestDigest()
│ │ ├── PackageDexOptimizer.performDexOpt()
│ │ ├── InstallArgs.doRename()
│ │ │ └── InstallArgs.getNextCodePath()
│ │ ├── replacePackageLI()
│ │ │ ├── shouldCheckUpgradeKeySetLP()
│ │ │ ├── compareSignatures()
│ │ │ ├── replaceSystemPackageLI()
│ │ │ │ ├── killApplication()
│ │ │ │ ├── removePackageLI()
│ │ │ │ ├── Settings.disableSystemPackageLPw()
│ │ │ │ ├── createInstallArgsForExisting()
│ │ │ │ ├── deleteCodeCacheDirsLI()
│ │ │ │ ├── scanPackageLI()
│ │ │ │ └── updateSettingsLI()
│ │ │ └── replaceNonSystemPackageLI()
│ │ │ ├── deletePackageLI()
│ │ │ ├── deleteCodeCacheDirsLI()
│ │ │ ├── scanPackageLI()
│ │ │ └── updateSettingsLI()
│ │ └── installNewPackageLI()
│ │ ├── scanPackageLI()
│ │ └── updateSettingsLI()
│ ├── InstallArgs.doPostInstall()
│ ├── BackupManager.restoreAtInstall()
│ └── sendMessage(POST_INSTALL)
│ |
│ PackageHandler.doHandleMessage().POST_INSTALL
│ ├── grantRequestedRuntimePermissions()
│ ├── sendPackageBroadcast()
│ └── IPackageInstallObserver.onPackageInstalled()
└── PackageHandler.doHandleMessage().MCS_UNBIND
└── PackageHandler.disconnectService()![image](https://upload-images.jianshu.io/upload_images/5713484-36bddaa4264c58d4.png)