海北公司网站建设多少钱,网页的基本布局包括什么,百度推广教程视频教程,xxx网站建设规划参考资料#xff1a;PMS 第 1 篇 - PackageManagerService 初始化
这个是基于Android 7的#xff0c;我看的代码是Android 9
前言
PMS 用来管理所有的 package 信息#xff0c;包括安装、卸载、更新以及解析 AndroidManifest.xml 以组织相应的数据结构#xff0c;这些数…参考资料PMS 第 1 篇 - PackageManagerService 初始化
这个是基于Android 7的我看的代码是Android 9
前言
PMS 用来管理所有的 package 信息包括安装、卸载、更新以及解析 AndroidManifest.xml 以组织相应的数据结构这些数据结构将会被 其他 service 和 application 使用到。
一、PMS的启动
先来看 SystemServer 中 PackageManagerService 的启动代码 位置frameworks/base/services/java/com/android/server/SystemServer.java
private void startBootstrapServices() {//...这里的installer也是一个系统服务traceBeginAndSlog(StartInstaller);Installer installer mSystemServiceManager.startService(Installer.class);traceEnd();//...traceBeginAndSlog(StartPackageManagerService);mPackageManagerService PackageManagerService.main(mSystemContext, installer,mFactoryTestMode ! FactoryTest.FACTORY_TEST_OFF, mOnlyCore);mFirstBoot mPackageManagerService.isFirstBoot();mPackageManager mSystemContext.getPackageManager();traceEnd();//...
}main 函数很简单只有短短几行代码执行时间却较长主要原因是 PKMS 在其构造函数中做了很多“重体力活”这也是 Android 启动速度慢的主要原因之一。 位置frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java public static PackageManagerService main(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {// Self-check for initial settings.PackageManagerServiceCompilerMapping.checkProperties(); //检测和设置某些编译器相关的属性PackageManagerService m new PackageManagerService(context, installer,factoryTest, onlyCore); //构造一个 PMS 对象m.enableSystemUserPackages(); //启用系统用户的包可确保在Android系统启动时系统应用程序已正确安装并可用ServiceManager.addService(package, m); //调用 ServiceManager 的 addService 注册 PackageManagerService 服务final PackageManagerNative pmn m.new PackageManagerNative();ServiceManager.addService(package_native, pmn); //启动了PackageManagerNative的服务return m;}
构造函数有如下 4 个参数
第一个参数系统进程的上下文实例第二个参数Installer 对象用于和 Installd 通信使用我们后面分析 Installd 再来介绍第三个参数factoryTest 为出厂测试默认为 false第四个参数onlyCore 表示是否只加载核心的应用默认也为 false。
整个函数的作用是创建和配置PackageManagerService对象并将其注册到系统服务中以便其他组件可以访问它。
二、PMS的初始化
位置frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java PackageManagerService 的构造器代码结构如下 public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, create package manager);EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,SystemClock.uptimeMillis());//...synchronized (mInstallLock) {synchronized (mPackages) {// Expose private service for system components to use.LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());sUserManager new UserManagerService(context, this,new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);mPermissionManager PermissionManagerService.create(context,new DefaultPermissionGrantedCallback() {Overridepublic void onDefaultRuntimePermissionsGranted(int userId) {synchronized(mPackages) {mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);}}}, mPackages /*externalLock*/);mDefaultPermissionPolicy mPermissionManager.getDefaultPermissionGrantPolicy();mSettings new Settings(mPermissionManager.getPermissionSettings(), mPackages);}//...// Create sub-components that provide services / data. Order here is important.synchronized (mInstallLock) {synchronized (mPackages) {//....EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,startTime);//...if (!mOnlyCore) {EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,SystemClock.uptimeMillis());}//...EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis());Slog.i(TAG, Time to scan packages: ((SystemClock.uptimeMillis()-startTime)/1000f) seconds);//...Runtime.getRuntime().gc();Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);// The initial scanning above does many calls into installd while// holding the mPackages lock, but were mostly interested in yelling// once we have a booted system.mInstaller.setWarnIfHeld(mPackages);Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);Log.d(preinstall, start preinstallSystem.currentTimeMillis());mHandler.postDelayed(new Runnable() {public void run() {try{SystemProperties.set(ctl.start, preinstall);}catch (Exception e){Log.d(preinstall, preinstall failed);e.printStackTrace();}}},1200);}根据 EventLog 可以将 PMS 的初始化分为以下几个过程
阶段1BOOT_PROGRESS_PMS_START阶段2BOOT_PROGRESS_PMS_SYSTEM_SCAN_START阶段3BOOT_PROGRESS_PMS_DATA_SCAN_START阶段4BOOT_PROGRESS_PMS_SCAN_END阶段5BOOT_PROGRESS_PMS_READY
下面来看看 PackageManangerService 的构造器方法代码为了便于分析我们把 PackageManagerService 构造器的代码分为如下几个部分
2.1 BOOT_PROGRESS_PMS_START
public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, create package manager);EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,SystemClock.uptimeMillis());if (mSdkVersion 0) {//【1】mSdkVersion 是 PKMS 的成员变量定义的时候进行赋值//其值取自系统属性“ro.build.version.sdk”即编译的 SDK 版本Slog.w(TAG, **** ro.build.version.sdk not set!);}mContext context;mFactoryTest factoryTest; // 默认为 false即运行在非工厂模式下mOnlyCore onlyCore; // 默认为 false,标记是否是只加载核心服务mMetrics new DisplayMetrics(); //【2】用于存储与显示屏相关的一些属性例如屏幕的宽 / 高尺寸分辨率等信息。mInstaller installer; //【3】初始化 mInstaller 对象installer 对象和 Native 进程 installd 交互// Create sub-components that provide services / data. Order here is important.//使用synchronized关键字来同步访问mInstallLock和mPackages。这是为了保证在多线程环境下的数据安全性确保只有一个线程可以同时执行这段代码块synchronized (mInstallLock) {synchronized (mPackages) {// Expose private service for system components to use.LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());sUserManager new UserManagerService(context, this,new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);mPermissionManager PermissionManagerService.create(context,new DefaultPermissionGrantedCallback() {Overridepublic void onDefaultRuntimePermissionsGranted(int userId) {synchronized(mPackages) {mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);}}}, mPackages /*externalLock*/);//【10】创建 DefaultPermissionGrantPolicy 对象用于给某些预制的apk给予权限,也可以撤销mDefaultPermissionPolicy mPermissionManager.getDefaultPermissionGrantPolicy();mSettings new Settings(mPermissionManager.getPermissionSettings(), mPackages);}}//【3】在 Settings 中创建 packages.xml、packages-backup.xml、packages.list 等文件对象// 并添加 system, phone, log, nfc, bluetooth, shell 这六种 shareUserId 到 mSettings后面扫描和安装有用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);String separateProcesses SystemProperties.get(debug.separate_processes);if (separateProcesses ! null separateProcesses.length() 0) {if (*.equals(separateProcesses)) {mDefParseFlags PackageParser.PARSE_IGNORE_PROCESSES;mSeparateProcesses null;Slog.w(TAG, Running with debug.separate_processes: * (ALL));} else {mDefParseFlags 0;mSeparateProcesses separateProcesses.split(,);Slog.w(TAG, Running with debug.separate_processes: separateProcesses);}} else {mDefParseFlags 0;mSeparateProcesses null;}//【4】创建 PackageDexOptimizer 对象用于 dex 优化mPackageDexOptimizer new PackageDexOptimizer(installer, mInstallLock, context,*dexopt*);DexManager.Listener dexManagerListener DexLogger.getListener(this,installer, mInstallLock);mDexManager new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock,dexManagerListener);mArtManagerService new ArtManagerService(mContext, this, installer, mInstallLock);//【5】创建 MoveCallbacks 对象用于操作回滚mMoveCallbacks new MoveCallbacks(FgThread.get().getLooper());//【6】创建 OnPermissionChangeListeners 对象用于监听权限改变mOnPermissionChangeListeners new OnPermissionChangeListeners(FgThread.get().getLooper());getDefaultDisplayMetrics(context, mMetrics); // 获得默认的显示//【7】创建 SystemConfig 对象用于获取系统配置信息// 主要有 /system/etc/ 目录和 /system/etc/sysconfig 目录下的 sysconfig 和 permissions 文件夹xml文件Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, get system config);SystemConfig systemConfig SystemConfig.getInstance();mAvailableFeatures systemConfig.getAvailableFeatures();Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);mProtectedPackages new ProtectedPackages(mContext);synchronized (mInstallLock) {// writersynchronized (mPackages) {//【8】建立并启动一个名为 “PackageManager” 的 HandlerThread类型是 ServiceThread处理安装卸载的消息mHandlerThread new ServiceThread(TAG,Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);mHandlerThread.start();//【9】创建一个 PackageHandler 对象绑定前面创建的 HandlerThreadmHandler new PackageHandler(mHandlerThread.getLooper());mProcessLoggingHandler new ProcessLoggingHandler();Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);mInstantAppRegistry new InstantAppRegistry(this);//【13】处理共享库ArrayMapString, 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);}SELinuxMMAC.readInstallPolicy();Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, loadFallbacks);FallbackCategoryProvider.loadFallbacks();Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, read user settings);// 判断是否是第一次开机并获得上一次的安装信息mFirstBoot !mSettings.readLPw(sUserManager.getUsers(false));Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);// Clean up orphaned packages for which the code path doesnt exist// and they are an update to a system app - caused by bug/32321269// 移除哪些 codePath 无效的 Package恢复处于 system 目录下的同名 packagefinal 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);}}if (mFirstBoot) { // 如果是第一次开机从另外一个系统拷贝 odex 文件到当前系统的 data 分区requestCopyPreoptedFiles();}//获取和设置定制的解决方案组件名称以便在后续的操作中使用它//传入config_customResolverActivity字符串资源的ID以获取系统配置文件中定制的解决方案组件名称。String customResolverActivity Resources.getSystem().getString(R.string.config_customResolverActivity);//如果获取到的字符串为空则将customResolverActivity变量赋值为null。if (TextUtils.isEmpty(customResolverActivity)) {customResolverActivity null;} else {mCustomResolverComponentName ComponentName.unflattenFromString(customResolverActivity);}long startTime SystemClock.uptimeMillis();//...这里开始是第二阶段 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,startTime);
流程总结
创建 Settings 对象创建 packages.xml、packages-backup.xml、packages.list 等文件对象并添加 system, phone, log, nfc, bluetooth, shell 这六种 shareUserId 到 mSettings后面扫描和安装有用初始化 mInstaller 对象用于和 installed 交互创建 PackageDexOptimizer 对象用于 dex 优化创建 OnPermissionChangeListeners 对象用于监听权限改变创建 SystemConfig 对象用于获取系统配置信息创建用户管理服务获得权限信息获得系统共享库
2.2 PMS_SYSTEM_SCAN_START
接上面 //...long startTime SystemClock.uptimeMillis();EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,startTime);// 获得环境变量BOOTCLASSPATH 和 SYSTEMSERVERCLASSPATHfinal String bootClassPath System.getenv(BOOTCLASSPATH);final String systemServerClassPath System.getenv(SYSTEMSERVERCLASSPATH);if (bootClassPath null) {Slog.w(TAG, No BOOTCLASSPATH found!);}if (systemServerClassPath null) {Slog.w(TAG, No SYSTEMSERVERCLASSPATH found!);}// 获得目录 /system/framework对其目录下的文件进行优化File frameworkDir new File(Environment.getRootDirectory(), framework);// 获得系统版本信息final VersionInfo ver mSettings.getInternalVersion();// 判断是否是 OTA 升级mIsUpgrade !Build.FINGERPRINT.equals(ver.fingerprint);if (mIsUpgrade) {logCriticalInfo(Log.INFO,Upgrading from ver.fingerprint to Build.FINGERPRINT);}// when upgrading from pre-M, promote system app permissions from install to runtime// 判断是否是从 Android 6.0 升级过来的如果是就需要把系统 app 的权限从安装时提高到运行时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.// 判断是否是从 Android 7.0 升级过来的mIsPreNUpgrade mIsUpgrade ver.sdkVersion Build.VERSION_CODES.N;// 判断是否是从 Android 7.1 升级过来的mIsPreNMR1Upgrade mIsUpgrade ver.sdkVersion Build.VERSION_CODES.N_MR1;// save off the names of pre-existing system packages prior to scanning; we dont// want to automatically grant runtime permissions for new system apps// 保存从 Android 6.0 升级前已经存在的系统应用包并对他们进行优先扫描if (mPromoteSystemApps) {IteratorPackageSetting pkgSettingIter mSettings.mPackages.values().iterator();while (pkgSettingIter.hasNext()) {PackageSetting ps pkgSettingIter.next();if (isSystemApp(ps)) {mExistingSystemPackages.add(ps.name);}}}//为包解析器准备一个缓存目录并将其赋值给mCacheDir变量以便在后续的包解析操作中使用mCacheDir preparePackageParserCache(mIsUpgrade);// Set flag to monitor and not change apk file paths when// scanning install directories.// 设置扫描参数int scanFlags SCAN_BOOTING | SCAN_INITIAL;if (mIsUpgrade || mFirstBoot) {scanFlags scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;}// Collect vendor/product overlay packages. (Do this before scanning any apps.)// For security and version matching reason, only consider// overlay packages if they reside in the right directory.// 扫描收集目录 /vendor/overlay 下的供应商应用包scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),mDefParseFlags| PackageParser.PARSE_IS_SYSTEM_DIR,scanFlags| SCAN_AS_SYSTEM| SCAN_AS_VENDOR,0);// 扫描收集目录 /product/overlayscanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),mDefParseFlags| PackageParser.PARSE_IS_SYSTEM_DIR,scanFlags| SCAN_AS_SYSTEM| SCAN_AS_PRODUCT,0);mParallelPackageParserCallback.findStaticOverlayPackages();// Find base frameworks (resource packages without code).// 扫描收集目录 /system/framework 下的应用包scanDirTracedLI(frameworkDir,mDefParseFlags| PackageParser.PARSE_IS_SYSTEM_DIR,scanFlags| SCAN_NO_DEX| SCAN_AS_SYSTEM| SCAN_AS_PRIVILEGED,0);// Collect privileged system packages.// 扫描收集目录 /system/priv-app 下的应用包 final File privilegedAppDir new File(Environment.getRootDirectory(), priv-app);scanDirTracedLI(privilegedAppDir,mDefParseFlags| PackageParser.PARSE_IS_SYSTEM_DIR,scanFlags| SCAN_AS_SYSTEM| SCAN_AS_PRIVILEGED,0);// 扫描收集目录 /system/app 下的应用包 // Collect ordinary system packages.final File systemAppDir new File(Environment.getRootDirectory(), app);scanDirTracedLI(systemAppDir,mDefParseFlags| PackageParser.PARSE_IS_SYSTEM_DIR,scanFlags| SCAN_AS_SYSTEM,0);// Collect privileged vendor packages.// 扫描收集目录 /vendor/priv-app 下的应用包File privilegedVendorAppDir new File(Environment.getVendorDirectory(), priv-app);try {privilegedVendorAppDir privilegedVendorAppDir.getCanonicalFile();} catch (IOException e) {// failed to look up canonical path, continue with original one}// 扫描收集目录 /vendor/app 下的应用包scanDirTracedLI(privilegedVendorAppDir,mDefParseFlags| PackageParser.PARSE_IS_SYSTEM_DIR,scanFlags| SCAN_AS_SYSTEM| SCAN_AS_VENDOR| SCAN_AS_PRIVILEGED,0);// Collect ordinary vendor packages.// 扫描收集目录 /vendor/app 下的应用包 File vendorAppDir new File(Environment.getVendorDirectory(), app);try {vendorAppDir vendorAppDir.getCanonicalFile();} catch (IOException e) {// failed to look up canonical path, continue with original one}scanDirTracedLI(vendorAppDir,mDefParseFlags| PackageParser.PARSE_IS_SYSTEM_DIR,scanFlags| SCAN_AS_SYSTEM| SCAN_AS_VENDOR,0);// Collect privileged odm packages. /odm is another vendor partition// other than /vendor.// 扫描收集目录 /odm/priv-app 下的应用包File privilegedOdmAppDir new File(Environment.getOdmDirectory(),priv-app);try {privilegedOdmAppDir privilegedOdmAppDir.getCanonicalFile();} catch (IOException e) {// failed to look up canonical path, continue with original one}scanDirTracedLI(privilegedOdmAppDir,mDefParseFlags| PackageParser.PARSE_IS_SYSTEM_DIR,scanFlags| SCAN_AS_SYSTEM| SCAN_AS_VENDOR| SCAN_AS_PRIVILEGED,0);// Collect ordinary odm packages. /odm is another vendor partition// other than /vendor.// 扫描收集目录 /odm/app 下的应用包File odmAppDir new File(Environment.getOdmDirectory(), app);try {odmAppDir odmAppDir.getCanonicalFile();} catch (IOException e) {// failed to look up canonical path, continue with original one}scanDirTracedLI(odmAppDir,mDefParseFlags| PackageParser.PARSE_IS_SYSTEM_DIR,scanFlags| SCAN_AS_SYSTEM| SCAN_AS_VENDOR,0);// Collect all OEM packages.// 扫描收集目录 /oem/app 下的应用包 final File oemAppDir new File(Environment.getOemDirectory(), app);scanDirTracedLI(oemAppDir,mDefParseFlags| PackageParser.PARSE_IS_SYSTEM_DIR,scanFlags| SCAN_AS_SYSTEM| SCAN_AS_OEM,0);// Collected privileged product packages.// 扫描收集目录 /product/priv-app 下的应用包 File privilegedProductAppDir new File(Environment.getProductDirectory(), priv-app);try {privilegedProductAppDir privilegedProductAppDir.getCanonicalFile();} catch (IOException e) {// failed to look up canonical path, continue with original one}scanDirTracedLI(privilegedProductAppDir,mDefParseFlags| PackageParser.PARSE_IS_SYSTEM_DIR,scanFlags| SCAN_AS_SYSTEM| SCAN_AS_PRODUCT| SCAN_AS_PRIVILEGED,0);// Collect ordinary product packages.// 扫描收集目录 /product/app 下的应用包File productAppDir new File(Environment.getProductDirectory(), app);try {productAppDir productAppDir.getCanonicalFile();} catch (IOException e) {// failed to look up canonical path, continue with original one}scanDirTracedLI(productAppDir,mDefParseFlags| PackageParser.PARSE_IS_SYSTEM_DIR,scanFlags| SCAN_AS_SYSTEM| SCAN_AS_PRODUCT,0);Log.d(preinstall, scanDirTracedLI: System.currentTimeMillis());// Prune any system packages that no longer exist.// 删除已经不存在的系统应用包// possiblyDeletedUpdatedSystemApps 和 stubSystemApps 用于存储可能已删除或更新的系统应用的包名和存根应用的包名final ListString possiblyDeletedUpdatedSystemApps new ArrayList();// Stub packages must either be replaced with full versions in the /data// partition or be disabled.final ListString stubSystemApps new ArrayList();if (!mOnlyCore) {// do this first before mucking with mPackages for the expecting better casefinal IteratorPackageParser.Package pkgIterator mPackages.values().iterator();while (pkgIterator.hasNext()) {final PackageParser.Package pkg pkgIterator.next();if (pkg.isStub) { //对于标记为存根应用的包将其包名添加到 stubSystemApps 列表中stubSystemApps.add(pkg.packageName);}}final IteratorPackageSetting psit mSettings.mPackages.values().iterator();while (psit.hasNext()) {PackageSetting ps psit.next();// 如果不是系统应用跳过if ((ps.pkgFlags ApplicationInfo.FLAG_SYSTEM) 0) {continue;}final PackageParser.Package scannedPkg mPackages.get(ps.name);if (scannedPkg ! null) { // 如果系统应用包已经被扫描到了scannedPkg null就不会被删掉/** If the system app is both scanned and in the* disabled packages list, then it must have been* added via OTA. Remove it from the currently* scanned package so the previously user-installed* application can be scanned.*/// 如果系统应用包不仅被扫描过在mPackages中并且在不可用列表中// 说明一定是通过覆盖安装的移除之前扫描的结果保证之前用户安装的应用能够被扫描if (mSettings.isDisabledSystemPackageLPr(ps.name)) {logCriticalInfo(Log.WARN,Expecting better updated system app for ps.name ; removing system app. Last known codePath ps.codePathString , versionCode ps.versionCode ; scanned versionCode scannedPkg.getLongVersionCode());// 将之前的扫描结果移除removePackageLI(scannedPkg, true);// 将这包添加到 mExpectingBetter 列表中mExpectingBetter.put(ps.name, ps.codePath);}// 跳出循环确保不会被删掉continue;}// 如果系统应用包没有被扫描并且他也不在不可用的列表中移除它这个包不存在if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {psit.remove();logCriticalInfo(Log.WARN, System package ps.name no longer exists; its data will be wiped);// Actual deletion of code and data will be handled by later// reconciliation step} else {// 如果系统应用包没有被扫描却在不可用的列表中就将他加入到 // possiblyDeletedUpdatedSystemApps 集合中需要被删除final PackageSetting disabledPs mSettings.getDisabledSystemPkgLPr(ps.name);if (disabledPs.codePath null || !disabledPs.codePath.exists()|| disabledPs.pkg null) {possiblyDeletedUpdatedSystemApps.add(ps.name);}}}}//delete tmp files // 移除临时文件deleteTempPackageFiles();final int cachedSystemApps PackageParser.sCachedPackageReadCount.get();// Remove any shared userIDs that have no associated packages// 移除没有和应用程序包相关联的共享用户 idmSettings.pruneSharedUsersLPw();final long systemScanTime SystemClock.uptimeMillis() - startTime;final int systemPackagesCount mPackages.size();Slog.i(TAG, Finished scanning system apps. Time: systemScanTime ms, packageCount: systemPackagesCount , timePerPackage: (systemPackagesCount 0 ? 0 : systemScanTime / systemPackagesCount) , cached: cachedSystemApps);if (mIsUpgrade systemPackagesCount 0) {MetricsLogger.histogram(null, ota_package_manager_system_app_avg_scan_time,((int) systemScanTime) / systemPackagesCount);}//...2.2.1 主要流程 获得环境变量BOOTCLASSPATH 和 SYSTEMSERVERCLASSPATH 对共享库进行 odex 优化操作 判断是否是通过 OTA 升级的 如果是从 6.0 升级过来的保存从 Android 6.0 升级前已经存在的系统应用包并对他们进行优先扫描 扫描收集以下目录中的供应商应用包 /vendor/overlay/system/framework/system/priv-app/system/app/vendor/app/oem/app… 删除已经不存在的系统应用包 清理所有安装不完全的应用包 移除临时文件 移除没有和应用程序包相关联的共享用户 id
2.2.2 细节分析
环境变量
我们可以通过 adb shell env 来查看系统所有的环境变量及相应值。也可通过命令adb shell echo $var 来看指定的环境变量的值
SYSTEMSERVERCLASSPATH
evk_8mm:/ # echo $SYSTEMSERVERCLASSPATH
/system/framework/services.jar:
/system/framework/ethernet-service.jar:
/system/framework/wifi-service.jar:
/system/framework/com.android.location.provider.jarBOOTCLASSPATH 该环境变量内容较多第三方定制的系统可能有所不同原生内容包含 /system/framework目录下的framework.jarext.jarcore-libart.jartelephony-common.jarims-common.jarcore-junit.jar等文件
evk_8mm:/ # echo $BOOTCLASSPATH
/system/framework/core-oj.jar:
/system/framework/core-libart.jar:
/system/framework/conscrypt.jar:
/system/framework/okhttp.jar:
/system/framework/bouncycastle.jar:
/system/framework/apache-xml.jar:
/system/framework/ext.jar:
/system/framework/framework.jar:
/system/framework/telephony-common.jar:
/system/framework/voip-common.jar:
/system/framework/ims-common.jar:
/system/framework/android.hidl.base-V1.0-java.jar:
/system/framework/android.hidl.manager-V1.0-java.jar:
/system/framework/framework-oahl-backward-compatibility.jar:
/system/framework/android.test.base.jardexopt 优化
执行 dex 优化操作的文件有以下几类
mSharedLibraries该共享库下的所有文件是由 SystemConfig 构造函数中赋值的/system/framework该目录的所有 apk 和 jar 文件
scanDirLI 扫描系统目录
扫描指定目录下的 apk 文件最终调用 PackageParser.parseBaseApk 来完成 AndroidManifest.xml 文件的解析生成 Applicationactivityservicebroadcastprovider 等信息。
/vendor/overlay/system/framework/system/priv-app/system/app/vendor/app/oem/app
2.3 BOOT_PROGRESS_PMS_DATA_SCAN_START //... 接上面if (!mOnlyCore) {EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,SystemClock.uptimeMillis());//这里似乎还是在扫描scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);scanDirTracedLI(sDrmAppPrivateInstallDir, mDefParseFlags| PackageParser.PARSE_FORWARD_LOCK,scanFlags | SCAN_REQUIRE_KNOWN, 0);// Remove disable package settings for updated system apps that were// removed via an OTA. If the update is no longer present, remove the// app completely. Otherwise, revoke their system privileges.// 执行最终的清理工作以确保系统中不存在已删除或更新的系统应用的残留文件和数据并撤消相关应用的系统权限。for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {PackageParser.Package deletedPkg mPackages.get(deletedAppName);mSettings.removeDisabledSystemPackageLPw(deletedAppName);final String msg;if (deletedPkg null) {// should have found an update, but, we didnt; remove everythingmsg Updated system package deletedAppName no longer exists; removing its data;// Actual deletion of code and data will be handled by later// reconciliation step} else {// found an update; revoke system privilegesmsg Updated system package deletedAppName no longer exists; revoking system privileges;// Dont do anything if a stub is removed from the system image. If// we were to remove the uncompressed version from the /data partition,// this is where itd be done.final PackageSetting deletedPs mSettings.mPackages.get(deletedAppName);deletedPkg.applicationInfo.flags ~ApplicationInfo.FLAG_SYSTEM;deletedPs.pkgFlags ~ApplicationInfo.FLAG_SYSTEM;}logCriticalInfo(Log.WARN, msg);}// 确保所有在用户 data 分区的应用都显示出来了如果无法显示// 那就回滚显示 system 分区的for (int i 0; i mExpectingBetter.size(); i) {final String packageName mExpectingBetter.keyAt(i);if (!mPackages.containsKey(packageName)) {final File scanFile mExpectingBetter.valueAt(i);logCriticalInfo(Log.WARN, Expected better packageName but never showed up; reverting to system);// 设置扫描参数不同的目录扫描参数不同final ParseFlags int reparseFlags;final ScanFlags int rescanFlags;if (FileUtils.contains(privilegedAppDir, scanFile)) {reparseFlags mDefParseFlags |PackageParser.PARSE_IS_SYSTEM_DIR;rescanFlags scanFlags| SCAN_AS_SYSTEM| SCAN_AS_PRIVILEGED;} else if (FileUtils.contains(systemAppDir, scanFile)) {reparseFlags mDefParseFlags |PackageParser.PARSE_IS_SYSTEM_DIR;rescanFlags scanFlags| SCAN_AS_SYSTEM;} else if (FileUtils.contains(privilegedVendorAppDir, scanFile)|| FileUtils.contains(privilegedOdmAppDir, scanFile)) {reparseFlags mDefParseFlags |PackageParser.PARSE_IS_SYSTEM_DIR;rescanFlags scanFlags| SCAN_AS_SYSTEM| SCAN_AS_VENDOR| SCAN_AS_PRIVILEGED;} else if (FileUtils.contains(vendorAppDir, scanFile)|| FileUtils.contains(odmAppDir, scanFile)) {reparseFlags mDefParseFlags |PackageParser.PARSE_IS_SYSTEM_DIR;rescanFlags scanFlags| SCAN_AS_SYSTEM| SCAN_AS_VENDOR;} else if (FileUtils.contains(oemAppDir, scanFile)) {reparseFlags mDefParseFlags |PackageParser.PARSE_IS_SYSTEM_DIR;rescanFlags scanFlags| SCAN_AS_SYSTEM| SCAN_AS_OEM;} else if (FileUtils.contains(privilegedProductAppDir, scanFile)) {reparseFlags mDefParseFlags |PackageParser.PARSE_IS_SYSTEM_DIR;rescanFlags scanFlags| SCAN_AS_SYSTEM| SCAN_AS_PRODUCT| SCAN_AS_PRIVILEGED;} else if (FileUtils.contains(productAppDir, scanFile)) {reparseFlags mDefParseFlags |PackageParser.PARSE_IS_SYSTEM_DIR;rescanFlags scanFlags| SCAN_AS_SYSTEM| SCAN_AS_PRODUCT;} else {Slog.e(TAG, Ignoring unexpected fallback path scanFile);continue;}// 设置系统 package 可用mSettings.enableSystemPackageLPw(packageName);// 重新解析 system 分区的 packagetry {scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);} catch (PackageManagerException e) {Slog.e(TAG, Failed to parse original system package: e.getMessage());}}}// Uncompress and install any stubbed system applications.// This must be done last to ensure all stubs are replaced or disabled.decompressSystemApplications(stubSystemApps, scanFlags);final int cachedNonSystemApps PackageParser.sCachedPackageReadCount.get()- cachedSystemApps;final long dataScanTime SystemClock.uptimeMillis() - systemScanTime - startTime;final int dataPackagesCount mPackages.size() - systemPackagesCount;Slog.i(TAG, Finished scanning non-system apps. Time: dataScanTime ms, packageCount: dataPackagesCount , timePerPackage: (dataPackagesCount 0 ? 0 : dataScanTime / dataPackagesCount) , cached: cachedNonSystemApps);if (mIsUpgrade dataPackagesCount 0) {MetricsLogger.histogram(null, ota_package_manager_data_app_avg_scan_time,((int) dataScanTime) / dataPackagesCount);}}mExpectingBetter.clear(); // 清空 mExpectingBetter 列表// Resolve the storage manager.mStorageManagerPackage getStorageManagerPackageName();// Resolve protected action filters. Only the setup wizard is allowed to// have a high priority filter for these actions.mSetupWizardPackage getSetupWizardPackageName();if (mProtectedFilters.size() 0) {if (DEBUG_FILTERS mSetupWizardPackage null) {Slog.i(TAG, No setup wizard; All protected intents capped to priority 0);}for (ActivityIntentInfo filter : mProtectedFilters) {if (filter.activity.info.packageName.equals(mSetupWizardPackage)) {if (DEBUG_FILTERS) {Slog.i(TAG, Found setup wizard; allow priority filter.getPriority() ; package: filter.activity.info.packageName activity: filter.activity.className priority: filter.getPriority());}// skip setup wizard; allow it to keep the high priority filtercontinue;}if (DEBUG_FILTERS) {Slog.i(TAG, Protected action; cap priority to 0; package: filter.activity.info.packageName activity: filter.activity.className origPrio: filter.getPriority());}filter.setPriority(0);}}mSystemTextClassifierPackage getSystemTextClassifierPackageName();mDeferProtectedFilters false;mProtectedFilters.clear();// 这里我们已经找到了所有的共享库文件// 我们需要更新所有的应用保证他们有正确的共享库路径。updateAllSharedLibrariesLPw(null);for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {// NOTE: We ignore potential failures here during a system scan (like// the rest of the commands above) because theres precious little we// can do about it. A settings error is reported, though.final ListString changedAbiCodePath adjustCpuAbisForSharedUserLPw(setting.packages, null /*scannedPackage*/);if (changedAbiCodePath ! null changedAbiCodePath.size() 0) {for (int i changedAbiCodePath.size() - 1; i 0; --i) {final String codePathString changedAbiCodePath.get(i);try {mInstaller.rmdex(codePathString,getDexCodeInstructionSet(getPreferredInstructionSet()));} catch (InstallerException ignored) {}}}// Adjust seInfo to ensure apps which share a sharedUserId are placed in the same// SELinux domain.setting.fixSeInfoLocked();}// 到这里系统中所有的 package 都被扫描到了这里是更新他们上一次的使用信息mPackageUsage.read(mPackages);mCompilerStats.read();//....当mOnlyCore false时则 scanDirLI 还会收集如下目录中的 apk 的信息
/data/app/data/app-private
2.4 BOOT_PROGRESS_PMS_SCAN_END EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis());Slog.i(TAG, Time to scan packages: ((SystemClock.uptimeMillis()-startTime)/1000f) seconds);// If the platform SDK has changed since the last time we booted,// we need to re-grant app permission to catch any new ones that// appear. This is really a hack, and means that apps can in some// cases get permissions that the user didnt initially explicitly// allow... it would be nice to have some better way to handle// this situation.// 如果从我们上次启动SDK 平台被改变了我们需要重新授予应用程序权限。final boolean sdkUpdated (ver.sdkVersion ! mSdkVersion);if (sdkUpdated) {Slog.i(TAG, Platform changed from ver.sdkVersion to mSdkVersion ; regranting permissions for internal storage);}// 赋予 package 相应请求的权限 mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, mPackages.values(),mPermissionCallback);ver.sdkVersion mSdkVersion;// If this is the first boot or an update from pre-M, and it is a normal// boot, then we need to initialize the default preferred apps across// all defined users.// 如果这是第一次开机或前-M的更新这是一个正常的启动然后我们需要初始化默认的首选应用程序给所有已经定义的用户。if (!onlyCore (mPromoteSystemApps || mFirstBoot)) {for (UserInfo user : sUserManager.getUsers(true)) {mSettings.applyDefaultPreferredAppsLPw(this, user.id);applyFactoryDefaultBrowserLPw(user.id);primeDomainVerificationsLPw(user.id);}}// Prepare storage for system user really early during boot,// since core system apps like SettingsProvider and SystemUI// cant wait for user to startfinal int storageFlags;if (StorageManager.isFileEncryptedNativeOrEmulated()) {storageFlags StorageManager.FLAG_STORAGE_DE;} else {storageFlags StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;}ListString deferPackages reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,true /* onlyCoreApps */);mPrepareAppDataFuture SystemServerInitThreadPool.get().submit(() - {TimingsTraceLog traceLog new TimingsTraceLog(SystemServerTimingAsync,Trace.TRACE_TAG_PACKAGE_MANAGER);traceLog.traceBegin(AppDataFixup);try {mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL,StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);} catch (InstallerException e) {Slog.w(TAG, Trouble fixing GIDs, e);}traceLog.traceEnd();traceLog.traceBegin(AppDataPrepare);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;}}traceLog.traceEnd();Slog.i(TAG, Deferred reconcileAppsData finished count packages);}, prepareAppData);// If this is first boot after an OTA, and a normal boot, then// we need to clear code cache directories.// Note that we do *not* clear the application profiles. These remain valid// across OTAs and are used to drive profile verification (post OTA) and// profile compilation (without waiting to collect a fresh set of profiles).// 如果这是在OTA升级后第一启动这是正常的启动然后我们需要清除代码缓存目录。if (mIsUpgrade !onlyCore) {Slog.i(TAG, Build fingerprint changed; clearing code caches);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)) {// No apps are running this early, so no need to freezeclearAppDataLIF(ps.pkg, UserHandle.USER_ALL,StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);}}ver.fingerprint Build.FINGERPRINT;}checkDefaultBrowser();// clear only after permissions and other defaults have been updated// 当权限和其他默认设置被更新后执行清除操作。mExistingSystemPackages.clear();mPromoteSystemApps false;// All the changes are done during package scanning.ver.databaseVersion Settings.CURRENT_DATABASE_VERSION;// can downgrade to reader// 信息写回 packages.xml 文件Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, write settings);mSettings.writeLPr();Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);//...2.5 BOOT_PROGRESS_PMS_READY EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,SystemClock.uptimeMillis());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;}// 建立 PackageInstallerService 服务对象mInstallerService new PackageInstallerService(context, this);final PairComponentName, String instantAppResolverComponent getInstantAppResolverLPr();if (instantAppResolverComponent ! null) {if (DEBUG_INSTANT) {Slog.d(TAG, Set ephemeral resolver: instantAppResolverComponent);}mInstantAppResolverConnection new InstantAppResolverConnection(mContext, instantAppResolverComponent.first,instantAppResolverComponent.second);mInstantAppResolverSettingsComponent getInstantAppResolverSettingsLPr(instantAppResolverComponent.first);} else {mInstantAppResolverConnection null;mInstantAppResolverSettingsComponent null;}updateInstantAppInstallerLocked(null);// Read and update the usage of dex files.// Do this at the end of PM init so that all the packages have their// data directory reconciled.// At this point we know the code paths of the packages, so we can validate// the disk file and build the internal cache.// The usage file is expected to be small so loading and verifying it// should take a fairly small time compare to the other activities (e.g. package// scanning).final MapInteger, ListPackageInfo 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)// Now after opening every single application zip, make sure they// are all flushed. Not really needed, but keeps things nice and// tidy.Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, GC);Runtime.getRuntime().gc();Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);// The initial scanning above does many calls into installd while// holding the mPackages lock, but were mostly interested in yelling// once we have a booted system.mInstaller.setWarnIfHeld(mPackages);Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);Log.d(preinstall, start preinstallSystem.currentTimeMillis());mHandler.postDelayed(new Runnable() {public void run() {try{SystemProperties.set(ctl.start, preinstall);}catch (Exception e){Log.d(preinstall, preinstall failed);e.printStackTrace();}}},1200);
PKMS 初始化完成阶段还会创建一个 PackageInstaller 服务。
四、总结
总结 PackageManagerService 的初始化工作都是在它的构造函数中完成的主要完成一下任务
添加一些用户 id如 system、phone 等解析 /system/etc/permission 下的 xml 文件主要 是 platform.xml建立 permission 和 gid 之间的关系可以指定一个权限与几个组对应当一个 apk 被授予这个权限时它也同时属于这几个组readPermission(parser perm) 给一些底层用户分配一些权限如 shell 授予各种 permission把一个权限赋予一个 uid当 apk 使用这个 uid 运行时就具备了这个权限系统增加的一些应用需要 link 的扩展的 jar 库系统每增加一个硬件都要添加相应的 featrue将解析结果放入 mAvailableFeatures;建立并启动 PackageHandler 消息循环用于处理 apk 安装请求如 adb installpackage installer 安装 apk 时就会发送消息检查 /data/system/packages.xml 是否存在里面记录了系统的 permission以及每个apk的 namecodePathflagstsversionuserid 等这些信息主要是通过 apk 安装的时候解析 AndroidManifest.xml 获取到的解析完 apk 后将更新信息写入这个文件并保存到 flash下次开机直接从里面读取相关信息添加到内存相关列表中当有 apk 安装升级删除时会更新这个文件检查 BootClassPathmSharedLibraries 及 /system/framework 下的jar是否需要 dexopt 需要则通过 dexopt 进行优化这里面主要是调用 mInstaller.dexopt 进行相应的优化建立 java 层的 installer 与 c 层的 installd 的 socket 联接使得在上层的 installremovedexopt 等功能最终由 installd 在底层实现启动 AppDirObserver 线程往中监测 /system/framework/system/app/data/app/data/app-private 目录的事件主要监听 add 和 remove 事件对于目录监听底层通过 inotify 机制实现inotify 是一种文件系统的变化通知机制如文件增加、删除等事件可以立刻让用户态得知它为用户态监视文件系统的变化提供了强大的支持当有 add event 时调用 scanPackageLI(Fileinint) 处理当有 remove event 时调用 removePackageLI 处理调用 scanDirLI 启动 apk 解析解析目录包括/system/framework、/system/app、/vendor/app、/data/app、/data/app-private移除临时文件赋予 package 相应请求的权限将解析出的 Package 的相关信息保存到相关全局变量还有文件。