PKMS 分析

1,693 阅读17分钟

简述

PackageManagerService(简称 PKMS),是 Android 系统中核心服务之一,负责应用程序的安装卸载信息查询,等工作。

PKMS服务也是通过binder进行通信,IPackageManager.aidl由工具转换后自动生成binder的服务端IPackageManager.Stub和客户端IPackageManager.Stub.Proxy,具体关系如图:

  • Binder服务端:PackageManagerService继承于IPackageManager.Stub;
  • Binder客户端:ApplicationPackageManager(简称APM)的成员变量mPM继承于IPackageManager.Stub.Proxy; 本身APM是继承于PackageManager对象。

PKMS 启动过程

我们知道PKMS 是Android 的核心服务之一,他在我们SystemServer进程中启动。

SystemServer启动PKMS: 先是在SystemServer.startBootstrapServices()函数中启动PKMS服务, 再调用startOtherServices()函数中对dex优化,磁盘管理功能,让PKMS进入systemReady状态。

核心步骤

SystemServer.startBootstrapServices()

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
  //1.启动Installer服务
  Installer installer = mSystemServiceManager.startService(Installer.class);
  //2.获取设备是否加密(手机设置密码),如果设备加密了,则只解析"core"应用
  String cryptState = VoldProperties.decrypt().orElse("");
  if (ENCRYPTING_STATE.equals(cryptState)) {
      mOnlyCore = true;
  } else if (ENCRYPTED_STATE.equals(cryptState)) {
      mOnlyCore = true;
  }
  //3.调用PKMS main方法初始化PackageManagerService,其中调用PackageManagerService() 构造函数创建了PKMS对象
  mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
              mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
  //PKMS是否是第一次启动
  mFirstBoot = mPackageManagerService.isFirstBoot();
  //4.如果设备没有加密,操作它。管理A/B OTA dexopting。
  if (!mOnlyCore) {
      boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
              false);
      if (!disableOtaDexopt) {
          OtaDexoptService.main(mSystemContext, mPackageManagerService);
      }
  }
}

startBootstrapServices()首先启动Installer服务,也就是安装器,随后判断当前的设备是否处于加密 状态,如果是则只是解析核心应用,接着调用PackageManagerService的静态方法main来创建pms对象

SystemServer.startOtherServices()

 private void startOtherServices() {
	if (!mOnlyCore) {
		//5.如果设备没有加密,执行performDexOptUpgrade,完成dex优化;
  	mPackageManagerService.updatePackagesIfNeeded();
 	}
	//6.最终执行performFstrim,完成磁盘维护 
  mPackageManagerService.performFstrimIfNeeded();
 	//7.PKMS准备就绪 
 	mPackageManagerService.systemReady();
}
  1. 启动Installer服务
  2. 获取设备是否加密(手机设置密码),如果设备加密了,则只解析"core"应用
  3. 调用PKMS main方法初始化PackageManagerService,其中调用PackageManagerService() 构造函数创建了PKMS对象
  4. 如果设备没有加密,操作它。管理A/B OTA dexopting。
  5. 如果设备没有加密,执行performDexOptUpgrade,完成dex优化
  6. 最终执行performFstrim,完成磁盘维护
  7. PKMS准备就绪

PKMS.main()

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

main函数主要工作:

  1. 检查Package编译相关系统属性
  2. 调用PackageManagerService构造方法
  3. 启用部分应用服务于多用户场景
  4. 往ServiceManager中注册”package”和”package_native”。

PKMS初始化 (构造方法) 细节可忽略

PKMS构造方法,整体描述图:

PKMS的构造函数中由两个重要的锁(mInstallLock、mPackages)和5个阶段构成

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
    PackageManager.disableApplicationInfoCache();
    PackageManager.disablePackageInfoCache();

    // Avoid invalidation-thrashing by preventing cache invalidations from causing property
    // writes if the cache isn't enabled yet.  We re-enable writes later when we're
    // done initializing.
    PackageManager.corkPackageInfoCache();

    final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
            Trace.TRACE_TAG_PACKAGE_MANAGER);
    mPendingBroadcasts = new PendingPackageBroadcasts();

    mInjector = injector;
    mInjector.bootstrap(this);
    mLock = injector.getLock();
    mInstallLock = injector.getInstallLock();
    LockGuard.installLock(mLock, LockGuard.INDEX_PACKAGES);
  	//阶段一
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
            SystemClock.uptimeMillis());
  	//....
    // CHECKSTYLE:OFF IndentationCheck
    synchronized (mInstallLock) {
    // writer
    synchronized (mLock) {
      	//...
      	//阶段二
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                startTime);
				//...
      	//阶段三
      	EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                    SystemClock.uptimeMillis());
       	//...
				//阶段四
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                SystemClock.uptimeMillis());
        //...
				//阶段五
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                SystemClock.uptimeMillis());
    } // synchronized (mLock)
    } // synchronized (mInstallLock)
    // CHECKSTYLE:ON IndentationCheck
  	//...
  	//gc
    Runtime.getRuntime().gc();
}

两个重要的锁(mInstallLock、mLock)、mPackages

mInstallLockmLock:用来保护所有安装apk的访问权限,此操作通常涉及繁重的磁盘数据读写等操作,并且是单线程操作,故有时候会处理很慢, 此锁不会在已经持有mLock锁的情况下加锁,反之,在已经持有mInstallLock锁的情况下,立即获取mLock是安全的

mLock = injector.getLock();
mInstallLock = injector.getInstallLock();

mPackages:用来解析内存中所有apk的package信息及相关状态。

final ArrayMap<String, AndroidPackage> mPackages = new ArrayMap<>();

阶段一(BOOT_PROGRESS_PMS_START)

EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis());
mContext = injector.getContext();
mFactoryTest = factoryTest;// 一般为false,即非工厂生产模式
mOnlyCore = onlyCore;//标记是否只加载核心服务
//1.构造 DisplayMetrics ,保存分辨率等相关信息
mMetrics = new DisplayMetrics();
//2.创建Installer对象,与installd交互
mInstaller = injector.getInstaller();

