Android-6.0之PMS解析下篇

本文转载于:http://www.iloveandroid.net/2016/06/20/Android_PackageManagerService-2/

前面介绍了PMS启动的时候,扫描系统app目录时的代码,现在分析PMS启动时,如何扫描用户安装的app。


继续PMS 构造方法

1
2
3
//调用installd执行/system/etc/updatecmds下命令脚本
if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
          mInstaller.moveFiles();

接下来一段代码是处理有升级包的系统应用,也就是执行过OTA升级后,第一次启动时,需要关心的逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// Prune any system packages that no longer exist.
           final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
           if (!mOnlyCore) {
               Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
               while (psit.hasNext()) {
                   PackageSetting ps = psit.next();

                   /*
 * If this is not a system app, it can't be a
 * disable system app.
 */
                   if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                       continue;//忽略普通应用
                   }

                   /*
 * If the package is scanned, it's not erased.
 */
                   final PackageParser.Package scannedPkg = mPackages.get(ps.name);
                   if (scannedPkg != null) {
                       /*
 * If the system app is both scanned and in the
 * disabled packages list, then it must have been
 * added via OTA. Remove it from the currently
 * scanned package so the previously user-installed
 * application can be scanned.
 */
                        // packages.xml中<updated-package>修饰的package会被记录到mSettings中的disable列表中去
                        // 这说明扫描的系统app是带有升级包的
                       if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                           logCriticalInfo(Log.WARN, "Expecting better updated system app for "
                                   + ps.name + "; removing system app. Last known codePath="
                                   + ps.codePathString + ", installStatus=" + ps.installStatus
                                   + ", versionCode=" + ps.versionCode + "; scanned versionCode="
                                   + scannedPkg.mVersionCode);
                           removePackageLI(ps, true);//将其从mPackages中移除
                           mExpectingBetter.put(ps.name, ps.codePath);// 将其添加到mExpectingBetter,后续处理
                       }

                       continue;
                   }

                  // 运行到这里说明packages.xml中记录的app,这次没有扫描到。
                   if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
                     // 如果这个app在packages.xml也不属于<updated-package>
                     // 意味着这个应用是残留在packages.xml中的,可能还会剩下沙箱数据,因此也要删掉
                       psit.remove();
                       logCriticalInfo(Log.WARN, "System package " + ps.name
                               + " no longer exists; wiping its data");
                       removeDataDirsLI(null, ps.name);
                   } else {
                     // 如果这个app在packages.xml属于<updated-package>
                     // 将其加入possiblyDeletedUpdatedSystemApps
                       final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
                       if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
                           possiblyDeletedUpdatedSystemApps.add(ps.name);
                       }
                   }
               }
           }

进行一些清理工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//扫描并删除未成功安装的apk包(针对第三方app)
 //look for any incomplete package installations
ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
//clean up list
for(int i = 0; i < deletePkgsList.size(); i++) {
    //clean up here
    cleanupInstallFailedPackage(deletePkgsList.get(i));
}

// 删除临时文件
//delete tmp files
deleteTempPackageFiles();

// 把从mSettings中没有关联任何应用的SharedUserSetting对象删掉
mSettings.pruneSharedUsersLPw();

现在开始扫描用户安装的app了

1
2
3
4
5
6
7

EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
        SystemClock.uptimeMillis());
scanDirLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);

scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
        scanFlags | SCAN_REQUIRE_KNOWN, 0);

同样是调用scanDirLI方法去扫描apk目录。这里要扫描的这两个文件是:

1
/data/app

/data/app-priv

逻辑和上一篇分析的是一样的,只不过传入的扫描参数发生了变化: SCAN_REQUIRE_KNOWN。

接下来是处理possiblyDeletedUpdatedSystemApps。

它里面存储的是在packages.xml中被标记为,但是前面又没有扫描到的其apk文件的app。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
 * Remove disable package settings for any updated system
 * apps that were removed via an OTA. If they're not a
 * previously-updated app, remove them completely.
 * Otherwise, just revoke their system-level permissions.
 */
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
    // 在扫描了用户app目录之后,再次尝试查找是否有这些app
    PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
    mSettings.removeDisabledSystemPackageLPw(deletedAppName);

    String msg;
    // 依旧没有,那么就删除他们的数据目录
    if (deletedPkg == null) {
        msg = "Updated system package " + deletedAppName
                + " no longer exists; wiping its data";
        removeDataDirsLI(null, deletedAppName);
    } else {
      // 找到了,说明是在用户app目录中找到的,那么移除系统权限
        msg = "Updated system app + " + deletedAppName
                + " no longer present; removing system privileges for "
                + deletedAppName;

        deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;

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

存放到mExpectingBetter是那些带有升级包的系统应用。前面已经把他们从PMS的mPackages中移除并放到了mExpectingBetter中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
    /**
 * Make sure all system apps that we expected to appear on
 * the userdata partition actually showed up. If they never
 * appeared, crawl back and revive the system version.
 */
    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");

            //确保是在
            ///system/app-priv
            ///system/app
            ///vendor/app
            ///oem/app
            // 这四个目录中。
            final int reparseFlags;
            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的mPackages中
            mSettings.enableSystemPackageLPw(packageName);

            /// 重新扫描这些文件
            try {
                scanPackageLI(scanFile, reparseFlags, scanFlags, 0, null);
            } catch (PackageManagerException e) {
                Slog.e(TAG, "Failed to parse original system package: "
                        + e.getMessage());
            }
        }
    }
}
  // 清除mExpectingBetter
  mExpectingBetter.clear();

接下来的代码作用是更新所有应用的动态库路径,如果是OTA升级导致前后SDK版本不一致,还要进行权限重新检查,并且删除app oat cache目录。

更新数据库版本,调用mSettings.writeLPr()将信息写入packages.xml中。

最后创建mInstallerService对象:

1
mInstallerService = new PackageInstallerService(context, this);

PMS构造方法的执行过程就是先读取保存在packages.xml中记录的系统关机前记录所有安装的app信息,保存在mSettings中的mPackages中。
然后扫描指定的若干目录中的app,并把信息记录在PMS的mPackages中。最后对两者进行对比,看是否能发现有升级的app,然后进行相关处理,最后在写入packages.xml中。

    原文作者:疾风-Bevis
    原文地址: https://blog.csdn.net/LOVE000520/article/details/70460799
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