PackageManagerService Android 8.1 源码解读 02

接上文:PackageManagerService Android 8.1 源码解读 01

d、第三步细节:PKMS.main(),main函数主要工作:

  1. 检查】Package编译相关系统属性
  2. 调用】PackageManagerService【构造方法】
  3. 启用】部分【应用服务】于多用户场景
  4. 注册】服务【”package”】和【”package_native”】到ServiceManager中。
public static PackageManagerService main(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
    // (1)检查Package编译相关系统属性
    PackageManagerServiceCompilerMapping.checkProperties();
    //(2)调用PackageManagerService构造方法, 可以参考【PKMS构造方法】
    PackageManagerService m = new PackageManagerService(context, installer,
            factoryTest, onlyCore);
    //(3)启用部分应用服务于多用户场景
    m.enableSystemUserPackages();
    //(4)往ServiceManager中注册”package”和”package_native”
    ServiceManager.addService("package", m);
    final PackageManagerNative pmn = m.new PackageManagerNative();
    ServiceManager.addService("package_native", pmn);
    return m;
}

d.1、函数checkProperties(),主要是检测编译属性的有效性,如果不合法,直接报错;

// Check that the properties are set and valid.
// Note: this is done in a separate method so this class can be statically initialized.
static void checkProperties() {
    // We're gonna check all properties and collect the exceptions, so we can give a general
    // overview. Store the exceptions here.
    RuntimeException toThrow = null;
    // REASON_LAST = 6
    for (int reason = 0; reason <= PackageManagerService.REASON_LAST; reason++) {
        try {
            // 循环检测系统属性名称的合法性
            String sysPropName = getSystemPropertyName(reason);
            if (sysPropName == null || sysPropName.isEmpty()) {
                throw new IllegalStateException("Reason system property name \"" +
                        sysPropName +"\" for reason " + REASON_STRINGS[reason]);
            }

            // 检测属性的有效性,忽略结果
            getAndCheckValidity(reason);
        } catch (Exception exc) {
            if (toThrow == null) {
                toThrow = new IllegalStateException("PMS compiler filter settings are bad.");
            }
            toThrow.addSuppressed(exc);
        }
    }

    if (toThrow != null) {
        throw toThrow;
    }
}
//获取系统属性名称
private static String getSystemPropertyName(int reason) {
    if (reason < 0 || reason >= REASON_STRINGS.length) {
        throw new IllegalArgumentException("reason " + reason + " invalid");
    }

    return "pm.dexopt." + REASON_STRINGS[reason];
}
//编译原因的名称。
static final String REASON_STRINGS[] = {
        "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "inactive", "shared"
};

// 根据给定的原因加载属性并检查其有效性。如果原因或值无效,这将引发异常。
private static String getAndCheckValidity(int reason) {
    String sysPropValue = SystemProperties.get(getSystemPropertyName(reason));
    if (sysPropValue == null || sysPropValue.isEmpty() ||
            !DexFile.isValidCompilerFilter(sysPropValue)) {
        throw new IllegalStateException("Value \"" + sysPropValue +"\" not valid "
                + "(reason " + REASON_STRINGS[reason] + ")");
    } else if (!isFilterAllowedForReason(reason, sysPropValue)) {
        throw new IllegalStateException("Value \"" + sysPropValue +"\" not allowed "
                + "(reason " + REASON_STRINGS[reason] + ")");
    }

    return sysPropValue;
}

检测到我的设备的属性名称如下:

k37mv1_bsp:/ $ getprop |grep pm.dexopt
[pm.dexopt.ab-ota]: [speed-profile]
[pm.dexopt.bg-dexopt]: [speed-profile]
[pm.dexopt.boot]: [verify]
[pm.dexopt.downgrade_after_inactive_days]: [10]
[pm.dexopt.first-boot]: [quicken]
[pm.dexopt.inactive]: [verify]
[pm.dexopt.install]: [quicken]
[pm.dexopt.shared]: [quicken]
k37mv1_bsp:/ $ 

d.2、【PKMS构造方法】:重点分析,内容比较多