// 将本地服务PackageManagerInternalImpl公开到LocalServices容器中
mPmInternal = new PackageManagerInternalImpl();
LocalServices.addService(PackageManagerInternal.class, mPmInternal);
//多用户管理服务
mUserManager = injector.getUserManagerService();
mComponentResolver = injector.getComponentResolver();
//3.获取权限管理服务mPermissionManager 和 mPermissionManagerService
mPermissionManager = injector.getPermissionManagerServiceInternal();//内部服务
mPermissionManagerService = (IPermissionManager) ServiceManager.getService("permissionmgr");//binder 注册的服务
//4.创建Settings对象
mSettings = injector.getSettings();

//添加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);
mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
//5.构造PackageDexOptimizer及DexManager类,处理dex优化
mPackageDexOptimizer = new PackageDexOptimizer(mInstaller, mInstallLock, mContext,
        "*dexopt*");
mDexManager =
        new DexManager(mContext, this, mPackageDexOptimizer, mInstaller, mInstallLock);
//ART虚拟机管理服务
mArtManagerService = new ArtManagerService(mContext, this, mInstaller, mInstallLock);
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());

mViewCompiler = new ViewCompiler(mInstallLock, mInstaller);
//获取默认分辨率
getDefaultDisplayMetrics(mInjector.getDisplayManager(), mMetrics);
//6.创建SystemConfig实例,获取系统配置信息,配置共享lib库
SystemConfig systemConfig = SystemConfig.getInstance();

//创建提供服务/数据的子组件。这里的顺序很重要,使用到了两个重要的同步锁:mInstallLock、 mPackages
// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
synchronized (mLock) {
  	//7.创建PackageManager的handler线程,循环处理外部安装相关消息。
    mHandlerThread = new ServiceThread(TAG,
            Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
    mHandlerThread.start();
  	//应用handler
    mHandler = new PackageHandler(mHandlerThread.getLooper());
  	//进程记录handler
    mProcessLoggingHandler = new ProcessLoggingHandler();
  	//Instant应用注册
    mInstantAppRegistry = new InstantAppRegistry(this);
		//共享lib库配置
    ArrayMap<String, SystemConfig.SharedLibraryEntry> libConfig
            = systemConfig.getSharedLibraries();
    final int builtInLibCount = libConfig.size();
    for (int i = 0; i < builtInLibCount; i++) {
        String name = libConfig.keyAt(i);
        SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);
        addBuiltInSharedLibraryLocked(entry.filename, name);
    }

    //添加依赖的依赖lib库
    long undefinedVersion = SharedLibraryInfo.VERSION_UNDEFINED;
    for (int i = 0; i < builtInLibCount; i++) {
        String name = libConfig.keyAt(i);
        SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);
        final int dependencyCount = entry.dependencies.length;
        for (int j = 0; j < dependencyCount; j++) {
            final SharedLibraryInfo dependency =
                getSharedLibraryInfoLPr(entry.dependencies[j], undefinedVersion);
            if (dependency != null) {
                getSharedLibraryInfoLPr(name, undefinedVersion).addDependency(dependency);
            }
        }
    }
		//读取安装相关SELinux策略
    SELinuxMMAC.readInstallPolicy();
		// 返回栈加载
    FallbackCategoryProvider.loadFallbacks();
		//读取并解析/data/system下的XML文件,下面详解
    mFirstBoot = !mSettings.readLPw(mInjector.getUserManagerInternal().getUsers(false));


    // 清理代码路径不存在的孤立软件包
    final int packageSettingCount = mSettings.mPackages.size();
    for (int i = packageSettingCount - 1; i >= 0; i--) {
        PackageSetting ps = mSettings.mPackages.valueAt(i);
        if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
                && mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
            mSettings.mPackages.removeAt(i);
            mSettings.enableSystemPackageLPw(ps.name);
        }
    }
		// 如果不是首次启动,也不是CORE应用,则拷贝预编译的DEX文件
    if (!mOnlyCore && mFirstBoot) {
        requestCopyPreoptedFiles();
    }
		...
先看Settings 构造函数
Settings(File dataDir, PermissionSettings permission,
        Object lock) {
    mLock = lock;
    mPermissions = permission;
    mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);

    mSystemDir = new File(dataDir, "system");//mSystemDir指向目录"/data/system"
    mSystemDir.mkdirs();//创建 "/data/system"
  	//设置权限
    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;

  	//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()会扫描下面5个文件

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

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

  • packages.xml:PKMS 扫描完目标文件夹后会创建该文件。当系统进行程序安装、卸载和更新等操作时,均 会更新该文件。该文件保存了系统中与 package 相关的一些信息。

  • packages.list:描述系统中存在的所有非系统自带的 APK 的信息。当这些程序有变动时,PKMS 就会更 新该文件。

  • packages-stopped.xml:从系统自带的设置程序中进入应用程序页面,然后在选择强制停止 (ForceStop)某个应用时,系统会将该应用的相关信息记录到此文件中。也就是该文件保存系统中被用户强 制停止的 Package 的信息。

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

Settings.readLPw()

扫码文件

boolean readLPw(@NonNull List<UserInfo> users) {
    FileInputStream str = null;

    if (str == null) {
        str = new FileInputStream(mSettingsFilename);
    }
    //解析"/data/system/packages.xml"
    XmlPullParser parser = Xml.newPullParser();
    parser.setInput(str, StandardCharsets.UTF_8.name());

    int type;
    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")) {
            mPermissions.readPermissions(parser);
        } else if (tagName.equals("permission-trees")) {
            mPermissions.readPermissionTrees(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);
        } //...
    }
    str.close();
		//...
    return true;
}

阶段二(BOOT_PROGRESS_PMS_SYSTEM_SCAN_START)

  1. 从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH;
  2. 对于旧版本升级的情况,将安装时获取权限变更为运行时申请权限;
  3. 扫描system/vendor/product/odm/oem等目录的priv-app、app、overlay包;
  4. 清除安装时临时文件以及其他不必要的信息。
