应用对于Android系统来说至关重要,系统会有几个时机对APP进行解析,一个是APK安装的时候会进行解析,还有一个就是系统在重启之后会进行解析,这里就简单的记录一下重启的时候APK的解析过程。
一、SystemServer
系统在启动之后从内核层启动第一个用户控件Init进程,再通过Init进程启动系统中第一个java 进程zygote,随之zygote fock出SystemServer,SystemServer再开始启动一些列系统服务,其中就包括PackageMangerService,在startBootstrapServices函数中:
public final void startBootstrapServices(TimingsTraceAndSlog timingsTraceAndSlog) { ..... // 先调用了PackageManagerService的main函数 Pair<PackageManagerService, IPackageManager> main = PackageManagerService.main(context, installer, domainVerificationService, z, this.mOnlyCore); // main 函数创建了PackageManagerService 和IPackageManager 的实例 this.mPackageManagerService = (PackageManagerService) main.first; IPackageManager iPackageManager = (IPackageManager) main.second; Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain"); // 该方法将在 BaseDexClassLoader 中安装一个报告器,同时还将强制报告系统服务器已加载的任何 dex 文件 SystemServerDexLoadReporter.configureSystemServerDexReporter(iPackageManager); this.mFirstBoot = this.mPackageManagerService.isFirstBoot(); this.mPackageManager = this.mSystemContext.getPackageManager();
二、PackageManagerService
在SystemServer中是先调用PackageManagerService的main函数来初始化它自己的,来看看它做了什么:
public static Pair<PackageManagerService, IPackageManager> main(Context context, Installer installer, @NonNull DomainVerificationService domainVerificationService, boolean factoryTest, boolean onlyCore) { PackageManagerServiceCompilerMapping.checkProperties(); final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing", Trace.TRACE_TAG_PACKAGE_MANAGER); t.traceBegin("create package manager"); final PackageManagerTracedLock lock = new PackageManagerTracedLock(); final Object installLock = new Object(); // 创建自带handler的线程 HandlerThread backgroundThread = new ServiceThread("PackageManagerBg", Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/); backgroundThread.start(); Handler backgroundHandler = new Handler(backgroundThread.getLooper()); // 创建PackageManagerServiceInjector 用来持有管理其他一系列重要的类实例 PackageManagerServiceInjector injector = new PackageManagerServiceInjector( context, lock, installer, installLock, new PackageAbiHelperImpl(), backgroundHandler, SYSTEM_PARTITIONS, // 解析compnent的 (i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mUserNeedsBadging), // 权限管理服务 (i, pm) -> PermissionManagerService.create(context, i.getSystemConfig().getAvailableFeatures()), // 用户管理服务 (i, pm) -> new UserManagerService(context, pm, new UserDataPreparer(installer, installLock, context, onlyCore), lock), // 系统数据库,用来访问系统数据库的 (i, pm) -> new Settings(Environment.getDataDirectory(), RuntimePermissionsPersistence.createInstance(), i.getPermissionManagerServiceInternal(), domainVerificationService, backgroundHandler, lock), (i, pm) -> AppsFilterImpl.create(i, i.getLocalService(PackageManagerInternal.class)), // compat服务用来管理一些系统特性 (i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"), // 系统配置服务,预置的系统的权限、硬件feature还有其他的一些配置在这里面解析 (i, pm) -> SystemConfig.getInstance(), // 在软件包上运行 dexopt 命令的辅助类。 (i, pm) -> new PackageDexOptimizer(i.getInstaller(), i.getInstallLock(), i.getContext(), "*dexopt*"), // dex 行为管理类会保存所有包的dex位置 (i, pm) -> new DexManager(i.getContext(), i.getPackageDexOptimizer(), i.getInstaller(), i.getInstallLock()), (i, pm) -> new ArtManagerService(i.getContext(), i.getInstaller(), i.getInstallLock()), (i, pm) -> ApexManager.getInstance(), (i, pm) -> new ViewCompiler(i.getInstallLock(), i.getInstaller()), (i, pm) -> (IncrementalManager) i.getContext().getSystemService(Context.INCREMENTAL_SERVICE), (i, pm) -> new DefaultAppProvider(() -> context.getSystemService(RoleManager.class), () -> LocalServices.getService(UserManagerInternal.class)), (i, pm) -> new DisplayMetrics(), // 包解析类 (i, pm) -> new PackageParser2(pm.mSeparateProcesses, pm.mOnlyCore, i.getDisplayMetrics(), pm.mCacheDir, pm.mPackageParserCallback) /* scanningCachingPackageParserProducer */, (i, pm) -> new PackageParser2(pm.mSeparateProcesses, pm.mOnlyCore, i.getDisplayMetrics(), null, pm.mPackageParserCallback) /* scanningPackageParserProducer */, (i, pm) -> new PackageParser2(pm.mSeparateProcesses, false, i.getDisplayMetrics(), null, pm.mPackageParserCallback) /* preparingPackageParserProducer */, // Prepare a supplier of package parser for the staging manager to parse apex file // during the staging installation. // 包安装服务 (i, pm) -> new PackageInstallerService( i.getContext(), pm, i::getScanningPackageParser), (i, pm, cn) -> new InstantAppResolverConnection( i.getContext(), cn, Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE), (i, pm) -> new ModuleInfoProvider(i.getContext()), (i, pm) -> LegacyPermissionManagerService.create(i.getContext()), (i, pm) -> domainVerificationService, (i, pm) -> { HandlerThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/); thread.start(); return new PackageHandler(thread.getLooper(), pm); }, new DefaultSystemWrapper(), LocalServices::getService, context::getSystemService, (i, pm) -> new BackgroundDexOptService(i.getContext(), i.getDexManager(), pm), (i, pm) -> IBackupManager.Stub.asInterface(ServiceManager.getService( Context.BACKUP_SERVICE)), (i, pm) -> new SharedLibrariesImpl(pm, i)); if (Build.VERSION.SDK_INT <= 0) { Slog.w(TAG, "**** ro.build.version.sdk not set!"); } // 初始化PackageManagerService PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest, PackagePartitions.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG, Build.VERSION.SDK_INT, Build.VERSION.INCREMENTAL); t.traceEnd(); // "create package manager" final CompatChange.ChangeListener selinuxChangeListener = packageName -> { synchronized (m.mInstallLock) { final Computer snapshot = m.snapshotComputer(); final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); if (packageState == null) { Slog.e(TAG, "Failed to find package setting " + packageName); return; } AndroidPackage pkg = packageState.getPkg(); SharedUserApi sharedUser = snapshot.getSharedUser( packageState.getSharedUserAppId()); String oldSeInfo = AndroidPackageUtils.getSeInfo(pkg, packageState); if (pkg == null) { Slog.e(TAG, "Failed to find package " + packageName); return; } final String newSeInfo = SELinuxMMAC.getSeInfo(pkg, sharedUser, m.mInjector.getCompatibility()); if (!newSeInfo.equals(oldSeInfo)) { Slog.i(TAG, "Updating seInfo for package " + packageName + " from: " + oldSeInfo + " to: " + newSeInfo); m.commitPackageStateMutation(null, packageName, state -> state.setOverrideSeInfo(newSeInfo)); m.mAppDataHelper.prepareAppDataAfterInstallLIF(pkg); } } }; //监听selinux的一些变化 injector.getCompatibility().registerListener(SELinuxMMAC.SELINUX_LATEST_CHANGES, selinuxChangeListener); injector.getCompatibility().registerListener(SELinuxMMAC.SELINUX_R_CHANGES, selinuxChangeListener); // ota完或者第一次开机为所有用户安装其被 m.installAllowlistedSystemPackages(); // 初始化 IPackageManagerImpl IPackageManagerImpl iPackageManager = m.new IPackageManagerImpl(); ServiceManager.addService("package", iPackageManager); // 初始化PackageManagerNative final PackageManagerNative pmn = new PackageManagerNative(m); ServiceManager.addService("package_native", pmn); LocalManagerRegistry.addManager(PackageManagerLocal.class, m.new PackageManagerLocalImpl()); return Pair.create(m, iPackageManager); }
简单的介绍了一下main,下面重头戏在PackageManagerService的初始化过程,它总共有两个构造函数,注意一个只做了赋值,我们这里调用的不是这个构造函数而是另一个
public PackageManagerService(PackageManagerServiceInjector injector, boolean onlyCore, boolean factoryTest, final String buildFingerprint, final boolean isEngBuild, final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) { mIsEngBuild = isEngBuild; ...... // 这里部分主要是给PackageMangerService的一些属性赋值 ...... // CHECKSTYLE:ON IndentationCheck t.traceEnd(); t.traceBegin("addSharedUsers"); // 注册各种UID 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); mSettings.addSharedUserLPw("android.uid.se", SE_UID, ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_UID, ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); mSettings.addSharedUserLPw("android.uid.uwb", UWB_UID, ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); t.traceEnd(); ...... // 又是一堆初始化赋值 ...... // 从systemconfig获取对于机器来说可用的硬件feature,可以在这里之前对feature进行修改 t.traceBegin("get system config"); SystemConfig systemConfig = injector.getSystemConfig(); mAvailableFeatures = systemConfig.getAvailableFeatures(); t.traceEnd(); ...... // 这里是读取在mac_permissions.xml下面配置的一些se策略可以有效的限制一些应用的权限 SELinuxMMAC.readInstallPolicy(); ...... final VersionInfo ver = mSettings.getInternalVersion(); // 指纹信息是否有更新 mIsUpgrade = !buildFingerprint.equals(ver.fingerprint); if (mIsUpgrade) { PackageManagerServiceUtils.logCriticalInfo(Log.INFO, "Upgrading from " + ver.fingerprint + " to " + PackagePartitions.FINGERPRINT); } mInitAppsHelper = new InitAppsHelper(this, mApexManager, mInstallPackageHelper, mInjector.getSystemPartitions()); // when upgrading from pre-M, promote system app permissions from install to runtime // 是否从M升上来 mPromoteSystemApps = mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1; // When upgrading from pre-N, we need to handle package extraction like first boot, // as there is no profiling data available. // 是否从N 升上来 mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N; // 是否从n mr升上来 mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1; // 是否从Q升上来 mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q; ...... // 根据不同的版本类型创建缓存目录,如果已存在则不创建 mCacheDir = PackageManagerServiceUtils.preparePackageParserCache( mIsEngBuild, mIsUserDebugBuild, mIncrementalVersion); final int[] userIds = mUserManager.getUserIds(); PackageParser2 packageParser = mInjector.getScanningCachingPackageParser(); // 初始化安装系统级APP mOverlayConfig = mInitAppsHelper.initSystemApps(packageParser, packageSettings, userIds, startTime); // 初始化安装非系统级APP mInitAppsHelper.initNonSystemApps(packageParser, userIds, startTime); packageParser.close(); ...... }
可以从上面PackageManagerService的初始化可以看到,机器开机的时候安装APP的任务是交给InitAppsHelper这个类来做的,两个函数一个initSystemApps一个initNonSystemApps,分别是初始化系统app和非系统app,两个函数都是对系统中的应用进行安装解析,区别就是针对系统app还是非系统app,我们先从系统app来看看。
三、InitAppsHelper
public OverlayConfig initSystemApps(PackageParser2 packageParser, WatchedArrayMap<String, PackageSetting> packageSettings, int[] userIds, long startTime)
initSystemApps有四个参数,看下其中比较重要的两个参数怎么来的
1、PackageParser2
第一个参数实在PackageManagerService初始化的时候从mInjector获取的,而这里的PackageParser2是在PackaManagerService的main函数初始化的
PackageParser2 packageParser = mInjector.getScanningCachingPackageParser();
2、WatchedArrayMap<String, PackageSetting>
首先这个参数是通过PackageMangerService的成员变量mSettings获取:
final WatchedArrayMap<String, PackageSetting> packageSettings = mSettings.getPackagesLocked();
Settings.getPackagesLocked
WatchedArrayMap<String, PackageSetting> getPackagesLocked() { return mPackages; }
Settings.addPackageLPw 中添加数据
PackageSetting addPackageLPw(String name, String realName, File codePath, int uid, int pkgFlags, int pkgPrivateFlags, @NonNull UUID domainSetId) { PackageSetting p = mPackages.get(name); if (p != null) { if (p.getAppId() == uid) { return p; } PackageManagerService.reportSettingsProblem(Log.ERROR, "Adding duplicate package, keeping first: " + name); return null; } p = new PackageSetting(name, realName, codePath, pkgFlags, pkgPrivateFlags, domainSetId) .setAppId(uid); if (mAppIds.registerExistingAppId(uid, p, name)) { mPackages.put(name, p); return p; } return null; }
Settings.readSettingsLPw,这个函数中对应用的一些配置信息进行解析,这些信息主要是存在/data/system目录下面
boolean readSettingsLPw(@NonNull Computer computer, @NonNull List<UserInfo> users, ArrayMap<String, Long> originalFirstInstallTimes) { mPendingPackages.clear(); mInstallerPackages.clear(); originalFirstInstallTimes.clear(); ArrayMap<Long, Integer> keySetRefs = new ArrayMap<>(); ArrayList<Signature> readSignatures = new ArrayList<>(); // 获取一系列配置文件,文件位于/data/system/下面,在setings初始化的时候被赋值 /** mSystemDir = new File(dataDir, "system"); mSystemDir.mkdirs(); mSettingsFilename = new File(mSystemDir, "packages.xml"); mSettingsReserveCopyFilename = new File(mSystemDir, "packages.xml.reservecopy"); mPreviousSettingsFilename = new File(mSystemDir, "packages-backup.xml"); 下面就是对这些配置文件进行解析 */ try (ResilientAtomicFile atomicFile = getSettingsFile()) { FileInputStream str = null; try { str = atomicFile.openRead(); if (str == null) { // Not necessary, but will avoid wtf-s in the "finally" section. findOrCreateVersion(StorageManager.UUID_PRIVATE_INTERNAL).forceCurrent(); findOrCreateVersion(StorageManager.UUID_PRIMARY_PHYSICAL).forceCurrent(); return false; } final TypedXmlPullParser parser = Xml.resolvePullParser(str); int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { // nothing } if (type != XmlPullParser.START_TAG) { mReadMessages.append("No start tag found in settings file\n"); PackageManagerService.reportSettingsProblem(Log.WARN, "No start tag found in package manager settings"); Slog.wtf(PackageManagerService.TAG, "No start tag found in package manager settings"); return false; } 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 (tagName.equals("package")) { //读取包信息 readPackageLPw(parser, readSignatures, keySetRefs, users, originalFirstInstallTimes); } else if (tagName.equals("permissions")) { mPermissions.readPermissions(parser); } else if (tagName.equals("permission-trees")) { mPermissions.readPermissionTrees(parser); } else if (tagName.equals("shared-user")) { readSharedUserLPw(parser, readSignatures, users); } else if (tagName.equals("preferred-packages")) { // no longer used. } else if (tagName.equals("preferred-activities")) { // Upgrading from old single-user implementation; // these are the preferred activities for user 0. readPreferredActivitiesLPw(parser, 0); } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) { // TODO: check whether this is okay! as it is very // similar to how preferred-activities are treated readPersistentPreferredActivitiesLPw(parser, 0); } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) { // TODO: check whether this is okay! as it is very // similar to how preferred-activities are treated readCrossProfileIntentFiltersLPw(parser, 0); } else if (tagName.equals(TAG_DEFAULT_BROWSER)) { readDefaultAppsLPw(parser, 0); } else if (tagName.equals("updated-package")) { readDisabledSysPackageLPw(parser, users); } else if (tagName.equals("renamed-package")) { String nname = parser.getAttributeValue(null, "new"); String oname = parser.getAttributeValue(null, "old"); if (nname != null && oname != null) { mRenamedPackages.put(nname, oname); } } else if (tagName.equals("last-platform-version")) { // Upgrade from older XML schema final VersionInfo internal = findOrCreateVersion( StorageManager.UUID_PRIVATE_INTERNAL); final VersionInfo external = findOrCreateVersion( StorageManager.UUID_PRIMARY_PHYSICAL); internal.sdkVersion = parser.getAttributeInt(null, "internal", 0); external.sdkVersion = parser.getAttributeInt(null, "external", 0); internal.buildFingerprint = external.buildFingerprint = XmlUtils.readStringAttribute(parser, "buildFingerprint"); internal.fingerprint = external.fingerprint = XmlUtils.readStringAttribute(parser, "fingerprint"); } else if (tagName.equals("database-version")) { // Upgrade from older XML schema final VersionInfo internal = findOrCreateVersion( StorageManager.UUID_PRIVATE_INTERNAL); final VersionInfo external = findOrCreateVersion( StorageManager.UUID_PRIMARY_PHYSICAL); internal.databaseVersion = parser.getAttributeInt(null, "internal", 0); external.databaseVersion = parser.getAttributeInt(null, "external", 0); } else if (tagName.equals("verifier")) { final String deviceIdentity = parser.getAttributeValue(null, "device"); mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity); } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) { // No longer used. } else if (tagName.equals("keyset-settings")) { mKeySetManagerService.readKeySetsLPw(parser, keySetRefs); } else if (TAG_VERSION.equals(tagName)) { final String volumeUuid = XmlUtils.readStringAttribute(parser, ATTR_VOLUME_UUID); final VersionInfo ver = findOrCreateVersion(volumeUuid); ver.sdkVersion = parser.getAttributeInt(null, ATTR_SDK_VERSION); ver.databaseVersion = parser.getAttributeInt(null, ATTR_DATABASE_VERSION); ver.buildFingerprint = XmlUtils.readStringAttribute(parser, ATTR_BUILD_FINGERPRINT); ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT); } else if (tagName.equals( DomainVerificationPersistence.TAG_DOMAIN_VERIFICATIONS)) { mDomainVerificationManager.readSettings(computer, parser); } else if (tagName.equals( DomainVerificationLegacySettings.TAG_DOMAIN_VERIFICATIONS_LEGACY)) { mDomainVerificationManager.readLegacySettings(parser); } else { Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: " + parser.getName()); XmlUtils.skipCurrentTag(parser); } } str.close(); } catch (IOException | XmlPullParserException | ArrayIndexOutOfBoundsException e) { // Remove corrupted file and retry. atomicFile.failRead(str, e); // Ignore the result to not mark this as a "first boot". readSettingsLPw(computer, users, originalFirstInstallTimes); } } return true; }
从上面的函数可以看出Settings这个类的主要职责就是存储修改解析应用的配置信息,这里涉及的东西比较多,不再赘述有兴趣可以自行查阅相关源码。
mFirstBoot = !mSettings.readLPw(computer, mInjector.getUserManagerInternal().getUsers( /* excludePartial= */ true, /* excludeDying= */ false, /* excludePreCreated= */ false));
这里是Settings解析的开始在PackageMangerService的构造函数中,这是第二个参数的由来,接着第三个四个参数就比较简单分别是uid和时间戳。
篇幅有限下一篇展开细说