This article is just a guide to the PkMS. It will not post a large chunk of code for analysis, but more based on method analysis of the implementation logic. In addition, the code is based on Android 11, which is quite different from the code before Android 10.
Content of this article
- How does the PkMS know the location of the APK
- The difference between system application and ordinary application
- Application scanning process and application information preservation
How does the PkMS know where the APK is
The answer is according to the path. For mobile phone users, the installed applications are placed in /data/app, while for system applications, they are distributed in various partitions, which can be simply regarded as directories, and /data is the data partition. The following partitions will be scanned, and only the priv-app and app directories will be scanned:
- Priv-app, app directory in the System partition
/system/priv-app
./system/app
- The product division
- Odm partition
- OEM partition
- Vendor partition
- System_ext partition
- Data partition, and finally scan
However, these partitions are not very strict implementation, do not involve the GMS test of the basic care, so where does APK exist? For example: Settings on/system_ext/priv – app/Settings/Settings. The apk, other partitions are similar, the analysis of application of the scanning process will also said. Here, why do we scan priv-app and app directories? Priv – app mean inside this directory are ring application, access privilege rights, the definition of permissions frameworks/base/core/res/AndroidManifest. Found in XML
The difference between system application and ordinary application
The answer is path. Applications in the data partition are common applications, and applications installed in other partitions are system applications. System applications cannot be uninstalled
Application scanning process
scanDirLI()
The parameters of scanDirLI are described.
- ScanDir: collection of application directories. For example, Settings
/system_ext/priv-app
- ScanFlags: indicates the scanning flag, which is added when the system is used
SCAN_AS_SYSTEM
Flag, plus if it’s a priv-app directorySCAN_AS_PRIVILGED
- PackageParser is the main utility class for parsing AndroidManifest.xml
- ExecutorService, the producer thread
ScanDirLI’s logic is simpler,
- In the above
/system_ext/priv-app
For example, walk through each directory and APK in the directory - Parse all directories and APK using ExecutorService(thread pool). See the PkMS Parse Package guide for details
- Get the ParsedPackage and make the call
addForInitLI()
addForInitLI()
The logic is quite complex, consider the situation to also want a lot of, some oneself also did not understand, just pick can say
-
First, the logic of renaming the package name. In PkMS, all packages use the package name as the unique primary key, so the application may need to change the package name. PkMS solution is given with the < the original – package android: name = “com. Android. Oldpackagename” / > indicate the need to cover installation package names, but need to take into account many situation just the way they are
- What if the package name is changed multiple times
- The handling of applications that have previously installed the old package name
- Handling of applications with old package names that have not been installed before
- Processing of applications that have previously installed the current package name
So what does PkMS do?
-
OriginalPackages: originalPackages: originalPackages: originalPackages: originalPackages: originalPackages: originalPackages: originalPackages
//ParsingPackageUtils.parseOriginalPackage() String orig = sa.getNonConfigurationString( R.styleable.AndroidManifestOriginalPackage_name, 0); if(! pkg.getPackageName().equals(orig)) {if (pkg.getOriginalPackages().isEmpty()) { pkg.setRealPackage(pkg.getPackageName()); } pkg.addOriginalPackage(orig); } Copy the code
-
Then get originalPkgSetting based on realPkgName in addForInitLI()
-
Next, determine whether to overwrite the installed application
The PackageInstaller and PermissionController are designed to replace apps in the AOSP with GMS apps. They are not universal, and if they are tagged, they will still be considered as two apps
-
What is an overwritten installation system application? The system application is updated and can be downloaded through the app store to cover the installation, but the system application is not uninstalled, but disable the system application, such as Google’s GMS application
-
If the installed application is faulty, enable the disabled application again
-
If the application isa system update, the disabled application needs to be scanned because the OTA upgrade may cause the system application to update apK. In this case, call scanPackageOnlyLI() to scan, which will be analyzed later
-
Next, determine whether to reuse the system application based on the version of the disabled application and the installed application
-
-
Handle signatures, which are required for installed applications
- This part of the AOSP is not written at all. The second part in the comment is not implemented yet
// Verify certificates against what was last scanned. Force re-collecting certificate in two // special cases: // 1) when scanning system, force re-collect only if system is upgrading. // 2) when scannning /data, force re-collect only if the app is privileged (updated from // preinstall, or treated as privileged, e.g. due to shared user ID). final boolean forceCollect = scanSystemPartition ? mIsUpgrade : PackageManagerServiceUtils.isApkVerificationForced(pkgSetting); Copy the code
- Whether to skip signature verification, this is used when overwriting installation
// Full APK verification can be skipped during certificate collection, only if the file is // in verified partition, or can be verified on access (when apk verity is enabled). In both // cases, only data in Signing Block is verified instead of the whole file. // TODO(b/136132412): skip for Incremental installation final boolean skipVerify = scanSystemPartition || (forceCollect && canSkipForcedPackageVerification(parsedPackage)); collectCertificatesLI(pkgSetting, parsedPackage, forceCollect, skipVerify); Copy the code
-
We also deal with the reverse of step 3, where there is an installed application (data partition) and then an OTA upgrade that adds the system application (system or other partition), which is discussed in three scenarios
- If the signatures are different, uninstall the applications in the data partition
- If the version of the system application is higher, the application in the data partition is removed, but the data of the application is retained
- If the version number used by the system is lower, the
shouldHideSystemApp
Set to true to apply to the disable system below
-
Call scanPackageNewLI() to continue the scan
-
ReconcilePackagesLocked () is invoked for reconciliation
-
Call commitReconciledScanResultLocked ()
scanPackageNewLI()
It is important to note that this method is not only used during startup scanning, but also when installing the application
- Rename the package again, this should be related to the installation, when I test the overwrite installation system application is valid, the normal application is not valid, will be considered as two applications
- call
adjustFlags()
To readjustscanFlags
, can be divided into the following situations- The application that renames the package name application or overrides the installation is the system application, and scanFlags is added to it
SCAN_AS_SYSTEM
And possibly other flags - If the Privilege application is included in sharedUserId, the application being scanned must be added as well
SCAN_AS_PRIVILEGED
- The application that renames the package name application or overrides the installation is the system application, and scanFlags is added to it
- To obtain
SharedUserSetting
At theaddForInitLI()
Obtained once for scanning disabledPkgSetting - build
ScanRequest
And callscanPackageOnlyLI()
To obtainScanResult
scanPackageOnlyLI()
The main logic in this section is to update the interpretation of packageSetting and library
- Determine if you need to get the ABI (
needToDeriveAbi
), if packageSetting, if the application is installed, there is no need to change the cpuAbi, and if not, parse the native library - Get the
tag. I don’t know what it is. I haven’t seen it yet
- Update or create a new
PackageSetting
, there are two types of creation, the first installation of the application or factory restore boot - According to the first step
needToDeriveAbi
Get the type of abi and set it in PackageSetting. Another thing is to parse the native SO library in APK and get the path to the corresponding SO library. Here is aSCAN_NEW_INSTALL
Flag, this is for installation, scan will not cause this problem - Set the timestamp of the installation, primarily the first and current installation. The use of this property is unknown at this time
- create
ScanResult
And return
reconcilePackagesLocked()
Let’s start with a few parameters:
ReconcileRequest
AllPackages ->mPackages, scannedPackages->scanPackageOnlyLI() SharedLibrarySource ->mSharedLibraries will push only after being parsedKeySetManagerService
Signature Management Service
ReconcilePackagesLocked () is also invoked by the process that installed the application, so some of the arguments from ReconcileRequest are for them, and the main function of this method is to verify signatures
- First check whether the signature needs to be updated
ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)
This is not very understandable, the signature can be updated? - call
verifySignatures()
Verify signature - The last generation
ReconciledPackage
And return
commitReconciledScanResultLocked()
This is also a method that is called both when you install the application and when you scan the application. Let’s just look at the scanning case
- Dealing with PackageSetting, this part of the logic is mixed up with the installation application, mainly including
- SharedUserSetting, this is usually only overridden if the sharedUserId has changed
- The logics for renaming packages are updated when the installation renames the package
- Write PackageSetting into package-restrictions. XML, which stores the four major components: disabled and Enabled
- The last call
commitPackageSettings()
Proceed to the last step
commitPackageSettings()
- Determine if there is a vendor defined ResolveActivity(
config_customResolverActivity
Property), if anysetUpCustomResolverActivity()
When you set the ResolveActivity to be custom, the ResolveActivity handles unspecified tasksandroid.action.View
the - Handle the ResolveActivity, specifying the framework ResolveActivity if none is available
- Update SharedLibraries, which is unfamiliar
- Check whether the Frozen application is required. If yes but no Frozen is available, exit the installation. The Frozen application is not required in the following cases
- SCAN_BOOTING, at boot time, because there are no applications to boot
- SCAN_DONT_KILL_APP, install does not kill the app, this is usually either specified in PkMS or at ADB installation time
- SCAN_IGNORE_FROZEN, ignore FROZEN, this option is not even specified by ADB, it may be the code left behind
- call
mSettings.insertPackageSettingLPw()
.This is not the place to update packages.xml, just put the pkgSetting in settings.mpackages - Put AndroidPackage in mPackages
- Update application information for KeySetManagerService, a service that manages signatures
- Add custom Permission and PermissionGroup to PermissionManagerService
- Add protected broadcasts, not for installation applications, but for system applications, such as teleservice, etc
- Update permissions for applications that have applied for these permissions. Note that these permissions are also defined by the application
What needs to be done after the scan is done
- Delete the deleted system applications and disable the disable applications
- call
PermissionManagerService.updateAllPermissions()
Update permissions, which are not performed until all application scans have been completed - Create a directory for the application data store. Note that this operation is only for System core applications (such as SystemUI). Applications under data have multiple users and each data application is for a single user.
- Finally, the PackageSetting, permission and signature fingerprint were written into PackageSetting. XML. I think this design should be to avoid shutdown in the middle, so that writing all the information at once can minimize shutdown in half