synchronized (mInstallLock) {
  // writer
	synchronized (mLock) {
    long startTime = SystemClock.uptimeMillis();
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
            startTime);
		//从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);
    
    // 对于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;
    mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;

    // Save the names of pre-existing packages prior to scanning, so we can determine
    // which system packages are completely new due to an upgrade.
    // 在扫描之前保存预先存在的系统package的名称,这样我们可以决定哪些系统packages有更新的预期
    if (isDeviceUpgrading()) {
        mExistingPackages = new ArraySet<>(mSettings.mPackages.size());
        for (PackageSetting ps : mSettings.mPackages.values()) {
            mExistingPackages.add(ps.name);
        }
    }
		// 准备解析package的缓存
    mCacheDir = preparePackageParserCache();

    // 设置flag,而不在扫描安装时更改文件路径
    int scanFlags = SCAN_BOOTING | SCAN_INITIAL;


    final int systemParseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR;
    final int systemScanFlags = scanFlags | SCAN_AS_SYSTEM;

    //扫描以下路径:/vendor/overlay、/product/overlay、/product_services/overlay、/odm/overlay、/oem/ overlay、/system/framework/system/priv-app、/system/app、/vendor/priv- app、/vendor/app、/odm/priv-app、/odm/app、/oem/app、/oem/priv-app、/product/priv-app、/product/app、/product_services/priv- app、/product_services/app、/product_services/priv-app
    //......scanDirTracedLI方法扫描
    
    final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
    final List<String> stubSystemApps = new ArrayList<>();
    // 删掉不存在的package
    if (!mOnlyCore) {
        final Iterator<AndroidPackage> pkgIterator = mPackages.values().iterator();
        while (pkgIterator.hasNext()) {
            final AndroidPackage pkg = pkgIterator.next();
            if (pkg.isStub()) {
                stubSystemApps.add(pkg.getPackageName());
            }
        }

        final Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
        while (psit.hasNext()) {
            PackageSetting ps = psit.next();

            // 如果不是系统应用,则不被允许disable
            if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                continue;
            }

            // 如果应用被扫描,则不允许被擦除
            final AndroidPackage 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;
            }
						//...
        }
    }
  }
}

阶段三(BOOT_PROGRESS_PMS_DATA_SCAN_START)

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

if (!mOnlyCore) {
	EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,SystemClock.uptimeMillis());
	scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0,packageParser, executorService);

  // 移除通过OTA删除的更新系统应用程序的禁用package设置
	// 如果更新不再存在,则完全删除该应用。否则,撤消其系统权限
  for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) {
      final String packageName = possiblyDeletedUpdatedSystemApps.get(i);
      final AndroidPackage pkg = mPackages.get(packageName);
      final String msg;

      // remove from the disabled system list; do this first so any future
      // scans of this package are performed without this state
      mSettings.removeDisabledSystemPackageLPw(packageName);
			//...
  }

  // 确保期望在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);
					//...
          mSettings.enableSystemPackageLPw(packageName);
          try {
            	//扫描APK
              scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);
          } catch (PackageManagerException e) {
          }
      }
  }

  // 解压缩并安装任何存根系统应用程序。必须最后执行此操作以确保替换或禁用所有存根
  installSystemStubPackages(stubSystemApps, scanFlags);
	//...
}
// 获取storage manager包名
mStorageManagerPackage = getStorageManagerPackageName();

// 解决受保护的action过滤器。只允许setup wizard(开机向导)为这些action设置高优先级过滤器
mSetupWizardPackage = getSetupWizardPackageNameImpl();
// 更新客户端以确保持有正确的共享库路径
updateAllSharedLibrariesLocked(null, null, Collections.unmodifiableMap(mPackages));
// 读取并更新要保留的package的上次使用时间
mPackageUsage.read(mSettings.mPackages);
mCompilerStats.read();

阶段四(BOOT_PROGRESS_PMS_SCAN_END)

EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, SystemClock.uptimeMillis());

//sdk版本变更,更新权限;
// 如果自上次启动以来,平台SDK已改变,则需要重新授予应用程序权限以捕获出现的任何新权限
final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);
mPermissionManager.updateAllPermissions(
        StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated);
ver.sdkVersion = mSdkVersion;
// 如果这是第一次启动或来自Android M之前的版本的升级,并且它是正常启动,那需要在 所有已定义的用户中初始化默认的首选应用程序
if (!mOnlyCore && (mPromoteSystemApps || mFirstBoot)) {
    for (UserInfo user : mInjector.getUserManagerInternal().getUsers(true)) {
        mSettings.applyDefaultPreferredAppsLPw(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;
}

//OTA升级后首次启动,清除不必要的缓存数据;
//如果是在OTA之后首次启动,并且正常启动,那需要清除代码缓存目录,但不清除应用程序配置文件
if (mIsUpgrade && !mOnlyCore) {
    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,
                    FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
                            | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
                            | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
        }
    }
    ver.fingerprint = Build.FINGERPRINT;
}

//安装Android-Q前的非系统应用程序在Launcher中隐藏他们的图标
if (!mOnlyCore && mIsPreQUpgrade) {
    int size = mSettings.mPackages.size();
    for (int i = 0; i < size; i++) {
        final PackageSetting ps = mSettings.mPackages.valueAt(i);
        if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
            continue;
        }
        ps.disableComponentLPw(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,
                UserHandle.USER_SYSTEM);
    }
}

// 仅在权限或其它默认配置更新后清除
mExistingSystemPackages.clear();
mPromoteSystemApps = false;

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

//降级去读取
//更新package.xml
mSettings.writeLPr();
  1. sdk版本变更,更新权限;
  2. OTA升级后首次启动,清除不必要的缓存数据;
  3. 权限等默认项更新完后,清理相关数据;
  4. 更新package.xml

阶段五(BOOT_PROGRESS_PMS_READY)

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

		EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis());
		//...

    //PermissionController 主持 缺陷许可证的授予和角色管理,所以这是核心系统的一个关键部分。
    mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr();

    mSettings.setPermissionControllerVersion(
            getPackageInfo(mRequiredPermissionControllerPackage, 0,
                    UserHandle.USER_SYSTEM).getLongVersionCode());

    
    updateInstantAppInstallerLocked(null);

    // 阅读并更新dex文件的用法
		// 在PM init结束时执行此操作,以便所有程序包都已协调其数据目录
		// 此时知道了包的代码路径,因此可以验证磁盘文件并构建内部缓存
		// 使用文件预计很小,因此与其他活动(例如包扫描)相比,加载和验证它应该花费相当小的时间
    final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
    for (int userId : userIds) {
        userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList());
    }
    mDexManager.load(userPackages);
    if (mIsUpgrade) {
        FrameworkStatsLog.write(
                FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
                BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME,
                SystemClock.uptimeMillis() - startTime);
    }
} // synchronized (mLock)
} // synchronized (mInstallLock)
// CHECKSTYLE:ON IndentationCheck

