• Android—PMS: installPackagesLI


    installPackagesLI

    1. private void installPackagesTracedLI(List requests) {
    2. try {
    3. Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
    4. installPackagesLI(requests);
    5. } finally {
    6. Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    7. }
    8. }
    9. private void installPackagesLI(List requests) {
    10. ....
    11. try {
    12. for (InstallRequest request : requests) {
    13. ....
    14. final PrepareResult prepareResult;
    15. try {
    16. //1.成功准备好的安装软件包所需的数据集。这包括将用于扫描和协调包的数据。
    17. prepareResult = preparePackageLI(request.args, request.installResult);
    18. }
    19. ....
    20. try {
    21. //2.根据prepare中收集的上下文查询解析后的包
    22. final List scanResults = scanPackageTracedLI(
    23. prepareResult.packageToScan, prepareResult.parseFlags,
    24. prepareResult.scanFlags, System.currentTimeMillis(),
    25. request.args.user);
    26. ....
    27. } catch (PackageManagerException e) {
    28. request.installResult.setError("Scanning Failed.", e);
    29. return;
    30. }
    31. }
    32. //3.协调,检查安装包状态确保安装成功
    33. ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
    34. installResults,
    35. prepareResults,
    36. mSharedLibraries,
    37. Collections.unmodifiableMap(mPackages), versionInfos,
    38. lastStaticSharedLibSettings);
    39. CommitRequest commitRequest = null;
    40. synchronized (mPackages) {
    41. Map reconciledPackages;
    42. try {
    43. Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
    44. reconciledPackages = reconcilePackagesLocked(
    45. reconcileRequest, mSettings.mKeySetManagerService);
    46. }
    47. ....
    48. }
    49. //4.提交
    50. executePostCommitSteps(commitRequest);
    51. }
    52. ....
    53. }

    1.准备 prepareResult = preparePackageLI(request.args, request.installResult);

    1. private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
    2. throws PrepareFailure {
    3. .....
    4. //解析包AndroidManifest.xml文件,签名信息等。
    5. PackageParser pp = new PackageParser();
    6. pp.setSeparateProcesses(mSeparateProcesses);
    7. pp.setDisplayMetrics(mMetrics);
    8. pp.setCallback(mPackageParserCallback);
    9. Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
    10. final PackageParser.Package pkg;
    11. try {
    12. pkg = pp.parsePackage(tmpPackageFile, parseFlags);
    13. DexMetadataHelper.validatePackageDexMetadata(pkg);
    14. } catch (PackageParserException e) {
    15. throw new PrepareFailure("Failed parse during installPackageLI", e);
    16. } finally {
    17. Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    18. }
    19. .....
    20. //冻结安装包
    21. final PackageFreezer freezer =
    22. freezePackageForInstall(pkgName, installFlags, "installPackageLI");
    23. boolean shouldCloseFreezerBeforeReturn = true;
    24. try {
    25. if (replace) {
    26. //更新包配置
    27. ...
    28. //如果是更新包还会判断是不是系统APP
    29. sysPkg = (isSystemApp(oldPackage));
    30. if (sysPkg) {
    31. ...
    32. }
    33. } else {
    34. //新包安装配置
    35. ...
    36. }
    37. ....
    38. //返回安装包的数据集
    39. return new PrepareResult(args.installReason, targetVolumeUuid, installerPackageName,
    40. args.user, replace, targetScanFlags, targetParseFlags, existingPackage, pkg,
    41. replace /* clearCodeCache */, sysPkg, renamedPackage, freezer,
    42. ps, disabledPs, childPackages);
    43. }

    preparePackageLI最主要的是

    pkg = pp.parsePackage(tmpPackageFile, parseFlags);

    \frameworks\base\core\java\android\content\pm\PackageParser.java

    1. public Package parsePackage(File packageFile, int flags) throws PackageParserException {
    2. return parsePackage(packageFile, flags, false /* useCaches */);
    3. }
    4. public Package parsePackage(File packageFile, int flags, boolean useCaches)
    5. throws PackageParserException {
    6. ....
    7. if (packageFile.isDirectory()) {
    8. parsed = parseClusterPackage(packageFile, flags);
    9. } else {
    10. //只有一个包走这里
    11. parsed = parseMonolithicPackage(packageFile, flags);
    12. }
    13. ....
    14. return parsed;
    15. }
    16. public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
    17. ....
    18. try {
    19. final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
    20. pkg.setCodePath(apkFile.getCanonicalPath());
    21. pkg.setUse32bitAbi(lite.use32bitAbi);
    22. return pkg;
    23. }
    24. ....
    25. }
    26. private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
    27. throws PackageParserException {
    28. try {
    29. ....
    30. parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
    31. final Resources res = new Resources(assets, mMetrics, null);
    32. final String[] outError = new String[1];
    33. final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
    34. if (pkg == null) {
    35. throw new PackageParserException(mParseError,
    36. apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
    37. }
    38. pkg.setVolumeUuid(volumeUuid);
    39. pkg.setApplicationVolumeUuid(volumeUuid);
    40. pkg.setBaseCodePath(apkPath);
    41. pkg.setSigningDetails(SigningDetails.UNKNOWN);
    42. return pkg;
    43. }
    44. ....
    45. }

    parseBaseApk是具体的解析方法,这里的ANDROID_MANIFEST_FILENAME就是manifest文件了

        public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";

    这里也去解析了资源文件等,最后都赋给了pkg这个Package对象,和Android四大组件相关的信息分别由activites、receivers、providers、services的list保存。

    2.扫描 final List scanResults = scanPackageTracedLI(prepareResult.packageToScan, prepareResult.parseFlags,prepareResult.scanFlags, System.currentTimeMillis(), request.args.user);

    根据prepare中收集的上下文查询已解析的包。

    扫描阶段会填充PackageSetting对象,PackageSetting生成之后会被记录到文件中,以后每次系统启动都会重新加载。

    3.协调 reconciledPackages = reconcilePackagesLocked(reconcileRequest, mSettings.mKeySetManagerService);

    验证安装包状态,以确保安装成功。协调新旧包,删除旧的package。

    4.提交  commitPackagesLocked(commitRequest);

    1. private void commitPackagesLocked(final CommitRequest request) {
    2. for (ReconciledPackage reconciledPkg : request.reconciledPackages.values()) {
    3. if (reconciledPkg.prepareResult.replace) {
    4. PackageParser.Package oldPackage = mPackages.get(packageName);
    5. // 1.设置安装和更新时间
    6. PackageSetting deletedPkgSetting = (PackageSetting) oldPackage.mExtras;
    7. setInstallAndUpdateTime(pkg, deletedPkgSetting.firstInstallTime,
    8. System.currentTimeMillis());
    9. //系统应用
    10. if (reconciledPkg.prepareResult.system) {
    11. // 2.系统应用-移除现有包,后面还会移除子包(已省略)
    12. removePackageLI(oldPackage, true);
    13. .....
    14. }
    15. } else {
    16. try {
    17. //3.非系统应用-删除包
    18. executeDeletePackageLIF(reconciledPkg.deletePackageAction, packageName,
    19. true, request.mAllUsers, true, pkg);
    20. }
    21. ....
    22. }
    23. }
    24. //4.提交包扫描并修改系统状态
    25. commitReconciledScanResultLocked(reconciledPkg);
    26. updateSettingsLI(pkg, reconciledPkg.installArgs.installerPackageName, request.mAllUsers,
    27. res, reconciledPkg.installArgs.user, reconciledPkg.installArgs.installReason);
    28. final PackageSetting ps = mSettings.mPackages.get(packageName);
    29. if (ps != null) {
    30. res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
    31. ps.setUpdateAvailable(false /*updateAvailable*/);
    32. }
    33. ....
    34. }
    35. }

    提交阶段第4步比较关键。前面3阶段填充了Package对象和PackageSetting对象数据,现在需要将这些数据提交。

    4.4 commitReconciledScanResultLocked(reconciledPkg);

    1. private void commitReconciledScanResultLocked(@NonNull ReconciledPackage reconciledPkg) {
    2. ....
    3. commitPackageSettings(pkg, oldPkg, pkgSetting, scanFlags,
    4. (parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/, reconciledPkg);
    5. ....
    6. }
    7. //将扫描包添加到系统中。当这个方法完成时,包将会可用于查询,解决等…
    8. private void commitPackageSettings(PackageParser.Package pkg,
    9. @Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting,
    10. final @ScanFlags int scanFlags, boolean chatty, ReconciledPackage reconciledPkg) {
    11. ....
    12. synchronized (mPackages) {
    13. //添加新的设置到mSettings
    14. mSettings.insertPackageSettingLPw(pkgSetting, pkg);
    15. //将新设置添加到mPackages中
    16. mPackages.put(pkg.applicationInfo.packageName, pkg);
    17. //将包的键集添加到全局KeySetManagerService
    18. KeySetManagerService ksms = mSettings.mKeySetManagerService;
    19. ksms.addScannedPackageLPw(pkg);
    20. mComponentResolver.addAllComponents(pkg, chatty);
    21. .....
    22. }
    23. }

    在此之前,四大组件信息等安装包信息都属于Package的私有财产,现在需要把它们登记注册到PKMS内部的财产管理对象中。这样,PKMS就可对外提供统一的组件信息,而不必拘泥于具体的Package。

    5.善后工作executePostCommitSteps(commitRequest);

    1. private void executePostCommitSteps(CommitRequest commitRequest) {
    2. for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
    3. .....
    4. //1.安装并准备/data/data下的文件夹
    5. prepareAppDataAfterInstallLIF(pkg);
    6. ....
    7. //2.dex2oat操作,用来将apk中的dex文件转换为oat文件
    8. final boolean performDexopt =
    9. (!instantApp || Global.getInt(mContext.getContentResolver(),
    10. Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
    11. && ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0);
    12. if (performDexopt) {
    13. // Compile the layout resources.
    14. if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) {
    15. Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "compileLayouts");
    16. mViewCompiler.compileLayouts(pkg);
    17. Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    18. }
    19. Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
    20. // Do not run PackageDexOptimizer through the local performDexOpt
    21. // method because `pkg` may not be in `mPackages` yet.
    22. //
    23. // Also, don't fail application installs if the dexopt step fails.
    24. DexoptOptions dexoptOptions = new DexoptOptions(packageName,
    25. REASON_INSTALL,
    26. DexoptOptions.DEXOPT_BOOT_COMPLETE
    27. | DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE);
    28. mPackageDexOptimizer.performDexOpt(pkg,
    29. null /* instructionSets */,
    30. getOrCreateCompilerPackageStats(pkg),
    31. mDexManager.getPackageUseInfoOrDefault(packageName),
    32. dexoptOptions);
    33. Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    34. }
    35. ...
    36. }
    37. }

    prepareAppDataAfterInstallLIF(pkg);

    1. private void prepareAppDataAfterInstallLIF(PackageParser.Package pkg) {
    2. ....
    3. final UserManagerService um = sUserManager;
    4. UserManagerInternal umInternal = getUserManagerInternal();
    5. for (UserInfo user : um.getUsers(false /* excludeDying */)) {
    6. final int flags;
    7. if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
    8. flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
    9. } else if (umInternal.isUserRunning(user.id)) {
    10. flags = StorageManager.FLAG_STORAGE_DE;
    11. } else {
    12. continue;
    13. }
    14. if (ps.getInstalled(user.id)) {
    15. // TODO: when user data is locked, mark that we're still dirty
    16. prepareAppDataLIF(pkg, user.id, flags);
    17. }
    18. }
    19. }
    20. private void prepareAppDataLIF(PackageParser.Package pkg, int userId, int flags) {
    21. if (pkg == null) {
    22. Slog.wtf(TAG, "Package was null!", new Throwable());
    23. return;
    24. }
    25. prepareAppDataLeafLIF(pkg, userId, flags);
    26. ....
    27. }
    28. private void prepareAppDataAndMigrateLIF(PackageParser.Package pkg, int userId, int flags,
    29. boolean maybeMigrateAppData) {
    30. prepareAppDataLIF(pkg, userId, flags);
    31. if (maybeMigrateAppData && maybeMigrateAppDataLIF(pkg, userId)) {
    32. // We may have just shuffled around app data directories, so
    33. // prepare them one more time
    34. prepareAppDataLIF(pkg, userId, flags);
    35. }
    36. }
    37. private void prepareAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
    38. ...
    39. try {
    40. ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
    41. appId, seInfo, app.targetSdkVersion);
    42. }
    43. ...
    44. }

    跟到最后发现是交给mInstaller去做的,这里的mInstaller是个Binder代理对象,具体实现在\frameworks\native\cmds\installd\InstalldNativeService.cpp

    1. std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
    2. std::string data(create_data_path(volume_uuid));
    3. if (volume_uuid == nullptr && userid == 0) {
    4. std::string legacy = StringPrintf("%s/data", data.c_str());
    5. struct stat sb;
    6. if (lstat(legacy.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) {
    7. /* /data/data is dir, return /data/data for legacy system */
    8. return legacy;
    9. }
    10. }
    11. return StringPrintf("%s/user/%u", data.c_str(), userid);
    12. }

    这里返回data/data 

    第5步executePostCommitSteps就是去建立用户数据文件夹,data/data;使用 dex2oat 把App编译成 oat 文件,并保存在 dalvik-cache 目录里;发送ACTION_PACKAGE_ADDED、ACTION_PACKAGE_REPLACED广播等等操作。

  • 相关阅读:
    缓冲区溢出保护
    ABS10-ASEMI开关电源整流桥ABS10
    用pyinstaller打包LGBM模型为ELF/EXE可执行文件
    浮点数精度、域宽、填充
    2023最新外贸建站:WordPress搭建外贸独立站零基础小白保姆级教程
    2018年计网408
    【iOS】音频中断
    写在前面(ShenYu)
    JSP快速入门
    Unity Shader - sahder变体剔除
  • 原文地址:https://blog.csdn.net/weixin_41939525/article/details/127791998