d.2.1、KMS初始化时的核心部分为PKMS()构造函数的内容,我们下面就来分析该流程:
PKMS的构造函数中由两个重要的锁(mInstallLockmPackages):

 

  • mInstallLock】 :用来保护所有安装apk的访问权限,此操作通常涉及【繁重的磁盘数据读写】等操作,并且是【单线程操作】,故有时候会【处理很慢】,此锁不会在已经持有mPackages锁的情况下持有,反之,在已经持有mInstallLock锁的情况下,立即获取mPackages是安全的
  • mPackages】:用来解析【内存中所有apk的package信息】及相关状态

和五个阶段组成:

  • 阶段1:BOOT_PROGRESS_PMS_START:PKMS开始阶段
  • 阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START:扫描系统app阶段
  • 阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START:扫描data目录阶段
  • 阶段4:BOOT_PROGRESS_PMS_SCAN_END:扫描结束
  • 阶段5:BOOT_PROGRESS_PMS_READY:pms做准备
     

阶段1:BOOT_PROGRESS_PMS_START:PKMS开始阶段

  • (1) 构造 【DisplayMetrics】 ,保存分辨率等相关信息;
  • (2) 构造【Settings】类,保存安装包信息,清除路径不存在的孤立应用,主要涉及/data/system/目录的packages.xml,packages-backup.xml,packages.list,packages-stopped.xml,packages-stoppedbackup.xml等文件。
  • (3) 创建【Installer】对象,与installd交互;
  • (4) 构造【PackageDexOptimizerDexManager】类,处理dex优化;
  • (5) 创建【SystemConfig】实例,获取系统配置信息,配置共享lib库;
  • (6) 创建【mSystemPermissions】对象,进行权限管理;
  • (7) 创建【PackageManager的handler】线程,循环处理外部安装相关消息。
     
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());
    // 保存上下文的引用 
		mContext = context;
		// 一般为false,即非工厂生产模式
    mFactoryTest = factoryTest;
    // 标记是否只加载核心服务,一般都是false
    mOnlyCore = onlyCore;
    // (1) 构造 DisplayMetrics ,保存分辨率等相关信息;
    mMetrics = new DisplayMetrics();
    // (2)构造Settings类,保存安装包信息,清除路径不存在的孤立应用,主要涉
    // 及/data/system/目录的packages.xml,packages-backup.xml, packages.list,
    // packages-stopped.xml,packages-stopped-backup.xml等文件。
    // 添加system, phone, log, nfc, bluetooth, shell 这6种shareUserId到mSettings;
    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);
    ......省略
    // (3)创建Installer对象,与installd交互;
    mInstaller = installer;
    // (4)构造【PackageDexOptimizer及DexManager】类,处理dex优化
    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);
		// (5)创建【SystemConfig】实例,获取系统配置信息,配置共享lib库;
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "get system config");
    // 这是一个单例模式,保存着系统的权限
    SystemConfig systemConfig = SystemConfig.getInstance();
    mGlobalGids = systemConfig.getGlobalGids();
    // (6)获取系统权限
    mSystemPermissions = systemConfig.getSystemPermissions();
    mAvailableFeatures = systemConfig.getAvailableFeatures();
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
		// 受保护的包名对象
    mProtectedPackages = new ProtectedPackages(mContext);
    // 创建提供服务、数据的子组件。
    // 这里的顺序很重要,使用到了两个重要的同步锁:mInstallLock、mPackages
    synchronized (mInstallLock) {
    // writer
    synchronized (mPackages) {
        // (7)创建PackageManager的handler线程,循环处理外部安装相关消息。
        // 启动"PackageManager"线程,负责apk的安装、卸载
	      mHandlerThread = new ServiceThread(TAG,
	              Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
	      mHandlerThread.start();
	      // 应用handler
	      mHandler = new PackageHandler(mHandlerThread.getLooper());
	      // 进程记录handler
	      mProcessLoggingHandler = new ProcessLoggingHandler();
	      // Watchdog监听ServiceThread是否超时:10分钟
	      Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
				// 创建默认的权限策略对象
	      mDefaultPermissionPolicy = new DefaultPermissionGrantPolicy(this);
	      // Instant应用注册
	      mInstantAppRegistry = new InstantAppRegistry(this);
				// 创建/data/app目录和/data/app-lib目录,/data/app-asec,已经/data/app-private目录
	      File dataDir = Environment.getDataDirectory();
	      // 创建/data/app目录
	      mAppInstallDir = new File(dataDir, "app");
	      // 创建/data/app-lib目录
	      mAppLib32InstallDir = new File(dataDir, "app-lib");
	      // 创建/data/app-asec目录
	      mAsecInternalPath = new File(dataDir, "app-asec").getPath();
	      // /data/app-private目录
	      mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
	      // 窗机用户管理服务
	      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);
	          }
	      }
				// 共享lib库配置
	      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);
	      }
				// 读取安装相关SELinux策略
	      mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
	
	      Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
	      // 读取并解析/data/system下的XML文件
	      mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
	      Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
	
	      // Clean up orphaned packages for which the code path doesn't exist
	      // and they are an update to a system app - caused by bug/32321269
	      // 清理代码路径不存在的孤立软件包
	      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);
	          }
	      }
				// 如果不是首次启动,也不是CORE应用,则拷贝预编译的DEX文件
	      if (!mOnlyCore && mFirstBoot) {
	          requestCopyPreoptedFiles();
	      }
				// 获取客制化的Activity,
	      String customResolverActivity = Resources.getSystem().getString(
	              R.string.config_customResolverActivity);
	      if (TextUtils.isEmpty(customResolverActivity)) {
	          customResolverActivity = null;
	      } else {
	          mCustomResolverComponentName = ComponentName.unflattenFromString(
	                  customResolverActivity);
	      }
	
	      long startTime = SystemClock.uptimeMillis();
          ...............

    }
    }
    ......
}