// 打开应用之后,及时回收处理
Runtime.getRuntime().gc();
// 上面的初始扫描在持有mPackage锁的同时对installd进行了多次调用
mInstaller.setWarnIfHeld(mLock);

APK扫描

在PKMS初始化的阶段二会调用PKMS.scanDirTracedLI()扫描某个目录的apk文件

  • PKMS.scanDirTracedLI 首先加入了一些systtrace的日志追踪,然后调用scanDirLI()进行分析
    • PKMS.scanDirLI

PKMS.scanDirLI

使用了ParallelPackageParser的对象,ParallelPackageParser是一个队列,我们这 里手机所有系统的apk,然后从这些队列里面取出apk,再调用PackageParser 解析进行解析:

private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime,
        PackageParser2 packageParser, ExecutorService executorService) {
    final File[] files = scanDir.listFiles();
    if (ArrayUtils.isEmpty(files)) {
        return;
    }
		// parallelPackageParser是一个队列,收集系统 apk 文件,
		// 然后从这个队列里面一个个取出 apk ,调用 PackageParser 解析
    ParallelPackageParser parallelPackageParser =
            new ParallelPackageParser(packageParser, executorService);

    // Submit files for parsing in parallel
    int fileCount = 0;
    for (File file : files) {
      	// 是Apk文件,或者是目录
        final boolean isPackage = (isApkFile(file) || file.isDirectory())
                && !PackageInstallerService.isStageName(file.getName());
        if (!isPackage) {
            // Ignore entries which are not packages
            continue;
        }
      	// 把APK信息存入parallelPackageParser中的对象mQueue,PackageParser()函数 赋给了队列中的pkg成员
        parallelPackageParser.submit(file, parseFlags);
        fileCount++;
    }

    // 从parallelPackageParser中取出队列apk的信息
    for (; fileCount > 0; fileCount--) {
        ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
        Throwable throwable = parseResult.throwable;
        int errorCode = PackageManager.INSTALL_SUCCEEDED;

        if (throwable == null) {
            // TODO(toddke): move lower in the scan chain
            // Static shared libraries have synthetic package names
            if (parseResult.parsedPackage.isStaticSharedLibrary()) {
                renameStaticSharedLibraryPackage(parseResult.parsedPackage);
            }
            try {
              	//调用 scanPackageChildLI 方法扫描一个特定的 apk 文件
              	//该类的实例代表一个 APK 文件,所以它就是和 apk 文件对应的数据结构。
                addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,
                        currentTime, null);
            } //...
        } //...

				//如果是非系统 apk 并且解析失败
        if ((scanFlags & SCAN_AS_SYSTEM) == 0
                && errorCode != PackageManager.INSTALL_SUCCEEDED) {
            // 非系统 Package 扫描失败,删除文件
            removeCodePathLI(parseResult.scanFile);
        }
    }
}

ParallelPackageParser.submit

把扫描路径中的APK等内容,放入队列mQueue, 并把parsePackage() 赋给ParseResult,用于PKMS.scanDirLI()parallelPackageParser.take()的调用.

public void submit(File scanFile, int parseFlags) {
    mExecutorService.submit(() -> {
        ParseResult pr = new ParseResult();
        try {
            pr.scanFile = scanFile;
          	//把parsePackage()赋值ParseResult,用于后面的调用
            pr.parsedPackage = parsePackage(scanFile, parseFlags);
        } //...
        try {
          	//把扫描路径中的APK等内容,放入队列mQueue
            mQueue.put(pr);
        } //...
    });
}

PackageParser.parsePackage

通过 PackageParser.parsePackage 进行apk解析:

如果传入的packageFile是目录, 调用parseClusterPackage()解析

如果传入的packageFile是APK文件, 调用parseMonolithicPackage()解析

public Package parsePackage(File packageFile, int flags, boolean useCaches)
        throws PackageParserException {
    if (packageFile.isDirectory()) {
        return parseClusterPackage(packageFile, flags);
    } else {
        return parseMonolithicPackage(packageFile, flags);
    }
}
  • PackageParser.parseClusterPackage
    • PackageParser.parseBaseApk
  • PackageParser.parseMonolithicPackage
    • PackageParser.parseBaseApk

两个方法都会进入PackageParser.parseBaseApk 来解析APK

PackageParser.parseBaseApk

private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
        throws PackageParserException {
    final String apkPath = apkFile.getAbsolutePath();
    //...
    XmlResourceParser parser = null;
    try {
        final int cookie = assets.findCookieForPath(apkPath);
        if (cookie == 0) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
                    "Failed adding asset path: " + apkPath);
        }
      	// 获得一个 XML 资源解析对象,该对象解析的是 APK 中的 AndroidManifest.xml 文件。
        parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
        final Resources res = new Resources(assets, mMetrics, null);

        final String[] outError = new String[1];
      	//再调用重载函数parseBaseApk()最终到parseBaseApkCommon(),解析 AndroidManifest.xml 后得到一个Package对象
        final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);

        pkg.setVolumeUuid(volumeUuid);
        pkg.setApplicationVolumeUuid(volumeUuid);
        pkg.setBaseCodePath(apkPath);
        pkg.setSigningDetails(SigningDetails.UNKNOWN);

        return pkg;

    } //...
}

PackageParser.parseBaseApkCommon

parseBaseApk -----> parseBaseApkCommon , parseBaseApk省略了

PackageParser.parseBaseApkCommon 从AndroidManifest.xml中获取标签名,解析标签中的各个item的内容,存入Package对象中 例如:获取标签 "application"、"permission"、"package"、"manifest"

