一、PMS概述
PKMS构造函数的主要功能:扫描Android系统中几个目标文件夹中的APK,从而建立合适的数据结构以管理诸如Package信息、四大组件信息、权限信息等各种信息。抽象地看,PKMS像一个加工厂,它解析实际的物理文件(APK文件)以生成符合自己要求的产品。例如,PKMS将解析APK包中的AndroidManifest.xml,并根据其中声明的Activity标签来创建与此对应的对象并加以保管,文章牵涉到的源码来自Android 8.0。
二、系统应用启动安装流程图
三、PMS初始化
PMS作为系统服务,在SystemServer中启动
frameworks/base/services/java/com/android/server/SystemServer.java
private void startBootstrapServices() {
//关联一个系统的installd守护进程
Installer installer = mSystemServiceManager.startService(Installer.class);
//PMS 初始化调用的地方,
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
//只有在加密设备时mOnlyCore才为true
}
Installer是一个负责创建,移除,更新数据目录,优化应用的系统服务。
PMS的main方法
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
ServiceManager.addService("package", m);
//把自己添加到系统服务
return m;
}
PMS构造方法主要功能
向设置中添加系统默认的共享ID(system、phone、log、nfc、bluetooth、shell、se等)
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
.....
mSettings = new Settings(mPackages);
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
刚进入构造函数,就会遇到第一个较为复杂的数据结构Setting及它的addShared-User-LPw函数
frameworks/base/services/core/java/com/android/server/pm/Settings.java
//添加一个以name为键,以SharedUserSetting为值键值对
ArrayMap<String, SharedUserSetting> mSharedUsers = new
ArrayMap<String, SharedUserSetting>();
SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
SharedUserSetting s = mSharedUsers.get(name);
if (s != null) {
if (s.userId == uid) {
return s;
}
return null;
}
s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
s.userId = uid;
if (addUserIdLPw(uid, s, name)) {
mSharedUsers.put(name, s);
return s;
}
return null;
}
//添加一个以uid为键,以SharedUserSetting为值键值对
SparseArray<Object> mOtherUserIds = new SparseArray<Object>();
private boolean addUserIdLPw(int uid, Object obj, Object name) {
if (uid > Process.LAST_APPLICATION_UID) {
return false;
}
if (uid >= Process.FIRST_APPLICATION_UID) {
int N = mUserIds.size();
final int index = uid - Process.FIRST_APPLICATION_UID;
while (index >= N) {
mUserIds.add(null);
N++;
}
if (mUserIds.get(index) != null) {
return false;
}
mUserIds.set(index, obj);
} else {
if (mOtherUserIds.get(uid) != null) {
return false;
}
mOtherUserIds.put(uid, obj);
}
return true;
}
sharedUserId的作用:
1.两个或多个声明了同一种sharedUserId的APK可共享彼此的数据,并且可运行在同一进程中。
2.更重要的是,通过声明特定的sharedUserId,该APK所在进程将被赋予指定的UID。
提示除了在AndroidManifest.xml中声明sharedUserId外,APK在编译时还必须使用对应的证书进行签名。
下面继续分析PKMS的构造函数,代码如下
初始化成员变量,如Installer、PackageDexOptimizer、DexManager、MoveCallbacks、OnPermissionChangeListeners等,并获取系统配置。
mInstaller = installer;
mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
"*dexopt*");
mDexManager = new DexManager(this, mPackageDexOptimizer, installer, mInstallLock);
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
mOnPermissionChangeListeners = new OnPermissionChangeListeners(
FgThread.get().getLooper());
getDefaultDisplayMetrics(context, mMetrics);
//获取系统配置,保存配置到PMS中
SystemConfig systemConfig = SystemConfig.getInstance();
mGlobalGids = systemConfig.getGlobalGids();
mSystemPermissions = systemConfig.getSystemPermissions();
mAvailableFeatures = systemConfig.getAvailableFeatures();
//过程比较简单,自行研究
下面继续分析PKMS的构造函数,代码如下
synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
//启动一个服务类线程。
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper());
//初始化用户管理服务
sUserManager = new UserManagerService(context, this,
new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore),
mPackages);
//将权限配置传入包管理器
ArrayMap<String, SystemConfig.PermissionEntry> permConfig
= systemConfig.getPermissions();
for (int i=0; i<permConfig.size(); i++) {
SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
BasePermission bp = mSettings.mPermissions.get(perm.name);
if (bp == null) {
bp = new BasePermission(perm.name, "android",
BasePermission.TYPE_BUILTIN);
mSettings.mPermissions.put(perm.name, bp);
}
if (perm.gids != null) {
bp.setGids(perm.gids, perm.perUser);
}
}
//将共享库传入包管理器
ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
final int builtInLibCount = libConfig.size();
for (int i = 0; i < builtInLibCount; i++) {
String name = libConfig.keyAt(i);
String path = libConfig.valueAt(i);
addSharedLibraryLPw(path, null, name,
SharedLibraryInfo.VERSION_UNDEFINED,
SharedLibraryInfo.TYPE_BUILTIN, PLATFORM_PACKAGE_NAME, 0);
}
mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
//是否是第一次启动
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
//清除代码路径不存在的孤立包
final int packageSettingCount = mSettings.mPackages.size();
for (int i = packageSettingCount - 1; i >= 0; i--) {
PackageSetting ps = mSettings.mPackages.valueAt(i);
if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
&& mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
mSettings.mPackages.removeAt(i);
mSettings.enableSystemPackageLPw(ps.name);
}
}
//准备包解析缓存
mCacheDir = preparePackageParserCache(mIsUpgrade);
下面继续分析PKMS的构造函数,代码如下
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
//设置标志监视和不改变apk文件路径时扫描安装目录。
int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
if (mIsUpgrade || mFirstBoot) {
scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}
//在扫描应用前,扫描手机供应商的覆盖安装包(/overlay)
scanDirTracedLI(new File(VENDOR_OVERLAY_DIR), mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags |
SCAN_TRUSTED_OVERLAY, 0);
mParallelPackageParserCallback.findStaticOverlayPackages();
//扫描应用目录,依次为特权系统目录 priv-app、普通目录 app、供应商系统目录
//vendor/app oem等
scanDirTracedLI(frameworkDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanFlags | SCAN_NO_DEX, 0);
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-
app");
scanDirTracedLI(privilegedAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
File vendorAppDir = new File("/vendor/app");
try {
vendorAppDir = vendorAppDir.getCanonicalFile();
} catch (IOException e) {
}
scanDirTracedLI(vendorAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
scanDirTracedLI为安装的主要流程,稍后集中分析,我们接着看构造方法。
//删除任何不再存在的系统包。
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
//存根包必须在/data分区中用完整版本替换,或者禁用。
final List<String> stubSystemApps = new ArrayList<>();
if (!mOnlyCore) {
final Iterator<PackageParser.Package> pkgIterator =
mPackages.values().iterator();
while (pkgIterator.hasNext()) {
final PackageParser.Package pkg = pkgIterator.next();
if (pkg.isStub) {
stubSystemApps.add(pkg.packageName);
}
}
final Iterator<PackageSetting> psit =
mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();
//如果包裹被扫描,它不会被删除。
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
//如果系统应用程序被扫描并且在禁用包列表中,那么它一定是通过OTA添加的。
//将其从当前扫描的包中删除,以便可以扫描之前用户安装的应用程序。
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
removePackageLI(scannedPkg, true);
mExpectingBetter.put(ps.name, ps.codePath);
}
continue;
}
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
psit.remove();
} else {
final PackageSetting disabledPs =
mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()
|| disabledPs.pkg == null) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
}
}
//寻找任何不完整的包安装,清理未完全安装的应用程序
ArrayList<PackageSetting> deletePkgsList =
mSettings.getListOfIncompleteInstallPackagesLPr();
for (int i = 0; i < deletePkgsList.size(); i++) {
final String packageName = deletePkgsList.get(i).name;
synchronized (mPackages) {
mSettings.removePackageLPw(packageName);
}
}
//删除tmp文件
deleteTempPackageFiles();
final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get();
//删除任何没有关联包的共享用户id
mSettings.pruneSharedUsersLPw();
final long systemScanTime = SystemClock.uptimeMillis() - startTime;
final int systemPackagesCount = mPackages.size();
if (!mOnlyCore) {
scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
| PackageParser.PARSE_FORWARD_LOCK,
scanFlags | SCAN_REQUIRE_KNOWN, 0);
//删除已通过OTA删除的更新系统应用程序的禁用包设置。如果更新不再存在,
//完全删除应用程序。否则,撤销他们的系统特权
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
mSettings.removeDisabledSystemPackageLPw(deletedAppName);
final String msg;
if (deletedPkg == null) {
//代码和数据的实际删除将由后面的econciliation步骤处理
} else {
final PackageSetting deletedPs =
mSettings.mPackages.get(deletedAppName);
//取消系统的特权
deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
}
}
//确保我们期望出现在userdata分区上的所有系统应用程序都实际出现了。
//如果它们没有出现,返回去恢复系统版本。
for (int i = 0; i < mExpectingBetter.size(); i++) {
final String packageName = mExpectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
final File scanFile = mExpectingBetter.valueAt(i);
int reparseFlags = mDefParseFlags;
if (FileUtils.contains(privilegedAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED;
} else if (FileUtils.contains(systemAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else if (FileUtils.contains(vendorAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else if (FileUtils.contains(oemAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else {
continue;
}
mSettings.enableSystemPackageLPw(packageName);
try {
scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0,
null);
} catch (PackageManagerException e) {
}
}
}
//解压并安装任何存根系统应用程序。这必须在最后完成,以确保替换或禁用所有存根。
decompressSystemApplications(stubSystemApps, scanFlags);
final int cachedNonSystemApps =
PackageParser.sCachedPackageReadCount.get()
- cachedSystemApps;
final long dataScanTime = SystemClock.uptimeMillis() - systemScanTime - startTime;
final int dataPackagesCount = mPackages.size() - systemPackagesCount;
}
mExpectingBetter.clear();
//既然我们知道了所有的共享库,那么就更新所有客户以获得正确的库路径。
updateAllSharedLibrariesLPw(null);
for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
adjustCpuAbisForSharedUserLPw(setting.packages, null /*scannedPackage*/);
}
//现在我们知道了所有要保存的包,读取和更新它们的最后使用时间。
mPackageUsage.read(mPackages);
mCompilerStats.read();
int updateFlags = UPDATE_PERMISSIONS_ALL;
if (ver.sdkVersion != mSdkVersion) {
updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG |
UPDATE_PERMISSIONS_REPLACE_ALL;
}
//更新权限
updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
ver.sdkVersion = mSdkVersion;
//安装应用,完成后检查webview,默认浏览器等。
if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
for (UserInfo user : sUserManager.getUsers(true)) {
mSettings.applyDefaultPreferredAppsLPw(this, user.id);
applyFactoryDefaultBrowserLPw(user.id);
primeDomainVerificationsLPw(user.id);
}
}
//在引导期间尽早为系统用户准备存储,因为像SettingsProvider和SystemUI这样的核心系统应用程序不能等待用户启动
final int storageFlags;
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
storageFlags = StorageManager.FLAG_STORAGE_DE;
} else {
storageFlags = StorageManager.FLAG_STORAGE_DE |
StorageManager.FLAG_STORAGE_CE;
}
List<String> deferPackages =
reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,
UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
true /* onlyCoreApps */);
mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
try {
mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL,
StorageManager.FLAG_STORAGE_DE |
StorageManager.FLAG_STORAGE_CE);
} catch (InstallerException e) {
}
if (deferPackages == null || deferPackages.isEmpty()) {
return;
}
int count = 0;
for (String pkgName : deferPackages) {
PackageParser.Package pkg = null;
synchronized (mPackages) {
PackageSetting ps = mSettings.getPackageLPr(pkgName);
if (ps != null && ps.getInstalled(UserHandle.USER_SYSTEM)) {
pkg = ps.pkg;
}
}
if (pkg != null) {
synchronized (mInstallLock) {
//创建应用数据目录
prepareAppDataAndMigrateLIF(pkg, UserHandle.USER_SYSTEM,
storageFlags,true /* maybeMigrateAppData */);
}
count++;
}
}
}, "prepareAppData");
//如果这是OTA之后的第一次引导,并且是正常引导,那么我们需要清除代码缓存目录
if (mIsUpgrade && !onlyCore) {
for (int i = 0; i < mSettings.mPackages.size(); i++) {
final PackageSetting ps = mSettings.mPackages.valueAt(i);
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL,
ps.volumeUuid)) {
clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
StorageManager.FLAG_STORAGE_DE |
StorageManager.FLAG_STORAGE_CE
| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
}
ver.fingerprint = Build.FINGERPRINT;
}
checkDefaultBrowser();
//只有在权限和其他默认值已更新后才清除
mExistingSystemPackages.clear();
mPromoteSystemApps = false;
//所有的更改都是在包扫描期间完成的。
ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;
//写应用程序配置到设置
mSettings.writeLPr();
if (!mOnlyCore) {
mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr();
mRequiredInstallerPackage = getRequiredInstallerLPr();
mRequiredUninstallerPackage = getRequiredUninstallerLPr();
mIntentFilterVerifierComponent =
getIntentFilterVerifierComponentNameLPr();
if (mIntentFilterVerifierComponent != null) {
mIntentFilterVerifier = new IntentVerifierProxy(mContext,
mIntentFilterVerifierComponent);
} else {
mIntentFilterVerifier = null;
}
mServicesSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES,
SharedLibraryInfo.VERSION_UNDEFINED);
mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
PackageManager.SYSTEM_SHARED_LIBRARY_SHARED,
SharedLibraryInfo.VERSION_UNDEFINED);
} else {
mRequiredVerifierPackage = null;
mRequiredInstallerPackage = null;
mRequiredUninstallerPackage = null;
mIntentFilterVerifierComponent = null;
mIntentFilterVerifier = null;
mServicesSystemSharedLibraryPackageName = null;
mSharedSystemSharedLibraryPackageName = null;
}
mInstallerService = new PackageInstallerService(context, this);
final Pair<ComponentName, String> instantAppResolverComponent =
getInstantAppResolverLPr();
if (instantAppResolverComponent != null) {
mInstantAppResolverConnection = new EphemeralResolverConnection(
mContext, instantAppResolverComponent.first,
instantAppResolverComponent.second);
mInstantAppResolverSettingsComponent =
getInstantAppResolverSettingsLPr(instantAppResolverComponent.first);
} else {
mInstantAppResolverConnection = null;
mInstantAppResolverSettingsComponent = null;
}
updateInstantAppInstallerLocked(null);
//读取和更新dex文件的使用。在PM init结束时执行此操作,以便所有包的数据目录都已协调。
//此时,我们知道了包的代码路径,因此可以验证磁盘文件并构建内部缓存
final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
for (int userId : currentUserIds) {
userPackages.put(userId, getInstalledPackages(/*flags*/ 0,
userId).getList());
}
mDexManager.load(userPackages);
if (mIsUpgrade) {
MetricsLogger.histogram(null, "ota_package_manager_init_time",
(int) (SystemClock.uptimeMillis() - startTime));
}
} // synchronized (mPackages)
} // synchronized (mInstallLock)
Runtime.getRuntime().gc();
FallbackCategoryProvider.loadFallbacks();
mInstaller.setWarnIfHeld(mPackages);
//向系统组件暴露私有服务
LocalServices.addService(PackageManagerInternal.class, new
PackageManagerInternalImpl());
}
以上为PMS大致流程、接着我们看scanDirTracedLI这个方法。
public void scanDirTracedLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
try {
scanDirLI(dir, parseFlags, scanFlags, currentTime);
} finally {
}
}
内部调用了scanDirLI这个方法。
private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
final File[] files = dir.listFiles();
//创建平行包解析工具
ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
mParallelPackageParserCallback);
int fileCount = 0;
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
//这里提交一个解析任务,
parallelPackageParser.submit(file, parseFlags);
fileCount++;
}
接着上面parallelPackageParser.submit(file, parseFlags)分析
frameworks/base/services/core/java/com/android/server/pm/ParallelPackageParser.java
public void submit(File scanFile, int parseFlags) {
//在线程池提交了一个任务
mService.submit(() -> {
//解析结果
ParseResult pr = new ParseResult();
try {
//创建一个包解析对象
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
pp.setCacheDir(mCacheDir);
pp.setCallback(mPackageParserCallback);
pr.scanFile = scanFile;
//调用parsePackage方法
pr.pkg = parsePackage(pp, scanFile, parseFlags);
} catch (Throwable e) {
pr.throwable = e;
} finally {
}
try {
把包解析对象放入队列中
mQueue.put(pr);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
mInterruptedInThread = Thread.currentThread().getName();
}
});
}
protected PackageParser.Package parsePackage(PackageParser packageParser, File scanFile,
int parseFlags) throws PackageParser.PackageParserException {
调用包解析parsePackage方法
return packageParser.parsePackage(scanFile, parseFlags, true /* useCaches */);
}
接着看PackageParser 的parsePackage()方法
frameworks/base/core/java/android/content/pm/PackageParser.java
public Package parsePackage(File packageFile, int flags, boolean useCaches)
throws PackageParserException {
//从缓冲中获取
Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
if (parsed != null) {
return parsed;
}
long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
if (packageFile.isDirectory()) {
//如果是目录走这里
parsed = parseClusterPackage(packageFile, flags);
} else {
parsed = parseMonolithicPackage(packageFile, flags);
}
//缓冲结果
cacheResult(packageFile, flags, parsed);
return parsed;
}
接着看PackageParser的parseClusterPackage方法
frameworks/base/core/java/android/content/pm/PackageParser.java
private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
//轻量级解析,获取包名,版本号等
final PackageLite lite = parseClusterPackageLite(packageDir, 0);
assetLoader = new DefaultSplitAssetLoader(lite, flags);
try {
final AssetManager assets = assetLoader.getBaseAssetManager();
final File baseApk = new File(lite.baseCodePath);
//调用parseBaseApk方法
final Package pkg = parseBaseApk(baseApk, assets, flags);
pkg.setCodePath(packageDir.getAbsolutePath());
pkg.setUse32bitAbi(lite.use32bitAbi);
return pkg;
} finally {
IoUtils.closeQuietly(assetLoader);
}
}
接着看PackageParser的parseBaseApk方法
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
String volumeUuid = null;
if (apkPath.startsWith(MNT_EXPAND)) {
final int end = apkPath.indexOf('/', MNT_EXPAND.length());
volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
}
mParseError = PackageManager.INSTALL_SUCCEEDED;
mArchiveSourcePath = apkFile.getAbsolutePath();
final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
Resources res = null;
XmlResourceParser parser = null;
try {
res = new Resources(assets, mMetrics, null);
//创建xml解析器
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final String[] outError = new String[1];
//调用同名重载方法
final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
pkg.setVolumeUuid(volumeUuid);
pkg.setApplicationVolumeUuid(volumeUuid);
pkg.setBaseCodePath(apkPath);
pkg.setSignatures(null);
return pkg;
} catch (PackageParserException e) {
throw e;
} catch (Exception e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to read manifest from " + apkPath, e);
} finally {
IoUtils.closeQuietly(parser);
}
}
接着看PackageParser的parseBaseApk重载方法
private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
String[] outError) throws XmlPullParserException, IOException {
final String splitName;
final String pkgName;
try {
Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
pkgName = packageSplit.first;
splitName = packageSplit.second;
if (!TextUtils.isEmpty(splitName)) {
outError[0] = "Expected base APK, but found split " + splitName;
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
return null;
}
} catch (PackageParserException e) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
return null;
}
if (mCallback != null) {
String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
if (overlayPaths != null && overlayPaths.length > 0) {
for (String overlayPath : overlayPaths) {
res.getAssets().addOverlayPath(overlayPath);
}
}
}
//创建包,从TypedArray 中获取AndroidManifest的属性填充Package
final Package pkg = new Package(pkgName);
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifest);
pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
pkg.baseRevisionCode = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
pkg.mVersionName = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifest_versionName, 0);
if (pkg.mVersionName != null) {
pkg.mVersionName = pkg.mVersionName.intern();
}
pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
sa.recycle();
//调用parseBaseApkCommon
return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
}
接着看PackageParser的parseBaseApkCommon方法,解析的核心方法。
private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
IOException {
mParseInstrumentationArgs = null;
int type;
boolean foundApp = false;
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifest);
//获取sharedUserId
String str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
if (str != null && str.length() > 0) {
if ((flags & PARSE_IS_EPHEMERAL) != 0) {
outError[0] = "sharedUserId not allowed in ephemeral application";
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
return null;
}
String nameError = validateName(str, true, false);
if (nameError != null && !"android".equals(pkg.packageName)) {
outError[0] = "<manifest> specifies bad sharedUserId name \""
+ str + "\": " + nameError;
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
return null;
}
pkg.mSharedUserId = str.intern();
//获取sharedUserId的标签
pkg.mSharedUserLabel = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
}
//获取要安装app的位置
pkg.installLocation = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_installLocation,
PARSE_DEFAULT_INSTALL_LOCATION);
pkg.applicationInfo.installLocation = pkg.installLocation;
//获取安装沙箱的版本号
final int targetSandboxVersion = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
PARSE_DEFAULT_TARGET_SANDBOX);
pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
/* Set the global "forward lock" flag */
if ((flags & PARSE_FORWARD_LOCK) != 0) {
pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
}
/* Set the global "on SD card" flag */
if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
}
if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
}
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
if (acceptedTags != null && !acceptedTags.contains(tagName)) {
XmlUtils.skipCurrentTag(parser);
continue;
}
if (tagName.equals(TAG_APPLICATION)) {
if (foundApp) {
if (RIGID_PARSER) {
outError[0] = "<manifest> has more than one <application>";
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
} else {
Slog.w(TAG, "<manifest> has more than one <application>");
XmlUtils.skipCurrentTag(parser);
continue;
}
}
foundApp = true;
//这里只分析application标签,其他标签类似,自行分析。
if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
return null;
}
}
return pkg;
}
接着看PackageParser的parseBaseApplication方法
private boolean parseBaseApplication(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
final ApplicationInfo ai = owner.applicationInfo;
final String pkgName = owner.applicationInfo.packageName;
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestApplication);
if (ai.name != null) {
ai.className = ai.name;
}
...解析了一大堆Application属性
sa.recycle();
final int innerDepth = parser.getDepth();
final CachedComponentArgs cachedArgs = new CachedComponentArgs();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
//解析activity,其他标签类似
if (tagName.equals("activity")) {
Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
owner.baseHardwareAccelerated);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.activities.add(a);
}
return true;
}
以上解析activity标签和application类似。
总结:parsePackage这个流程就是解析AndroidManifest.xml里面的内容,然后对应保存到Package这个大的数据中去,Package里面有很多小的数据结构。
回到上面scanDirLI这个方法里面
for (; fileCount > 0; fileCount--) {
//从解析队列面取一个解析结果出来
ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
Throwable throwable = parseResult.throwable;
int errorCode = PackageManager.INSTALL_SUCCEEDED;
if (throwable == null) {
// 静态共享库具有合成的包名
if (parseResult.pkg.applicationInfo.isStaticSharedLibrary()) {
renameStaticSharedLibraryPackage(parseResult.pkg);
}
try {
if (errorCode == PackageManager.INSTALL_SUCCEEDED) {
//调用scanPackageLI
scanPackageLI(parseResult.pkg, parseResult.scanFile, parseFlags, scanFlags,
currentTime, null);
}
} catch (PackageManagerException e) {
errorCode = e.error;
}
} else if (throwable instanceof PackageParser.PackageParserException) {
PackageParser.PackageParserException e = (PackageParser.PackageParserException)
throwable;
errorCode = e.error;
} else {
throw new IllegalStateException("Unexpected exception occurred while parsing "
+ parseResult.scanFile, throwable);
}
// 删除无效的用户数据应用程序
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
errorCode == PackageManager.INSTALL_FAILED_INVALID_APK) {
//删除无效应用数据
removeCodePathLI(parseResult.scanFile);
}
}
parallelPackageParser.close();
}
scanDirLI主要功能提交解析,并且获取解析结果,如果解析成功并且是静态共享库则重名,然后会调用
scanPackageLI(PackageParser.Package pkg, File scanFile,
final int policyFlags, int scanFlags, long currentTime, @Nullable UserHandle user);这个方法。
如果解析失败并且不是系统应用则会删除扫描文件。
接着看PMS的scanPackageLI方法
private PackageParser.Package scanPackageLI(PackageParser.Package pkg, File scanFile,
final int policyFlags, int scanFlags, long currentTime, @Nullable UserHandle user)
throws PackageManagerException {
if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
if (pkg.childPackages != null && pkg.childPackages.size() > 0) {
scanFlags |= SCAN_CHECK_ONLY;
}
} else {
scanFlags &= ~SCAN_CHECK_ONLY;
}
// Scan the parent
//走这里
PackageParser.Package scannedPkg = scanPackageInternalLI(pkg, scanFile, policyFlags,
scanFlags, currentTime, user);
// Scan the children
final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
PackageParser.Package childPackage = pkg.childPackages.get(i);
scanPackageInternalLI(childPackage, scanFile, policyFlags, scanFlags,
currentTime, user);
}
//第二次则正常扫描。
if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
return scanPackageLI(pkg, scanFile, policyFlags, scanFlags, currentTime, user);
}
return scannedPkg;
}
如果有子包第一次会先执行扫描检查,第二次则正常扫描。
接着看PMS的scanPackageInternalLI方法
private PackageParser.Package scanPackageInternalLI(PackageParser.Package pkg, File scanFile,
int policyFlags, int scanFlags, long currentTime, @Nullable UserHandle user)
throws PackageManagerException {
PackageSetting ps = null;
PackageSetting updatedPkg;
synchronized (mPackages) {
// 看看我们是否已经知道这个包裹。
String oldName = mSettings.getRenamedPackageLPr(pkg.packageName);
if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
//这个包被重命名为原来的名称。让我们使用它。
ps = mSettings.getPackageLPr(oldName);
}
// 如果没有原始的包,请查看真正的包名。
if (ps == null) {
ps = mSettings.getPackageLPr(pkg.packageName);
}
//检查此包是否隐藏/更新系统包。必须在原始或真实的包名称下寻找它,这取决于我们的状态。
updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
// 如果这是一个我们不知道的系统分区上的包,我们可能需要删除系统分区上禁用的子包,
// 或者如果父apk在数据分区上更新,不再定义这个子包,可能需要不添加子包。
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
// 如果这是更新的系统应用程序的父程序包,并且此系统应用程序进行了OTA更新,
//而该更新程序不再定义某些子程序包,我们必须从禁用的系统程序包中修剪它们。
PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(pkg.packageName);
if (disabledPs != null) {
final int scannedChildCount = (pkg.childPackages != null)
? pkg.childPackages.size() : 0;
final int disabledChildCount = disabledPs.childPackageNames != null
? disabledPs.childPackageNames.size() : 0;
for (int i = 0; i < disabledChildCount; i++) {
String disabledChildPackageName = disabledPs.childPackageNames.get(i);
boolean disabledPackageAvailable = false;
for (int j = 0; j < scannedChildCount; j++) {
PackageParser.Package childPkg = pkg.childPackages.get(j);
if (childPkg.packageName.equals(disabledChildPackageName)) {
disabledPackageAvailable = true;
break;
}
}
if (!disabledPackageAvailable) {
mSettings.removeDisabledSystemPackageLPw(disabledChildPackageName);
}
}
}
}
}
final boolean isUpdatedPkg = updatedPkg != null;
boolean isUpdatedSystemPkg = isUpdatedPkg
&& (policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0;
boolean isUpdatedPkgBetter = false;
// 首先检查这是否是一个可能涉及更新的系统软件包
if (isUpdatedSystemPkg) {
//如果新软件包不在“ / system / priv-app”中(例如由于OTA),则需要删除FLAG_PRIVILEGED。
if (locationIsPrivileged(scanFile)) {
updatedPkg.pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
} else {
updatedPkg.pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
}
if (ps != null && !ps.codePath.equals(scanFile)) {
// 路径与上次扫描的路径已更改...针对我们存储的内容检查新路径的版本,以确定要执行的操作。
if (pkg.mVersionCode <= ps.versionCode) {
// 系统包已经更新,代码路径与忽略条目不匹配。跳过它。
if (!updatedPkg.codePath.equals(scanFile)) {
updatedPkg.codePath = scanFile;
updatedPkg.codePathString = scanFile.toString();
updatedPkg.resourcePath = scanFile;
updatedPkg.resourcePathString = scanFile.toString();
}
updatedPkg.pkg = pkg;
updatedPkg.versionCode = pkg.mVersionCode;
//更新被禁用的系统子包,使其也指向该包。
final int childCount = updatedPkg.childPackageNames != null
? updatedPkg.childPackageNames.size() : 0;
for (int i = 0; i < childCount; i++) {
String childPackageName = updatedPkg.childPackageNames.get(i);
PackageSetting updatedChildPkg = mSettings.getDisabledSystemPkgLPr(
childPackageName);
if (updatedChildPkg != null) {
updatedChildPkg.pkg = pkg;
updatedChildPkg.versionCode = pkg.mVersionCode;
}
}
} else {
// 系统分区上的当前应用程序比我们在数据分区上更新的应用程序更好。 切换回系统分区版本。 在这一点上,它安全地认为
//系统分区中的应用程序将通过.如果没有,则不会有该应用程序的有效版本
// writer
synchronized (mPackages) {
// 只需从软件包列表中删除已加载的条目。
mPackages.remove(ps.name);
}
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
synchronized (mPackages) {
mSettings.enableSystemPackageLPw(ps.name);
}
isUpdatedPkgBetter = true;
}
}
}
String resourcePath = null;
String baseResourcePath = null;
if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !isUpdatedPkgBetter) {
if (ps != null && ps.resourcePathString != null) {
resourcePath = ps.resourcePathString;
baseResourcePath = ps.resourcePathString;
} else {
}
} else {
resourcePath = pkg.codePath;
baseResourcePath = pkg.baseCodePath;
}
// 显式设置应用程序对象路径。
pkg.setApplicationVolumeUuid(pkg.volumeUuid);
pkg.setApplicationInfoCodePath(pkg.codePath);
pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath);
pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths);
pkg.setApplicationInfoResourcePath(resourcePath);
pkg.setApplicationInfoBaseResourcePath(baseResourcePath);
pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
// 如果我们对系统应用程序进行了更新,但是更新的时间并不比我们已经扫描的包更近,那么抛出一个异常
if (isUpdatedSystemPkg && !isUpdatedPkgBetter) {
// 将CPU Abis设置为应用程序信息。
if ((scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0) {
final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, updatedPkg);
derivePackageAbi(pkg, scanFile, cpuAbiOverride, false, mAppLib32InstallDir);
} else {
pkg.applicationInfo.primaryCpuAbi = updatedPkg.primaryCpuAbiString;
pkg.applicationInfo.secondaryCpuAbi = updatedPkg.secondaryCpuAbiString;
}
throw new PackageManagerException(Log.WARN, "Package " + ps.name + " at "
+ scanFile + " ignored: updated version " + ps.versionCode
+ " better than this " + pkg.mVersionCode);
}
if (isUpdatedPkg) {
// 更新的系统应用最初不会设置PARSE_IS_SYSTEM标志
policyFlags |= PackageParser.PARSE_IS_SYSTEM;
// 一个更新的特权应用程序最初不会设置PARSE_IS_PRIVILEGED标志
if ((updatedPkg.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
policyFlags |= PackageParser.PARSE_IS_PRIVILEGED;
}
}
// 根据上次扫描的内容验证证书
collectCertificatesLI(ps, pkg, scanFile, policyFlags);
/*
*出现了一个新的系统应用程序,但是我们早先已经安装了一个非系统的同名应用程序。
*/
boolean shouldHideSystemApp = false;
if (!isUpdatedPkg && ps != null
&& (policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
/*
* 检查以确保签名首先匹配。如果没有,请擦除已安装的应用程序及其数据。
*/
if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
!= PackageManager.SIGNATURE_MATCH) {
try (PackageFreezer freezer = freezePackage(pkg.packageName,
"scanPackageInternalLI")) {
deletePackageLIF(pkg.packageName, null, true, null, 0, null, false, null);
}
ps = null;
} else {
/*
* 如果新添加的系统应用程序的版本比已安装的版本旧,请隐藏它。
* 稍后将对其进行扫描,并像更新一样对其进行重新添加。
*/
if (pkg.mVersionCode <= ps.versionCode) {
shouldHideSystemApp = true;
} else {
/*
* 新发现的系统应用程序是先前安装的较新版本。
* 只需删除已安装的应用程序并用我们自己的应用程序替换它,同时保留应用程序数据。
*/
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
}
}
}
// 如果apk的代码和资源保存在不同的文件中,则将其向前锁定(不公开)。
if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
policyFlags |= PackageParser.PARSE_FORWARD_LOCK;
}
}
final int userId = ((user == null) ? 0 : user.getIdentifier());
if (ps != null && ps.getInstantApp(userId)) {
scanFlags |= SCAN_AS_INSTANT_APP;
}
if (ps != null && ps.getVirtulalPreload(userId)) {
scanFlags |= SCAN_AS_VIRTUAL_PRELOAD;
}
//请注意,只有在即将解包应用程序时才调用以下方法
PackageParser.Package scannedPkg = scanPackageLI(pkg, policyFlags, scanFlags
| SCAN_UPDATE_SIGNATURE, currentTime, user);
/*
* 如果系统应用程序应被先前安装的数据覆盖,请立即隐藏系统应用程序,并让/ data / app扫描再次将其拾取。
*/
if (shouldHideSystemApp) {
synchronized (mPackages) {
mSettings.disableSystemPackageLPw(pkg.packageName, true);
}
}
return scannedPkg;
}
首先查看系统有没有这个包的设置,查看是不是一个更新包。
如果是系统应用更新,查看原来的子包在这次扫描中有没有定义,如果没有,则从原来更新设置中移除。
如果是系统应用更新,在根据扫描文件的位置赋予其相应的权限,如果原来包的版本大于等于当前扫描包,则更新原来包的属性为当前扫描包的属性。
否则移除原来包的设置,创建安装参数,清理资源。
收集签名信息
如果是一个新的系统应用,并且之前安装了一个同名的非系统应用,如果他们签名不相同,删除安装的信息和数据
否则 如果当前安装应用的版本小于等于原来的版本则隐藏它,否则创建安装参数。
根据相关策略标识给与响应权限。然后调用scanPackageLI这个函数。
最后根据是否隐藏,保存到mDisabledSysPackages这个数据结构里面。
接着看PMS的scanPackageLI五个参数的同名方法
private PackageParser.Package scanPackageLI(PackageParser.Package pkg, final int policyFlags,
int scanFlags, long currentTime, @Nullable UserHandle user)
throws PackageManagerException {
boolean success = false;
try {
final PackageParser.Package res = scanPackageDirtyLI(pkg, policyFlags, scanFlags,
currentTime, user);
success = true;
return res;
} finally {
if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
// DELETE_DATA_ON_FAILURES is only used by frozen paths
destroyAppDataLIF(pkg, UserHandle.USER_ALL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
destroyAppProfilesLIF(pkg, UserHandle.USER_ALL);
}
}
}
调用scanPackageDirtyLI,如果失败则删除app data下面的内容和目录
接着看PMS的scanPackageDirtyLI方法
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
final int policyFlags, final int scanFlags, long currentTime, @Nullable UserHandle user)
throws PackageManagerException {
//应用策略
applyPolicy(pkg, policyFlags);
//判断包的有效性
assertPackageIsValid(pkg, policyFlags, scanFlags);
//初始化资源文件
final File scanFile = new File(pkg.codePath);
final File destCodeFile = new File(pkg.applicationInfo.getCodePath());
final File destResourceFile = new File(pkg.applicationInfo.getResourcePath());
SharedUserSetting suid = null;
PackageSetting pkgSetting = null;
PackageSetting nonMutatedPs = null;
final PackageParser.Package oldPkg;
// writer
synchronized (mPackages) {
//保存静态库
String[] usesStaticLibraries = null;
if (pkg.usesStaticLibraries != null) {
usesStaticLibraries = new String[pkg.usesStaticLibraries.size()];
pkg.usesStaticLibraries.toArray(usesStaticLibraries);
}
//如果pkgSetting等于null 则创建新的
if (pkgSetting == null) {
final String parentPackageName = (pkg.parentPackage != null)
? pkg.parentPackage.packageName : null;
final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
final boolean virtualPreload = (scanFlags & SCAN_AS_VIRTUAL_PRELOAD) != 0;
pkgSetting = Settings.createNewSetting(pkg.packageName, origPackage,
disabledPkgSetting, realName, suid, destCodeFile, destResourceFile,
pkg.applicationInfo.nativeLibraryRootDir, pkg.applicationInfo.primaryCpuAbi,
pkg.applicationInfo.secondaryCpuAbi, pkg.mVersionCode,
pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags, user,
true /*allowInstall*/, instantApp, virtualPreload,
parentPackageName, pkg.getChildPackageNames(),
UserManagerService.getInstance(), usesStaticLibraries,
pkg.usesStaticLibrariesVersions);
if (origPackage != null) {
mSettings.addRenamedPackageLPw(pkg.packageName, origPackage.name);
}
mSettings.addUserToSettingLPw(pkgSetting);
} else {
//否则基于原来的更新
Settings.updatePackageSetting(pkgSetting, disabledPkgSetting, suid, destCodeFile,
pkg.applicationInfo.nativeLibraryDir, pkg.applicationInfo.primaryCpuAbi,
pkg.applicationInfo.secondaryCpuAbi, pkg.applicationInfo.flags,
pkg.applicationInfo.privateFlags, pkg.getChildPackageNames(),
UserManagerService.getInstance(), usesStaticLibraries,
pkg.usesStaticLibrariesVersions);
}
//写用户约束的信息
mSettings.writeUserRestrictionsLPw(pkgSetting, oldPkgSetting);
if ((scanFlags & SCAN_BOOTING) == 0
&& (policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
//更新共享库
updateSharedLibrariesLPr(pkg, null);
}
if (mFoundPolicyFile) {
//分配se权限
SELinuxMMAC.assignSeInfoValue(pkg);
}
if ((scanFlags & SCAN_CHECK_ONLY) == 0 && pkg.mAdoptPermissions != null) {
for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
final String origName = pkg.mAdoptPermissions.get(i);
final PackageSetting orig = mSettings.getPackageLPr(origName);
if (orig != null) {
if (verifyPackageUpdateLPr(orig, pkg)) {
//迁移权限
mSettings.transferPermissionsLPw(origName, pkg.packageName);
}
}
}
}
}
//如果是check only 则把之前保存的恢复
if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
if (nonMutatedPs != null) {
synchronized (mPackages) {
mSettings.mPackages.put(nonMutatedPs.name, nonMutatedPs);
}
}
} else {
final int userId = user == null ? 0 : user.getIdentifier();
//最重要的一个方法,添加包信息到包管理器,把解析出来的包信息转移到PMS内部数据结构里面
commitPackageSettings(pkg, pkgSetting, user, scanFlags,
(policyFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/);
}
if (oldPkg != null) {
final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
AsyncTask.execute(new Runnable() {
public void run() {
//如果group改变则撤销权限
revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg, allPackageNames);
}
});
}
return pkg;
}
通过上述的扫描过程,我们得到了当前apk文件对应的Package信息。不过这部分信息是存储在PackageParser中的,我们必须将这部分信息传递到PMS中。毕竟最终的目的是:让PMS能得到所有目录下Package的信息。
scanPackageDirtyLI函数主要就是把签名解析应用程序得到的package、provider、service、receiver和activity等信息保存在PackageManagerService相关的成员列表里