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(),

本文深入剖析了Android系统中PackageManagerService如何扫描系统路径下的所有APK文件,从Android10.0到Android11.0的路径变化,以及 APK 的扫描过程。首先,通过遍历系统所有分区并调用scanDirTracedLI方法进行扫描。接着,解析过程中,使用ParallelPackageParser队列收集系统apk,逐个进行PackageParser解析。最后,解析完成后,进行校验、签名检查和更新操作。整个过程涉及系统分区、文件遍历、XML解析和包管理等多个关键步骤。
最低0.47元/天 解锁文章
524

被折叠的 条评论
为什么被折叠?