private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
        XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
        IOException {

    TypedArray sa = res.obtainAttributes(parser,
            com.android.internal.R.styleable.AndroidManifest);
		//拿到AndroidManifest.xml 中的sharedUserId, 一般情况下有“android.uid.system”等信息
    String str = sa.getNonConfigurationString(
            com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
    if (str != null && str.length() > 0) {
				//...
      	//赋值SharedUserId
        pkg.mSharedUserId = str.intern();
        pkg.mSharedUserLabel = sa.getResourceId(
                com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
    }
		
    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
				//从AndroidManifest.xml中获取标签名
        String tagName = parser.getName();

				//如果读到AndroidManifest.xml中的tag是"application",执行parseBaseApplication()进行解析
        if (tagName.equals(TAG_APPLICATION)) {
            if (foundApp) {
							//...
            }

            foundApp = true;
          	// 解析"application"的信息,赋值给pkg, 这里解析到的是"application" <application 包含了 四大组件
            if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
                return null;
            }
        } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
          	//进行"permission group"的解析
            if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
                return null;
            }
        } else if (tagName.equals(TAG_PERMISSION)) {
          	//进行"permission"的解析
            if (!parsePermission(pkg, res, parser, outError)) {
                return null;
            }
        } //...
    }
		//...
    return pkg;
}

上面解析AndroidManifest.xml,会得到 "application"、"overlay"、"permission"、"uses- permission" 等信息

我们下面就针对"application"进行展开分析一下,进入 PackageParser.parseBaseApplication()函数

PackageParser.parseBaseApplication

private boolean parseBaseApplication(Package owner, Resources res,
        XmlResourceParser parser, int flags, String[] outError)
    throws XmlPullParserException, IOException {
    //...
    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
            && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
  			//...
				// 获取"application"子标签的标签内容
        String tagName = parser.getName();
        if (tagName.equals("activity")) {//如果标签是"activity", 解析Activity的信息,把activity加入 Package对象
            Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
                    owner.baseHardwareAccelerated);
            if (a == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            hasActivityOrder |= (a.order != 0);
            owner.activities.add(a);

        } else if (tagName.equals("receiver")) {// 如果标签是"receiver",获取 receiver信息,加入Package对象
            Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
                    true, false);
            if (a == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            hasReceiverOrder |= (a.order != 0);
            owner.receivers.add(a);

        } else if (tagName.equals("service")) {// 如果标签是"service",获取service信 息,加入Package对象
            Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
            if (s == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            hasServiceOrder |= (s.order != 0);
            owner.services.add(s);

        } else if (tagName.equals("provider")) {// 如果标签是"provider",获取 provider信息,加入Package对象
            Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
            if (p == null) {
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }

            owner.providers.add(p);

        } //...
    }
		//...
    return true;
}

在 PackageParser 扫描完一个 APK 后,此时系统已经根据该 APK 中 AndroidManifest.xml,创建了一 个完整的 Package 对象

总结

第一步:扫描APK,解析AndroidManifest.xml文件,得到清单文件各个标签内容

第二步:解析清单文件到的信息由 Package 保存。从该类的成员变量可看出,和 Android 四大组件相关 的信息分别由 activites、receivers、providers、services 保存,由于一个 APK 可声明多个组件,因此 activites 和 receivers等均声明为 ArrayList

APK的安装

安装步骤一: 把Apk的信息通过IO流的形式写入到PackageInstaller.Session中

安装步骤二: 调用PackageInstaller.Session的commit方法, 把Apk的信息交给PKMS处理

安装步骤三: 进行Apk的Copy操作, 进行安装

安装的三步走,整体描述图:

PackageInstallerActivity.bindUi

点击一个apk后,会弹出安装界面,点击确定按钮后,会进入PackageInstallerActivitybindUi() 中 的mAlert点击事件, 弹出的安装界面底部显示的是一个diaglog,主要由bindUi构成,上面有 ”取消“ 和 ” 安装“ 两个按钮,点击安装后 调用startInstall()进行安装:

private void bindUi() {
    mAlert.setIcon(mAppSnippet.icon);
    mAlert.setTitle(mAppSnippet.label);
    mAlert.setView(R.layout.install_content_view);
    mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
            (ignored, ignored2) -> {
                if (mOk.isEnabled()) {
                    if (mSessionId != -1) {
                        mInstaller.setPermissionsResult(mSessionId, true);
                        finish();
                    } else {
                      	//进行APK安装
                        startInstall();
                    }
                }
            }, null);
    mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
            (ignored, ignored2) -> {
                // Cancel and finish
                setResult(RESULT_CANCELED);
                if (mSessionId != -1) {
                  	//如果mSessionId存在,执行setPermissionsResult()完成取消安装
                    mInstaller.setPermissionsResult(mSessionId, false);
                }
                finish();
            }, null);
    setupAlert();

    mOk = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
    mOk.setEnabled(false);
}

PackageInstallerActivity.startInstall

startInstall方法组装了一个Intent,并跳转到 InstallInstalling 这个Activity,并关闭掉当前的 PackageInstallerActivity。InstallInstalling主要用于向包管理器发送包的信息并处理包管理的回调:

private void startInstall() {
    Intent newIntent = new Intent();
  	//设置Intent中的class为 InstallInstalling,用来进行Activity跳转
    newIntent.setClass(this, InstallInstalling.class);
    //...
    startActivity(newIntent);
    finish();
}

InstallInstalling.onCreate

protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ApplicationInfo appInfo = getIntent()
            .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
    mPackageURI = getIntent().getData();

    if ("package".equals(mPackageURI.getScheme())) {
        //...
    } else {
      	//根据mPackageURI创建一个对应的File
        final File sourceFile = new File(mPackageURI.getPath());
      	//...
				//第一步.如果savedInstanceState不为null,获取此前保存的mSessionId和 mInstallId,其中mSessionId是安装包的会话id,mInstallId是等待的安装事件id
        if (savedInstanceState != null) {
            mSessionId = savedInstanceState.getInt(SESSION_ID);
            mInstallId = savedInstanceState.getInt(INSTALL_ID);

            // Reregister for result; might instantly call back if result was delivered while
            // activity was destroyed
            try {
              // 第二步.根据mInstallId向InstallEventReceiver注册一个观察者,launchFinishBasedOnResult会接收到安装事件的回调, 
              //无论安装成功或者失败都会关闭当前的Activity(InstallInstalling)。如果savedInstanceState为null,代码的逻辑也是类似的
                InstallEventReceiver.addObserver(this, mInstallId,
                        this::launchFinishBasedOnResult);
            } //...
        } else {
          	// 第三步.创建SessionParams,它用来代表安装会话的参数,组装params
            PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                    PackageInstaller.SessionParams.MODE_FULL_INSTALL);
            //...
						// 第四步.根据mPackageUri对包(APK)进行轻量级的解析,并将解析的参数赋值给 SessionParams
            File file = new File(mPackageURI.getPath());
            try {
                PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);
                params.setAppPackageName(pkg.packageName);
                params.setInstallLocation(pkg.installLocation);
                params.setSize(
                        PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
            } //...
            try {
              	// 第五步.向InstallEventReceiver注册一个观察者返回一个新的mInstallId, 
              	//其中InstallEventReceiver继承自BroadcastReceiver,用于接收安装事件并回调给EventResultPersister。
                mInstallId = InstallEventReceiver
                        .addObserver(this, EventResultPersister.GENERATE_NEW_ID,
                                this::launchFinishBasedOnResult);
            } //...
            try {
              	// 第六步.PackageInstaller的createSession方法内部会通过IPackageInstaller与PackageInstallerService进行进程间通信, 
  							//最终调用的是PackageInstallerService的createSession方法来创建并返回mSessionId
                mSessionId = getPackageManager().getPackageInstaller().createSession(params);
            } //...
        }

        mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);

        mSessionCallback = new InstallSessionCallback();
    }
}

以上第六步是重点 PackageInstaller 的 createSession()内部会通过IPackageInstaller与 PackageInstallerService进行进程间通信,最终调用的是PackageInstallerService的createSession方法 来创建并返回mSessionId

InstallInstalling.onResume

protected void onResume() {
    super.onResume();
    // This is the first onResume in a single life of the activity
    if (mInstallingTask == null) {
        PackageInstaller installer = getPackageManager().getPackageInstaller();
      	// 获取sessionInfo
        PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);
        if (sessionInfo != null && !sessionInfo.isActive()) {
          	// 创建内部类InstallingAsyncTask的对象,调用execute(),最终进入
onPostExecute()
            mInstallingTask = new InstallingAsyncTask();
            mInstallingTask.execute();
        } //...
    }
}

InstallInstalling.onResume方法中,调用onPostExecute()方法,将APK的信息通过IO流的形式写入 到PackageInstaller.Session中

InstallInstalling.InstallingAsyncTask 会在onPostExecute中 调用PackageInstaller.Session的commit方法,进行安装

PackageInstaller.Session.commit()最总会执行PackageInstallerSession.commit()

PackageInstallerSession.commit

public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
		//...
  	//调用markAsSealed
    if (!markAsSealed(statusReceiver, forTransfer)) {
        return;
    }
		//...
  	//向Handler发送一个类型为MSG_STREAM_VALIDATE_AND_COMMIT的消息
    dispatchStreamValidateAndCommit();
}

dispatchStreamValidateAndCommit() => mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget() => mHandlerCallback.handleMessage() => handleStreamValidateAndCommit()

PackageInstallerSession.handleStreamValidateAndCommit

private void handleStreamValidateAndCommit() {
    PackageManagerException unrecoverableFailure = null;
    // This will track whether the session and any children were validated and are ready to
    // progress to the next phase of install
  	//判断当前seesion和子seesion都已经准备就绪,准备进入下一步install 步骤
    boolean allSessionsReady = false;
    try {
        allSessionsReady = streamValidateAndCommit();
    } catch (PackageManagerException e) {
        unrecoverableFailure = e;
    }

    if (isMultiPackage()) {
        int childCount = mChildSessionIds.size();
        ArrayList<PackageInstallerSession> nonFailingSessions = new ArrayList<>(childCount);

        for (int i = childCount - 1; i >= 0; --i) {
            final int childSessionId = mChildSessionIds.keyAt(i);
            try {
                PackageInstallerSession session = mSessionProvider.getSession(childSessionId);
              	//遍历所有子session
                allSessionsReady &= session.streamValidateAndCommit();
                nonFailingSessions.add(session);
            } catch (PackageManagerException e) {
                allSessionsReady = false;
                if (unrecoverableFailure == null) {
                    unrecoverableFailure = e;
                }
            }
        }
				//...
    }

    if (!allSessionsReady) {
        return;
    }
		//进入下一步Install
    mHandler.obtainMessage(MSG_INSTALL).sendToTarget();
}

mHandlerCallback.handleMessage() => handleInstall() => installNonStagedLocked() => PackageManagerService.installStage()

PackageManagerService.installStage

发送 INIT_COPY 的Handler 消息

void installStage(ActiveInstallSession activeInstallSession) {
  	//创建了类型为INIT_COPY的消息
    final Message msg = mHandler.obtainMessage(INIT_COPY);
  	//创建InstallParams,它对应于包的安装数据
    final InstallParams params = new InstallParams(activeInstallSession);
    params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
    msg.obj = params;

    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage",
            System.identityHashCode(msg.obj));
    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
            System.identityHashCode(msg.obj));
		//将InstallParams通过消息发送出去。
    mHandler.sendMessage(msg);
}

void installStage(List<ActiveInstallSession> children)
        throws PackageManagerException {
    final Message msg = mHandler.obtainMessage(INIT_COPY);
    final MultiPackageInstallParams params =
            new MultiPackageInstallParams(UserHandle.ALL, children);
    params.setTraceMethod("installStageMultiPackage")
            .setTraceCookie(System.identityHashCode(params));
    msg.obj = params;

    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStageMultiPackage",
            System.identityHashCode(msg.obj));
    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
            System.identityHashCode(msg.obj));
    mHandler.sendMessage(msg);
}

mHandler在PKMS初始化阶段一里面创建的,所以后续流程进入PKMS.PackageHandler.handleMessage => PKMS.PackageHandler.doHandleMessage

PKMS.PackageHandler.doHandleMessage