重点分析一下readLPw,mSettings.readLPwreadLPw()会扫描下面5个文件

  • 1) "/data/system/packages.xml" :所有安装app信息
  • 2) "/data/system/packages-backup.xml" :所有安装app信息之备份的信息记录
  • 3) "/data/system/packages.list" :所有安装app信息
  • 4) "/data/system/packages-stopped.xml" :所有强制停止app信息
  • 5) "/data/system/packages-stopped-backup.xml" :所有强制停止app信息之备份的信息记录

五个文件共分为三组,简单的作用描述如下:

  1. packages.xml】:PKMS 扫描完目标文件夹后会创建该文件。当系统进行程序安装、卸载和更新等操作时,均会更新该文件。该文件保存了系统中与 package 相关的一些信息。
  2. packages.list】:描述系统中存在的所有非系统自带的 APK 的信息。当这些程序有变动时,PKMS 就会更新该文件。
  3. packages-stopped.xml】:从系统自带的设置程序中进入应用程序页面,然后在选择强制停止(ForceStop)某个应用时,系统会将该应用的相关信息记录到此文件中。也就是该文件保存系统中被用户强制停止的 Package 的信息。

这些目录的指向,都在Settings中的构造函数完成, 如下所示,得到目录后调用readLPw()进行扫描

Settings(File dataDir, Object lock) {
    mLock = lock;

    mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
		// mSystemDir指向目录"/data/system"
    mSystemDir = new File(dataDir, "system");
    // 创建 "/data/system"
    mSystemDir.mkdirs();
    // 设置权限
    FileUtils.setPermissions(mSystemDir.toString(),
            FileUtils.S_IRWXU|FileUtils.S_IRWXG
            |FileUtils.S_IROTH|FileUtils.S_IXOTH,
            -1, -1);
    // (1)指向目录"/data/system/packages.xml"
    mSettingsFilename = new File(mSystemDir, "packages.xml");
    // (2)指向目录"/data/system/packages-backup.xml"
    mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
    // (3)指向目录"/data/system/packages.list"
    mPackageListFilename = new File(mSystemDir, "packages.list");
    FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);

    final File kernelDir = new File("/config/sdcardfs");
    mKernelMappingFilename = kernelDir.exists() ? kernelDir : null;

    // Deprecated: Needed for migration
    // (4)指向目录"/data/system/packages-stopped.xml"
    mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
    // (5)指向目录"/data/system/packages-stopped-backup.xml"
    mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}

