PackageManagerService的构造函数中调用了scanDirTracedLI方法来扫描某个目录的apk文件。
1. 扫描路径
在Android 10.0中,PKMS主要扫描以下路径的APK信息:
/vendor/overlay
/product/overlay
/product_services/overlay
/odm/overlay
/oem/overlay
/system/framework
/system/priv-app
/system/app
/vendor/priv-app
/vendor/app
/odm/priv-app
/odm/app
/oem/app
/oem/priv-app
/product/priv-app
/product/app
/product_services/priv-app
/product_services/app
/product_services/priv-app
然而在Android 11.0中,PKMS扫描的路径虽然和Android 10.0中的不完全相同但是也是扫描的所有的路径。从以下注释中也可以看出
// Android 10.0中执行scanDirTracedLI方法前的注释
// Collect vendor/product/product_services overlay packages. (Do this before scanning
// any apps.)
// Android 11.0中执行scanDirTracedLI方法前的注释
// Collect vendor/product/system_ext overlay packages. (Do this before scanning
// any apps.)
现在我们从源码中去找一下扫描的是所有路径的依据:
for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
final ScanPartition partition = mDirsToScanAsSystem.get(i);
if (partition.getOverlayFolder() == null) {
continue;
}
scanDirTracedLI(partition.getOverlayFolder(), systemParseFlags,
systemScanFlags | partition.scanFlag, 0,
packageParser, executorService);
}
我们发现,此处遍历了一个mDirToScanAsSystem集合。
在执行scanTracedLI方法前有这样一段代码:
for (int i = 0; i < activeApexInfos.size(); i++) {
final ScanPartition scanPartition =
resolveApexToScanPartition(activeApexInfos.get(i));
if (scanPartition != null) {
scanPartitions.add(scanPartition);
}
}
mDirsToScanAsSystem = new ArrayList<>();
mDirsToScanAsSystem.addAll(SYSTEM_PARTITIONS);
mDirsToScanAsSystem.addAll(scanPartitions);
看一下resolveApexToScanPartition方法的源码:
private static @Nullable ScanPartition resolveApexToScanPartition(
ApexManager.ActiveApexInfo apexInfo) {
for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
ScanPartition sp = SYSTEM_PARTITIONS.get(i);
if (apexInfo.preInstalledApexPath.getAbsolutePath().startsWith(
sp.getFolder().getAbsolutePath())) {
return new ScanPartition(apexInfo.apexDirectory, sp, SCAN_AS_APK_IN_APEX);
}
}
return null;
}
我们看到新建了一个ScanPartition对象,
public ScanPartition(@NonNull SystemPartition partition) {
super(partition);
scanFlag = scanFlagForPartition(partition);
}
在构造方法中调用了scanFlagForPartition方法,代码如下:
private static int scanFlagForPartition(PackagePartitions.SystemPartition partition) {
switch (partition.type) {
case PackagePartitions.PARTITION_SYSTEM:
return 0;
case PackagePartitions.PARTITION_VENDOR:
return SCAN_AS_VENDOR;
case PackagePartitions.PARTITION_ODM:
return SCAN_AS_ODM;
case PackagePartitions.PARTITION_OEM:
return SCAN_AS_OEM;
case PackagePartitions.PARTITION_PRODUCT:
return SCAN_AS_PRODUCT;
case PackagePartitions.PARTITION_SYSTEM_EXT:
return SCAN_AS_SYSTEM_EXT;
default:
throw new IllegalStateException("Unable to determine scan flag for "
+ partition.getFolder());
}
}
而上面的代码:
mDirsToScanAsSystem.addAll(SYSTEM_PARTITIONS);
中SYSTEM_PARTITIONS的初始化代码如下:
/**
* The list of all system partitions that may contain packages in ascending order of
* specificity (the more generic, the earlier in the list a partition appears).
*/
@VisibleForTesting(visibility = Visibility.PRIVATE)
public static final List<ScanPartition> SYSTEM_PARTITIONS = Collections.unmodifiableList(
PackagePartitions.getOrderedPartitions(ScanPartition::new));
注释表示返回的就是系统的所有分区。接着看一下PackagePartitions类中的getOrderdPartitions方法的代码:
/**
* Returns a list in which the elements are products of the specified function applied to the
* list of {@link #SYSTEM_PARTITIONS} in increasing specificity order.
*/
public static <T> ArrayList<T> getOrderedPartitions(
@NonNull Function<SystemPartition, T> producer) {
final ArrayList<T> out = new ArrayList<>();
for (int i = 0, n = SYSTEM_PARTITIONS.size(); i < n; i++) {
final T v = producer.apply(SYSTEM_PARTITIONS.get(i));
if (v != null) {
out.add(v);
}
}
return out;
}
SYSTEM_PARTITIONS的初始化代码:
/**
* The list of all system partitions that may contain packages in ascending order of
* specificity (the more generic, the earlier in the list a partition appears).
*/
private static final ArrayList<SystemPartition> SYSTEM_PARTITIONS =
new ArrayList<>(Arrays.asList(
new SystemPartition(Environment.getRootDirectory(), PARTITION_SYSTEM,
true /* containsPrivApp */, false /* containsOverlay */),
new SystemPartition(Environment.getVendorDirectory(), PARTITION_VENDOR,
true /* containsPrivApp */, true /* containsOverlay */),
new SystemPartition(Environment.getOdmDirectory(), PARTITION_ODM,
true /* containsPrivApp */, true /* containsOverlay */),
new SystemPartition(Environment.getOemDirectory(), PARTITION_OEM,
false /* containsPrivApp */, true /* containsOverlay */),
new SystemPartition(Environment.getProductDirectory(), PARTITION_PRODUCT,
true /* containsPrivApp */, true /* containsOverlay */),
new SystemPartition(Environment.getSystemExtDirectory(), PARTITION_SYSTEM_EXT,
true /* containsPrivApp */, true /* containsOverlay */)));
此处的注释又明确的指出是系统的所有分区。因此,在scanDirTracedLI方法中扫描的就是系统中所有路径的apk文件。
2. APK的扫描过程
2.1 PackageManagerService.java scanDirTracedLI()
从下面的函数可知,scanDirTracedLI的入口很简单,首先加入了一下systtrace的日志追踪,然后调用scanDirLI()进行分析
private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags, long
currentTime, PackageParser2 packageParser, ExecutorService executorService) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() +
"]");
try {
scanDirLI(scanDir, parseFlags, scanFlags, currentTime, packageParser, executorService);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
2.2 PackageManagerService.java scanDirLI()
scanDirLI()中使用了ParallelPackageParser的对象,ParallelPackageParser是一个队列,我们这里手机所有系统的apk,然后从这些队列里面取出apk,再调用PackageParser解析器进行解析。
private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime,
PackageParser2 packageParser, ExecutorService executorService) {
final File[] files = scanDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
Log.d(TAG, "No files in app dir " + scanDir);
return;
}
if (DEBUG_PACKAGE_SCANNING) {
Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags
+ " flags=0x" + Integer.toHexString(parseFlags));
}
// ParallelPackageParser是一个队列,收集系统 apk 文件,
// 然后从这个队列里面一个个取出apk,调用PackageParser解析
ParallelPackageParser parallelPackageParser =
new ParallelPackageParser(packageParser, executorService);
// Submit files for parsing in parallel
int fileCount = 0;
for (File file : files) {
// 是 apk文件,或者是目录
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
// 过滤掉非 apk 文件,如果不是则跳过继续扫描
if (!isPackage) {
// Ignore entries which are not packages
continue;
}
// 把 apk 信息存入ParallelPackageParser中的对象mQueue,
// parsePackage()函数赋予给了队列中的parsedPackage成员
parallelPackageParser.submit(file, parseFlags);
fileCount++;
}
// Process results one by one
for (; fileCount > 0; fileCount--) {
ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
Throwable throwable = parseResult.throwable;
int errorCode = PackageManager.INSTALL_SUCCEEDED;
if (throwable == null) {
// TODO(toddke): move lower in the scan chain
// Static shared libraries have synthetic package names
if (parseResult.parsedPackage.isStaticSharedLibrary()) {
renameStaticSharedLibraryPackage(parseResult.parsedPackage);
}
try {
addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,
currentTime, null);
} catch (PackageManagerException e) {
errorCode = e.error;
Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage());
}
} else if (throwable instanceof PackageParserException) {
PackageParserException e = (PackageParserException)
throwable;
errorCode = e.error;
Slog.w(TAG, "Failed to parse " + parseResult.scanFile + ": " + e.getMessage());
} else {
throw new IllegalStateException("Unexpected exception occurred while parsing "
+ parseResult.scanFile, throwable);
}
if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0 && errorCode != INSTALL_SUCCEEDED) {
mApexManager.reportErrorWithApkInApex(scanDir.getAbsolutePath());
}
// Delete invalid userdata apps
// 如果是非系统 apk 并且解析失败
if ((scanFlags & SCAN_AS_SYSTEM) == 0
&& errorCode != PackageManager.INSTALL_SUCCEEDED) {
logCriticalInfo(Log.WARN,
"Deleting invalid package at " + parseResult.scanFile);
// 非系统 Package 扫描失败,删除文件
removeCodePathLI(parseResult.scanFile);
}
}
}
2.3 ParallelPackageParser.java submit()
把扫描路径中的APK等内容,放入队列mQueue,并把parsePackage()赋值给ParseResult,用于后面的调用
public void submit(File scanFile, int parseFlags) {
mExecutorService.submit(() -> {
ParseResult pr = new ParseResult();
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parallel parsePackage [" + scanFile + "]");
try {
pr.scanFile = scanFile;
pr.parsedPackage = parsePackage(scanFile, parseFlags);
} catch (Throwable e) {
pr.throwable = e;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
try {
mQueue.put(pr);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// Propagate result to callers of take().
// This is helpful to prevent main thread from getting stuck waiting on
// ParallelPackageParser to finish in case of interruption
mInterruptedInThread = Thread.currentThread().getName();
}
});
}
通过parsePackage()调用到了PackageParser2.java中的parsePackage()进行apk的解析:
public ParsedPackage parsePackage(File packageFile, int flags, boolean useCaches)
throws PackageParserException {
if (useCaches && mCacher != null) {
ParsedPackage parsed = mCacher.getCachedResult(packageFile, flags);
if (parsed != null) {
return parsed;
}
}
long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
ParseInput input = mSharedResult.get().reset();
// 调用了ParsingPackageUtils的parsePackage方法,
ParseResult<ParsingPackage> result = parsingUtils.parsePackage(input, packageFile, flags);
if (result.isError()) {
throw new PackageParserException(result.getErrorCode(), result.getErrorMessage(),
result.getException());
}
ParsedPackage parsed = (ParsedPackage) result.getResult().hideAsParsed();
long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
if (mCacher != null) {
mCacher.cacheResult(packageFile, flags, parsed);
}
if (LOG_PARSE_TIMINGS) {
parseTime = cacheTime - parseTime;
cacheTime = SystemClock.uptimeMillis() - cacheTime;
if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
+ "ms, update_cache=" + cacheTime + " ms");
}
}
return parsed;
}
在parsePackage方法中调用到了ParsingPackageUtils.java的parsePackage方法:
public ParseResult<ParsingPackage> parsePackage(ParseInput input, File packageFile,
int flags)
throws PackageParserException {
if (packageFile.isDirectory()) {
// 如果传入的packageFile是目录,调用parseClustrPackage()解析
return parseClusterPackage(input, packageFile, flags);
} else {
// 如果是APK文件,就调用parseMonolithicPackage()解析
return parseMonolithicPackage(input, packageFile, flags);
}
}
先来看一下对目录的解析:
private ParseResult<ParsingPackage> parseClusterPackage(ParseInput input, File packageDir,
int flags) {
// 获取应用目录的PackageLite对象,这个对象分开保存了目录下的核心应用和非核心应用的名称
ParseResult<PackageParser.PackageLite> liteResult =
ApkLiteParseUtils.parseClusterPackageLite(input, packageDir, 0);
if (liteResult.isError()) {
return input.error(liteResult);
}
final PackageParser.PackageLite lite = liteResult.getResult();
// 如果lite中没有核心应用,退出
if (mOnlyCoreApps && !lite.coreApp) {
return input.error(INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED,
"Not a coreApp: " + packageDir);
}
// Build the split dependency tree.
// 构建分割的依赖项树
SparseArray<int[]> splitDependencies = null;
final SplitAssetLoader assetLoader;
if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
try {
splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
} catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
return input.error(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
}
} else {
assetLoader = new DefaultSplitAssetLoader(lite, flags);
}
try {
final AssetManager assets = assetLoader.getBaseAssetManager();
final File baseApk = new File(lite.baseCodePath);
// 对核心应用进行解析
ParseResult<ParsingPackage> result = parseBaseApk(input, baseApk,
lite.codePath, assets, flags);
if (result.isError()) {
return input.error(result);
}
ParsingPackage pkg = result.getResult();
if (!ArrayUtils.isEmpty(lite.splitNames)) {
pkg.asSplit(
lite.splitNames,
lite.splitCodePaths,
lite.splitRevisionCodes,
splitDependencies
);
final int num = lite.splitNames.length;
for (int i = 0; i < num; i++) {
final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
// 对非核心应用的处理
parseSplitApk(input, pkg, i, splitAssets, flags);
}
}
pkg.setUse32BitAbi(lite.use32bitAbi);
return input.success(pkg);
} catch (PackageParserException e) {
return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to load assets: " + lite.baseCodePath, e);
} finally {
IoUtils.closeQuietly(assetLoader);
}
}
再看parseMonolithicPackage(),它的作用是解析给定的APK文件,将其作为单个单块包处理。
最终也是调用parseBaseApk()进行解析,我们接下来看下parseBaseApk()
private ParseResult<ParsingPackage> parseMonolithicPackage(ParseInput input, File apkFile,
int flags) throws PackageParserException {
ParseResult<PackageParser.PackageLite> liteResult =
ApkLiteParseUtils.parseMonolithicPackageLite(input, apkFile, flags);
if (liteResult.isError()) {
return input.error(liteResult);
}
final PackageParser.PackageLite lite = liteResult.getResult();
if (mOnlyCoreApps && !lite.coreApp) {
return input.error(INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED,
"Not a coreApp: " + apkFile);
}
final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
try {
// 对核心应用解析
ParseResult<ParsingPackage> result = parseBaseApk(input,
apkFile,
apkFile.getCanonicalPath(),
assetLoader.getBaseAssetManager(), flags);
if (result.isError()) {
return input.error(result);
}
return input.success(result.getResult()
.setUse32BitAbi(lite.use32bitAbi));
} catch (IOException e) {
return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to get path: " + apkFile, e);
} finally {
IoUtils.closeQuietly(assetLoader);
}
}
parseBaseApk()主要是对AndroidManifest.xml进行解析,解析所有的信息放在Package对象中。
private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, File apkFile,
String codePath, AssetManager assets, int flags) {
final String apkPath = apkFile.getAbsolutePath();
.......
final int cookie = assets.findCookieForPath(apkPath);
if (cookie == 0) {
return input.error(INSTALL_PARSE_FAILED_BAD_MANIFEST,
"Failed adding asset path: " + apkPath);
}
// assets.openXmlResourceParser(...)。获得一个 XML 资源解析对象,
// 其中PackageParser.ANDROID_MANIFEST_FILENAME就是指的AndroidManifest.xml文件
try (XmlResourceParser parser = assets.openXmlResourceParser(cookie,
PackageParser.ANDROID_MANIFEST_FILENAME)) {
final Resources res = new Resources(assets, mDisplayMetrics, null);
// 再调用重载函数parseBaseApk
ParseResult<ParsingPackage> result = parseBaseApk(input, apkPath, codePath, res,
parser, flags);
final ParsingPackage pkg = result.getResult();
.......
pkg.setVolumeUuid(volumeUuid);
if ((flags & PackageParser.PARSE_COLLECT_CERTIFICATES) != 0) {
pkg.setSigningDetails(getSigningDetails(pkg, false));
} else {
pkg.setSigningDetails(SigningDetails.UNKNOWN);
}
return input.success(pkg);
} catch (Exception e) {
return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to read manifest from " + apkPath, e);
}
}
重载函数parseBaseApk()
private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, String apkPath,
String codePath, Resources res, XmlResourceParser parser, int flags)
throws XmlPullParserException, IOException, PackageParserException {
......
final TypedArray manifestArray = res.obtainAttributes(parser, R.styleable.AndroidManifest);
try {
final boolean isCoreApp =
parser.getAttributeBooleanValue(null, "coreApp", false);
final ParsingPackage pkg = mCallback.startParsingPackage(
pkgName, apkPath, codePath, manifestArray, isCoreApp);
// 调用parseBaseApkTags()
final ParseResult<ParsingPackage> result =
parseBaseApkTags(input, pkg, manifestArray, res, parser, flags);
if (result.isError()) {
return result;
}
return input.success(pkg);
} finally {
manifestArray.recycle();
}
}
在重载的parseBaseApk()中调用了,parseBaseApkTags()方法
private ParseResult<ParsingPackage> parseBaseApkTags(ParseInput input, ParsingPackage pkg,
TypedArray sa, Resources res, XmlResourceParser parser, int flags)
throws XmlPullParserException, IOException {
......
// 判断是是否是Application标签
if (PackageParser.TAG_APPLICATION.equals(tagName)) {
if (foundApp) {
if (PackageParser.RIGID_PARSER) {
result = input.error("<manifest> has more than one <application>");
} else {
Slog.w(TAG, "<manifest> has more than one <application>");
result = input.success(null);
}
} else {
foundApp = true;
// 是application标签,调用parseBaseApplication方法,解析application
result = parseBaseApplication(input, pkg, res, parser, flags);
}
} else {
// 如果不是application标签,调用parseBaseApkTag方法,解析核心应用的所有tag
result = parseBaseApkTag(tagName, input, pkg, res, parser, flags);
}
}
......
return input.success(pkg);
}
解析application标签,进入parseBaseApplication()方法:
private ParseResult<ParsingPackage> parseBaseApplication(ParseInput input,
ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags)
throws XmlPullParserException, IOException {
// .......
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG
|| parser.getDepth() > depth)) {
if (type != XmlPullParser.START_TAG) {
continue;
}
final ParseResult result;
// 获取 "application" 子标签的标签内容
String tagName = parser.getName();
boolean isActivity = false;
switch (tagName) {
// 如果标签是 "activity"
case "activity":
isActivity = true;
// fall-through
case "receiver":
// 如果标签是 "receiver",获取receiver信息
ParseResult<ParsedActivity> activityResult =
ParsedActivityUtils.parseActivityOrReceiver(mSeparateProcesses, pkg,
res, parser, flags, PackageParser.sUseRoundIcon, input);
if (activityResult.isSuccess()) {
ParsedActivity activity = activityResult.getResult();
if (isActivity) {
hasActivityOrder |= (activity.getOrder() != 0);
pkg.addActivity(activity);
} else {
hasReceiverOrder |= (activity.getOrder() != 0);
pkg.addReceiver(activity);
}
}
result = activityResult;
break;
case "service":
// 解析 "service"
ParseResult<ParsedService> serviceResult =
ParsedServiceUtils.parseService(mSeparateProcesses, pkg, res, parser,
flags, PackageParser.sUseRoundIcon, input);
if (serviceResult.isSuccess()) {
ParsedService service = serviceResult.getResult();
hasServiceOrder |= (service.getOrder() != 0);
pkg.addService(service);
}
result = serviceResult;
break;
case "provider":
// 解析 "provider"
ParseResult<ParsedProvider> providerResult =
ParsedProviderUtils.parseProvider(mSeparateProcesses, pkg, res, parser,
flags, PackageParser.sUseRoundIcon, input);
if (providerResult.isSuccess()) {
pkg.addProvider(providerResult.getResult());
}
result = providerResult;
break;
case "activity-alias":
// 解析 "activity-alias"
activityResult = ParsedActivityUtils.parseActivityAlias(pkg, res,
parser, PackageParser.sUseRoundIcon, input);
if (activityResult.isSuccess()) {
ParsedActivity activity = activityResult.getResult();
hasActivityOrder |= (activity.getOrder() != 0);
pkg.addActivity(activity);
}
result = activityResult;
break;
default:
result = parseBaseAppChildTag(input, tagName, pkg, res, parser, flags);
break;
}
}
//.......
return input.success(pkg);
}
2.4 PackageManagerService.java scanDirLI()方法中,调用了addForInitLI()方法,
调用addForInitLI()在platform初始化时,把package内容加入到内部数据结构。在此方法中,进行安装包的校验、签名检查、apk更新等操作,把Package加入到系统中。
private AndroidPackage addForInitLI(ParsedPackage parsedPackage,
@ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
@Nullable UserHandle user)
throws PackageManagerException {
// 判断系统应用是否需要更新
synchronized (mLock) {
if (scanSystemPartition) {
if (isSystemPkgUpdated) {
//......
}
}
}
if (isSystemPkgBetter) {
// 更新安装包到 system 分区中
synchronized (mLock) {
// just remove the loaded entries from package lists
mPackages.remove(pkgSetting.name);
}
// 创建安装参数 InstallArgs
final InstallArgs args = createInstallArgsForExisting(
pkgSetting.codePathString,
pkgSetting.resourcePathString, getAppDexInstructionSets(
pkgSetting.primaryCpuAbiString, pkgSetting.secondaryCpuAbiString));
args.cleanUpResourcesLI();
synchronized (mLock) {
mSettings.enableSystemPackageLPw(pkgSetting.name);
}
}
// 安装包校验
collectCertificatesLI(pkgSetting, parsedPackage, forceCollect, skipVerify);
try (@SuppressWarnings("unused") PackageFreezer freezer = freezePackage(
parsedPackage.getPackageName(),
"scanPackageInternalLI")) {
// 如果两个apk签名不匹配,则调用 deletePackageLIF 方法清除 apk 文件及其数据
deletePackageLIF(parsedPackage.getPackageName(), null, true, null, 0, null,
false, null);
}
pkgSetting = null;
} else if (newPkgVersionGreater) {
// 更新系统 apk 程序
InstallArgs args = createInstallArgsForExisting(
pkgSetting.codePathString,
pkgSetting.resourcePathString, getAppDexInstructionSets(
pkgSetting.primaryCpuAbiString, pkgSetting.secondaryCpuAbiString));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
}
}
// 如果新安装的系统 app 会被旧的 APP 数据覆盖,所以需要隐藏系统应用程序,并重新扫描 /data/app 目录
if (shouldHideSystemApp) {
synchronized (mLock) {
mSettings.disableSystemPackageLPw(parsedPackage.getPackageName(), true);
}
}
return scanResult.pkgSetting.pkg;
}
APK扫描过程就分析完了,其实Android 10.0 和 Android 11.0的扫描过程大体是一致的,不过就是其中的一些细节还是有些从差别。在这里推荐一篇以Android 10.0为基础的分析文章,讲的不错。
https://blog.csdn.net/yiranfeng/article/details/103961304
谢谢大家!