void doHandleMessage(Message msg) {
    switch (msg.what) {
        case INIT_COPY: {
            HandlerParams params = (HandlerParams) msg.obj;
            if (params != null) {
              	//执行APK拷贝动作,这里会执行到 final void startCopy()
                params.startCopy();
            }
            break;
        } //...
    }
}

PKMS.HandlerParams.startCopy

final void startCopy() {
    handleStartCopy();
    handleReturnCode();
}

abstract void handleStartCopy();
abstract void handleReturnCode();

进入startCopy后调用两个抽象方法,PKMS.HandlerParams 的派生类分别是 PKMS.MultiPackageInstallParams (多个包安装)和 InstallParams (单个包安装)不过最终进入到 PKMS.InstallParams.handleStartCopy()PKMS.InstallParams.handleReturnCode()

PKMS.InstallParams.handleReturnCode

void handleReturnCode() {
    if (mVerificationCompleted
            && mIntegrityVerificationCompleted && mEnableRollbackCompleted) {
        //....
      	//拷贝APK
        if (mRet == PackageManager.INSTALL_SUCCEEDED) {
            mRet = mArgs.copyApk();
        }
        //...
      	//进入加载流程
      	processPendingInstall(mArgs, mRet);
    }
}

PKMS.InstallParams.copyApk() => PKMS.InstallParams.doCopyApk() => PackageManagerServiceUtils.copyPackage() => PackageManagerServiceUtils.copyFile() 通过文件流的操作,把APK拷贝到/data/app等目录

PKMS.processPendingInstall

文件拷贝到指定目录之后,接着就是安装解析APK

private void processPendingInstall(final InstallArgs args, final int currentStatus) {
    if (args.mMultiPackageInstallParams != null) {
      	//多个安装包需要打包,最后还是执行processInstallRequestsAsync()
        args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
    } else {
      	//设置安装参数
        PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
      	//创建一个新线程,处理安装参数,进行安装
        processInstallRequestsAsync(
                res.returnCode == PackageManager.INSTALL_SUCCEEDED,
                Collections.singletonList(new InstallRequest(args, res)));
    }
}

PKMS.processInstallRequestsAsync

mHandler.post 进行安装

private void processInstallRequestsAsync(boolean success,
        List<InstallRequest> installRequests) {
    mHandler.post(() -> {
        if (success) {
            for (InstallRequest request : installRequests) {
              	//1.如果之前安装失败,清除无用信息
                request.args.doPreInstall(request.installResult.returnCode);
            }
            synchronized (mInstallLock) {
              	//2. installPackagesTracedLI 是安装过程的核心方法,然后调用 installPackagesLI 进行安装。
                installPackagesTracedLI(installRequests);
            }
            for (InstallRequest request : installRequests) {
              	//3.如果之前安装失败,清除无用信息
                request.args.doPostInstall(
                        request.installResult.returnCode, request.installResult.uid);
            }
        }
        for (InstallRequest request : installRequests) {
            restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
                    new PostInstallData(request.args, request.installResult, null));
        }
    });
}

PKMS.installPackagesLI

private void installPackagesLI(List<InstallRequest> requests) {
		//...
    try {
        for (InstallRequest request : requests) {
            final PrepareResult prepareResult;
            try {
              	// 环节一.Prepare 准备:分析任何当前安装状态,分析包并对其进行初始验证。
                prepareResult =
                        preparePackageLI(request.args, request.installResult);
            } //....
            //...
            try {
              	// 环节二.Scan 扫描:考虑到prepare中收集的上下文,询问已分析的包。
                final ScanResult result = scanPackageTracedLI(
                        prepareResult.packageToScan, prepareResult.parseFlags,
                        prepareResult.scanFlags, System.currentTimeMillis(),
                        request.args.user, request.args.abiOverride);
                //...
            } //...
        }
      	// 环节三.Reconcile 调和:在彼此的上下文和当前系统状态中验证扫描的包,以确保安装成功。
        ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
                installResults,
                prepareResults,
                mSharedLibraries,
                Collections.unmodifiableMap(mPackages), versionInfos,
                lastStaticSharedLibSettings);
        synchronized (mLock) {
            Map<String, ReconciledPackage> reconciledPackages;
            try {
                reconciledPackages = reconcilePackagesLocked(
                        reconcileRequest, mSettings.mKeySetManagerService);
            } //...
            try {
                commitRequest = new CommitRequest(reconciledPackages,
                        mUserManager.getUserIds());
              	//环节四.Commit 提交:提交所有扫描的包并更新系统状态。这是安装流中唯一可以修改系统状态的 地方,必须在此阶段之前确定所有可预测的错误。
                commitPackagesLocked(commitRequest);
                success = true;
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
        }
      	// 环节五.完成APK的安装
        executePostCommitSteps(commitRequest);
    } //...
}

PKMS.executePostCommitSteps

安装APK,并为新的代码路径准备应用程序配置文件,并再次检查是否需要 dex优化

如果是直接安装新包,会为新的代码路径准备应用程序配置文件

如果是替换安装:其主要过程为更新设置,清除原有的某些APP数据,重新生成相关的app数据目录等 步骤,同时要区分系统应用替换和非系统应用替换。而安装新包:则直接更新设置,生成APP数据即 可。

private void executePostCommitSteps(CommitRequest commitRequest) {
    final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();
    for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
        //...
      	//准备AppData 进行安装
        prepareAppDataAfterInstallLIF(pkg);
      	//如果需要替换安装,则需要清楚原有的APP数据
        if (reconciledPkg.prepareResult.clearCodeCache) {
            clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
                    | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
        }
        //...
       	//为新的代码路径准备应用程序配置文件。这需要在调用dexopt之前完成,以便任何安装时配 置文件都可以用于优化。
        mArtManagerService.prepareAppProfiles(
                pkg,
                resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()),
                /* updateReferenceProfileContent= */ true);
				
        final boolean performDexopt =
                (!instantApp || Global.getInt(mContext.getContentResolver(),
                Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
                && !pkg.isDebuggable()
                && (!onIncremental);

        if (performDexopt) {
            //...
						//4)执行dex优化
            mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
                    null /* instructionSets */,
                    getOrCreateCompilerPackageStats(pkg),
                    mDexManager.getPackageUseInfoOrDefault(packageName),
                    dexoptOptions);
        }
        BackgroundDexOptService.notifyPackageChanged(packageName);
        notifyPackageChangeObserversOnUpdate(reconciledPkg);
    }
    NativeLibraryHelper.waitForNativeBinariesExtraction(incrementalStorages);
}