继续看:readLPw()函数

boolean readLPw(@NonNull List<UserInfo> users) {
    FileInputStream str = null;
   	......省略
        if (str == null) {
            ......省略
            str = new FileInputStream(mSettingsFilename);
        }
        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(str, StandardCharsets.UTF_8.name());

        int type;//遍历文件,查找xml文件的第一个起始字符
        while ((type = parser.next()) != XmlPullParser.START_TAG
                && type != XmlPullParser.END_DOCUMENT) {
            ;
        }
		......省略

        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;
            }
			// 根据XML的各个节点进行各种操作,例如读取权限、shared-user等
            String tagName = parser.getName();
            if (tagName.equals("package")) {
                readPackageLPw(parser);
            } else if (tagName.equals("permissions")) {
                readPermissionsLPw(mPermissions, parser);
            } else if (tagName.equals("permission-trees")) {
                readPermissionsLPw(mPermissionTrees, parser);
            } else if (tagName.equals("shared-user")) {
                readSharedUserLPw(parser);
            } 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);
            } ......省略

        str.close();
    ......
    return true;
}

 

阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START:扫描系统app阶段

  • (1) 从【init.rc】中获取环境变量BOOTCLASSPATHSYSTEMSERVERCLASSPATH
  • (2) 对于【旧版本升级】的情况,将【安装时】获取权限变更为【运行时】申请权限;
  • (3) 【扫描】system/vendor/product/odm/oem等目录的priv-app、app、overlay包;
  • (4) 【清除】安装时临时文件以及其他不必要的信息。
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
	synchronized (mInstallLock) {
	synchronized (mPackages) {
		// 记录扫描开始时间
			EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
			        startTime);
			// (1)从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH;
			final String bootClassPath = System.getenv("BOOTCLASSPATH");
			final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
			......省略
			// 获取system/framework目录
			File frameworkDir = new File(Environment.getRootDirectory(), "framework");
			// 获取内部版本
			final VersionInfo ver = mSettings.getInternalVersion();
			// 判断fingerprint是否有更新
			mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
			if (mIsUpgrade) {
			    logCriticalInfo(Log.INFO,
			            "Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT);
			}
			// (2)对于旧版本升级的情况,将安装时获取权限变更为运行时申请权限
			// 对于Android M之前版本升级上来的情况,需将系统应用程序权限从安装升级到运行时
			mPromoteSystemApps =
			        mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;
			
			// 对于Android N之前版本升级上来的情况,需像首次启动一样处理package
			mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;
			
			mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
			
			// 在扫描之前保存预先存在的系统package的名称,不希望自动为新系统应用授予运行时权限
			if (mPromoteSystemApps) {
			    Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
			    while (pkgSettingIter.hasNext()) {
			        PackageSetting ps = pkgSettingIter.next();
			        if (isSystemApp(ps)) {
			            mExistingSystemPackages.add(ps.name);
			        }
			    }
			}
			// 准备解析package的缓存
			mCacheDir = preparePackageParserCache(mIsUpgrade);
			
			// 设置flag,而不在扫描安装时更改文件路径
			int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
			
			if (mIsUpgrade || mFirstBoot) {
			    scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
			}
			
			// (3)扫描"/vendor/overlay"等目录的priv-app、app文件;
			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();
			// 扫描"/system/framework"目录;
			// Find base frameworks (resource packages without code).
			scanDirTracedLI(frameworkDir, mDefParseFlags
			        | PackageParser.PARSE_IS_SYSTEM
			        | PackageParser.PARSE_IS_SYSTEM_DIR
			        | PackageParser.PARSE_IS_PRIVILEGED,
			        scanFlags | SCAN_NO_DEX, 0);
			
			
			// Collected privileged system packages.
			// 扫描"/system/priv-app"目录;
			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);
			
			// Collect ordinary system packages.
			// 扫描"/system/app"目录
			final File systemAppDir = new File(Environment.getRootDirectory(), "app");
			scanDirTracedLI(systemAppDir, mDefParseFlags
			        | PackageParser.PARSE_IS_SYSTEM
			        | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
			
			// Collect all vendor packages.
			// 扫描"/vendor/app"目录
			File vendorAppDir = new File("/vendor/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
			        | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
			
			// Collect all OEM packages.
			// 扫描"/oem/app"目录
			final File oemAppDir = new File(Environment.getOemDirectory(), "app");
			scanDirTracedLI(oemAppDir, mDefParseFlags
			        | PackageParser.PARSE_IS_SYSTEM
			        | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
			
			// 删除任何不再存在的系统包.
			final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
			// Stub packages must either be replaced with full versions in the /data
			// partition or be disabled.
			final List<String> stubSystemApps = new ArrayList<>();
			// 删掉不存在的package
			if (!mOnlyCore) {
			    // do this first before mucking with mPackages for the "expecting better" case
			    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();
			        // 如果不是系统应用,则不被允许disable
			        if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
			            /// M: Operator apps are belong to system domain, therefore, need prune.
			            /// We should also consider OTA from old version without mtkFlag
			            if (sPmsExt.isNotOperatorApp(ps))
			                continue;
			        }
			
			        // 如果应用被扫描,则不允许被擦除
			        final PackageParser.Package scannedPkg = mPackages.get(ps.name);
			        if (scannedPkg != null) {
			            // 如果系统应用被扫描且存在disable应用列表中,则只能通过OTA升级添加
			            if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
			                ......
			                removePackageLI(scannedPkg, true);
			                mExpectingBetter.put(ps.name, ps.codePath);
			            }
			
			            continue;
			        }
			
			        if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
			            psit.remove();
			            logCriticalInfo(Log.WARN, "System package " + ps.name
			                    + " no longer exists; it's data will be wiped");
			            // Actual deletion of code and data will be handled by later
			            // reconciliation step
			        } else {
			            // we still have a disabled system package, but, it still might have
			            // been removed. check the code path still exists and check there's
			            // still a package. the latter can happen if an OTA keeps the same
			            // code path, but, changes the package name.
			            final PackageSetting disabledPs =
			                    mSettings.getDisabledSystemPkgLPr(ps.name);
			            if (disabledPs.codePath == null || !disabledPs.codePath.exists()
			                    || disabledPs.pkg == null) {
			                possiblyDeletedUpdatedSystemApps.add(ps.name);
			            }
			        }
			    }
			}
			
			//look for any incomplete package installations
			ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
			for (int i = 0; i < deletePkgsList.size(); i++) {
			    // Actual deletion of code and data will be handled by later
			    // reconciliation step
			    final String packageName = deletePkgsList.get(i).name;
			    logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + packageName);
			    synchronized (mPackages) {
			        mSettings.removePackageLPw(packageName);
			    }
			}
			// (4)清除安装时临时文件以及其他不必要的信息。
      // 删除临时文件
			deleteTempPackageFiles();
			
			final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get();
			
			// 删除没有关联应用的共享UID标识
			mSettings.pruneSharedUsersLPw();
			final long systemScanTime = SystemClock.uptimeMillis() - startTime;
			final int systemPackagesCount = mPackages.size();
			......
			}
			}
}

 

阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START:扫描data目录阶段

对于不仅仅解析核心应用的情况下,还处理data目录的应用信息,及时更新,去除不必要的数据

if (!mOnlyCore) {
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
            SystemClock.uptimeMillis());
    // 扫描app安装目录:/data/app
    scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
		// 扫描app-private目录:/data/app-private
    scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
            | PackageParser.PARSE_FORWARD_LOCK,
            scanFlags | SCAN_REQUIRE_KNOWN, 0);

    // 移除通过OTA删除的更新系统应用程序的禁用package设置
    // 如果更新不再存在,则完全删除该应用。否则,撤消其系统权限
    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 didn't; remove everything
            msg = "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 privileges
            msg = "Updated system package + " + deletedAppName
                    + " no longer exists; revoking system privileges";

            // Don't 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 it'd be done.

            final PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
            deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
            deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
        }
        logCriticalInfo(Log.WARN, msg);
    }

    // 确保期望在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);

            logCriticalInfo(Log.WARN, "Expected better " + packageName
                    + " but never showed up; reverting to system");

            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 {
                Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                continue;
            }

            mSettings.enableSystemPackageLPw(packageName);

            try {
            		//扫描APK
                scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);
            } catch (PackageManagerException e) {
                Slog.e(TAG, "Failed to parse original system package: "
                        + e.getMessage());
            }
        }
    }

    // 解压缩并安装任何存根系统应用程序。必须最后执行此操作以确保替换或禁用所有存根
    decompressSystemApplications(stubSystemApps, scanFlags);
    ......
}
mExpectingBetter.clear();

// 获取storage manager包名
mStorageManagerPackage = getStorageManagerPackageName();

// 解决受保护的action过滤器。只允许setup wizard(开机向导)为这些action
// 设置高优先级过滤器
mSetupWizardPackage = getSetupWizardPackageName();
......

// 更新客户端以确保持有正确的共享库路径
updateAllSharedLibrariesLPw(null);
......
// 读取并更新要保留的package的上次使用时间
mPackageUsage.read(mPackages);
mCompilerStats.read();

 

阶段4:BOOT_PROGRESS_PMS_SCAN_END:扫描结束

  • (1) 【sdk版本】变更,更新权限;
  • (2) 【OTA升级】后首次启动,清除不必要的缓存数据;
  • (3) 【权限】等默认项更新完后,清理相关数据;
  • (4) 【更新】package.xml
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
        SystemClock.uptimeMillis());
Slog.i(TAG, "Time to scan packages: "
        + ((SystemClock.uptimeMillis()-startTime)/1000f)
        + " seconds");
// (1) sdk版本变更,更新权限;
// 如果自上次启动以来,平台SDK已改变,则需要重新授予应用程序权限以捕获出现的任何新权限
int updateFlags = UPDATE_PERMISSIONS_ALL;
if (ver.sdkVersion != mSdkVersion) {
    Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
            + mSdkVersion + "; regranting permissions for internal storage");
    updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
}
// 更新权限
updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
// 设置sdk的版本
ver.sdkVersion = mSdkVersion;

// 如果这是第一次启动或来自Android M之前的版本的升级,并且它是正常启动,那需要在
// 所有已定义的用户中初始化默认的首选应用程序
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(() -> {
    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");

// (2) OTA升级后首次启动,清除不必要的缓存数据;
// 如果是在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 freeze
            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();

// (3) 权限等默认项更新完后,清理相关数据;
// 仅在权限或其它默认配置更新后清除
mExistingSystemPackages.clear();
mPromoteSystemApps = false;

// 所有变更均在扫描过程中完成
ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;

//【同学们注意】(4) 更新package.xml
// 降级去读取
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings");
mSettings.writeLPr();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

 

阶段5:BOOT_PROGRESS_PMS_READY:pms做准备

GC回收内存 和一些细节而已

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 {
    ......省略,都是if体的清空数据
}
// 创建PackageInstallerService服务
mInstallerService = new PackageInstallerService(context, this);
final Pair<ComponentName, String> instantAppResolverComponent =
        getInstantAppResolverLPr();
if (instantAppResolverComponent != null) {
    if (DEBUG_EPHEMERAL) {
        Slog.d(TAG, "Set ephemeral resolver: " + instantAppResolverComponent);
    }
    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);
} // synchronized (mPackages)
} // synchronized (mInstallLock)


// GC回收内存
// 打开应用之后,及时回收处理
Runtime.getRuntime().gc();

// 返回栈的回滚
FallbackCategoryProvider.loadFallbacks();

// 上面的初始扫描在持有mPackage锁的同时对installd进行了多次调用
mInstaller.setWarnIfHeld(mPackages);

// 将PackageManagerInternalImpl添加到本地服务中
LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());

下一篇继续,将进入三部曲

PackageManagerService Android 8.1 源码解读 03
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值