我们的安装流程会经过下面的跳转PKMS.prepareAppDataAfterInstallLIF() => PKMS.prepareAppDataLIF() => PKMS.prepareAppDataLeafLIF()

PKMS.prepareAppDataLeafLIF

private void prepareAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
    //...
    try {
      	//调用Installd守护进程的入口
        ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
                appId, seInfo, pkg.getTargetSdkVersion());
    } //...
  	//...
    prepareAppDataContentsLeafLIF(pkg, ps, userId, flags);
}

Installer.createAppData

收尾工作,安装完成后,更新设置,更新安装锁等:

public long createAppData(String uuid, String packageName, int userId, int flags, int appId,
        String seInfo, int targetSdkVersion) throws InstallerException {
    if (!checkBeforeRemote()) return -1;
    try {
      	// mInstalld 为IInstalld的对象,即通过Binder调用到 进程installd,最终调用 installd的createAppData()
      	// Installd 是由init 进程孵化出来的进程
        return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
                targetSdkVersion);
    } catch (Exception e) {
        throw InstallerException.from(e);
    }
}

总结

整个安装的原理就是将apk文件安装到对应的目录下。

PKMS权限扫描

PackageManagerService 需求对 /system/etc/permissions中的各种xml进行扫描,进行相应的权限存储,以便后面权限申请使用。

那么权限扫描又是在什么时候执行的呢?

我们知道在PackageManagerService的构造函数中,会获取SystemConfig的单例对象,SystemConfig 在实例化的时候就会进行权限扫描。

SystemConfig

public static SystemConfig getInstance() {
    synchronized (SystemConfig.class) {
        if (sInstance == null) {
            sInstance = new SystemConfig();
        }
        return sInstance;
    }
}

SystemConfig() {
    try {
        readAllPermissions();
    } //...
}

private void readAllPermissions() {
    // Read configuration from system
    readPermissions(Environment.buildPath(
            Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);

    // Read configuration from the old permissions dir
    readPermissions(Environment.buildPath(
            Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);

    // Vendors are only allowed to customize these
    int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
            | ALLOW_ASSOCIATIONS;
    if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
        // For backward compatibility
        vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
    }
    readPermissions(Environment.buildPath(
            Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);

    String vendorSkuProperty = SystemProperties.get(VENDOR_SKU_PROPERTY, "");
    if (!vendorSkuProperty.isEmpty()) {
        String vendorSkuDir = "sku_" + vendorSkuProperty;
        readPermissions(Environment.buildPath(
                Environment.getVendorDirectory(), "etc", "sysconfig", vendorSkuDir),
                vendorPermissionFlag);
        readPermissions(Environment.buildPath(
                Environment.getVendorDirectory(), "etc", "permissions", vendorSkuDir),
                vendorPermissionFlag);
    }

    // Allow ODM to customize system configs as much as Vendor, because /odm is another
    // vendor partition other than /vendor.
    int odmPermissionFlag = vendorPermissionFlag;
    readPermissions(Environment.buildPath(
            Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);

    String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
    if (!skuProperty.isEmpty()) {
        String skuDir = "sku_" + skuProperty;

        readPermissions(Environment.buildPath(
                Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
        readPermissions(Environment.buildPath(
                Environment.getOdmDirectory(), "etc", "permissions", skuDir),
                odmPermissionFlag);
    }
    //...
}

SystemConfig 是一个单例的设计模式,在创建SystemConfig的时候自动会通过调用SystemConfig.readAllPermissions()读取所有权限,SystemConfig.readPermissions()扫描指定文件。

SystemConfig.readPermissionsFromXml

SystemConfig.readPermissions() =>SystemConfig.readPermissionsFromXml()

解析xml的标签节点,存入mGlobalGids、mPermissions、mSystemPermissions等成员变量中.

private void readPermissionsFromXml(File permFile, int permissionFlag) {
    FileReader permReader = null;
    try {
        permReader = new FileReader(permFile);
    } //...

    final boolean lowRam = ActivityManager.isLowRamDeviceStatic();

    try {
        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(permReader);
        //...
        while (true) {
        	//...
            String name = parser.getName();
            switch (name) {
                case "group": { //解析 group 标签,前面介绍的 XML 文件中没有单独使用该标签的地方
                    if (allowAll) {
                        String gidStr = parser.getAttributeValue(null, "gid");
                        if (gidStr != null) {
                            int gid = android.os.Process.getGidForName(gidStr);
                            mGlobalGids = appendInt(mGlobalGids, gid);
                        }
                    } else {
                        logNotAllowedInPartition(name, permFile, parser);
                    }
                    XmlUtils.skipCurrentTag(parser);
                } break;
                case "permission": {//解析 permission 标签
                    if (allowPermissions) {
                        String perm = parser.getAttributeValue(null, "name");
                        if (perm == null) {
                            XmlUtils.skipCurrentTag(parser);
                            break;
                        }
                        perm = perm.intern();
                        readPermission(parser, perm);//调用 readPermission 处理,存入mPermissions
                    } else {
                        logNotAllowedInPartition(name, permFile, parser);
                        XmlUtils.skipCurrentTag(parser);
                    }
                } break;
            }
        }
    } //...
}

签名

静默安装,签名,须知内容:

// 如果想实现,静默安装,就需要设置好UID,只有设置这个UID后,才有安装的权限
// 但是这个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);

总结

Android系统启动时,会启动(应用程序管理服务器PKMS),此服务负责扫描系统中特定的目录,寻找里面的APK格式的文件,并对这些文件进行解析,然后得到应用程序相关信息,最后完成应用程序的安装

PKMS在安装应用过程中,会全面解析应用程序的AndroidManifest.xml文件,来得到Activity, Service, BroadcastReceiver, ContextProvider 等信息,在结合PKMS服务就可以在OS中正常的使用 应用程序了

在Android系统中,系统启动时由SystemServer启动PKMS服务,启动该服务后会执行应用程序的安装过程