2.3 packages.xml中的privateFlags字段

前文提到,packages.xml 这个文件位于ROM设备的 data/system,读取需要root权限。记录系统中所有安装的应用信息,包含基本信息、签名和权限等。 与2.2类似,下面来分析确认一下privateFlags字段与LOCAL_PRIVILEGED_MODULE的关系。
PackageManagerService在install和scan应用的过程中,有些属性会持久化,以便下次使用。frameworks/base/services/core/Java/com/Android/server/pm/下有关的几个setting类:

abstract class SettingBase/*** Settings base class for pending and resolved classes.*/
abstract class PackageSettingBase extends SettingBase/*** Settings data for a particular package we know about.*/
final class PackageSetting extends PackageSettingBase

以上三个类是设置的item,即对应每个app的设置项。在PMS中,维护有成员变量

    final Settings mSettings;

Settings这个类同样位于frameworks/base/services/core/Java/com/Android/server/pm/,它包含一个PackageSetting的Map:

/*** Holds information about dynamic settings.*/
final class Settings {......final ArrayMap<String, PackageSetting> mPackages =new ArrayMap<String, PackageSetting>();......
}

Settings的构造方法:

    Settings(Object lock) {this(Environment.getDataDirectory(), lock);}Settings(File dataDir, Object lock) {mLock = lock;mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);mSystemDir = new File(dataDir, "system");mSystemDir.mkdirs();FileUtils.setPermissions(mSystemDir.toString(),FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH|FileUtils.S_IXOTH,-1, -1);mSettingsFilename = new File(mSystemDir, "packages.xml");mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");mPackageListFilename = new File(mSystemDir, "packages.list");FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);// Deprecated: Needed for migrationmStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");}

PMS中的mSettings是在PMS构造方法中被创建对象:

mSettings = new Settings(mPackages);

这次调用传递的参数是mPackages,这个在LOCAL_PRIVILEGED_MODULE 详解(3) 中有所介绍,是用以缓存PMS扫描app得到的信息。从Settings构造方法看到,这个参数是一个锁,用以同步Settings的一些逻辑,主要是锁一段写文件的逻辑Settings.RuntimePermissionPersistence.writePermissionsForUserAsyncLPr(int userId)。
在Settings的构造方法中,创建data/system目录,并且拿到了该目录下五个设置文件的引用。Settings负责app信息的持久化。
对于PMS而言,mPackages负责内存中缓存app信息,mSettings负责持久化app信息,堪称左膀右臂。
接下来继续关注我们的点,看看packages.xml中的privateFlags字段是怎么样写入的,与LOCAL_PRIVILEGED_MODULE之间的关系。

Settings的持久化(写入文件)逻辑:
主写入方法:

void writeLPr()

作用是对写入的文件做一些检查,并且处理写入的循环逻辑,调用下面这些具体的写入方法完成写入:

void writePackageListLPr(int creatingUserId)
void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg)
void writePackageLPr(XmlSerializer serializer, final PackageSetting pkg)
void writeSigningKeySetLPr(XmlSerializer serializer, PackageKeySetData data)
void writeUpgradeKeySetsLPr(XmlSerializer serializer, PackageKeySetData data)
void writeKeySetAliasesLPr(XmlSerializer serializer, PackageKeySetData data)
void writePermissionLPr(XmlSerializer serializer, BasePermission bp)

其中,writePackageLPr()有对于packages.xml中的privateFlags字段的写入逻辑:

void writePackageLPr(XmlSerializer serializer, final PackageSetting pkg)throws java.io.IOException {serializer.startTag(null, "package");serializer.attribute(null, ATTR_NAME, pkg.name);if (pkg.realName != null) {serializer.attribute(null, "realName", pkg.realName);}serializer.attribute(null, "codePath", pkg.codePathString);if (!pkg.resourcePathString.equals(pkg.codePathString)) {serializer.attribute(null, "resourcePath", pkg.resourcePathString);}if (pkg.legacyNativeLibraryPathString != null) {serializer.attribute(null, "nativeLibraryPath", pkg.legacyNativeLibraryPathString);}if (pkg.primaryCpuAbiString != null) {serializer.attribute(null, "primaryCpuAbi", pkg.primaryCpuAbiString);}if (pkg.secondaryCpuAbiString != null) {serializer.attribute(null, "secondaryCpuAbi", pkg.secondaryCpuAbiString);}if (pkg.cpuAbiOverrideString != null) {serializer.attribute(null, "cpuAbiOverride", pkg.cpuAbiOverrideString);}serializer.attribute(null, "publicFlags", Integer.toString(pkg.pkgFlags));serializer.attribute(null, "privateFlags", Integer.toString(pkg.pkgPrivateFlags));serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));serializer.attribute(null, "version", String.valueOf(pkg.versionCode));if (pkg.sharedUser == null) {serializer.attribute(null, "userId", Integer.toString(pkg.appId));} else {serializer.attribute(null, "sharedUserId", Integer.toString(pkg.appId));}if (pkg.uidError) {serializer.attribute(null, "uidError", "true");}if (pkg.installStatus == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {serializer.attribute(null, "installStatus", "false");}if (pkg.installerPackageName != null) {serializer.attribute(null, "installer", pkg.installerPackageName);}if (pkg.volumeUuid != null) {serializer.attribute(null, "volumeUuid", pkg.volumeUuid);}pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);writePermissionsLPr(serializer, pkg.getPermissionsState().getInstallPermissionStates());writeSigningKeySetLPr(serializer, pkg.keySetData);writeUpgradeKeySetsLPr(serializer, pkg.keySetData);writeKeySetAliasesLPr(serializer, pkg.keySetData);writeDomainVerificationsLPr(serializer, pkg.verificationInfo);serializer.endTag(null, "package");}

可见,privateFlags字段是一个非可选字段,对于任意一个app,都存在。

继续向回追溯,看writeLPr()对于writePackageLPr()的调用:

    void writeLPr() {......for (final PackageSetting pkg : mPackages.values()) {writePackageLPr(serializer, pkg);}......
}

写入的值源自mPackages。

接着看mPackages中,对应的privateFlags字段是怎么维护的。在私有方法getPackageLPw()中维护,取决于传入的参数int pkgPrivateFlags。需要注意的是,仅仅取决于的一位ApplicationInfo.PRIVATE_FLAG_PRIVILEGED(即1<<3):

    private PackageSetting getPackageLPw(String name, PackageSetting origPackage,String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,String legacyNativeLibraryPathString, String primaryCpuAbiString,String secondaryCpuAbiString, int vc, int pkgFlags, int pkgPrivateFlags,UserHandle installUser, boolean add, boolean allowInstall) {PackageSetting p = mPackages.get(name);......if (p.sharedUser != sharedUser) {PackageManagerService.reportSettingsProblem(Log.WARN,"Package " + name + " shared user changed from "+ (p.sharedUser != null ? p.sharedUser.name : "<nothing>")+ " to "+ (sharedUser != null ? sharedUser.name : "<nothing>")+ "; replacing with new");p = null;} else {// If what we are scanning is a system (and possibly privileged) package,// then make it so, regardless of whether it was previously installed only// in the data partition.p.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;p.pkgPrivateFlags |= pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;}}......return p;}

上一级的调用,包内方法getPackageLPw():

    PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi,int pkgFlags, int pkgPrivateFlags, UserHandle user, boolean add) {final String name = pkg.packageName;PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, secondaryCpuAbi,pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user, add, true /* allowInstall */);return p;}

在PMS的scanPackageDirtyLI()有对于包内方法getPackageLPw()的调用。关于PMS的scanPackageDirtyLI()在上一篇中有所介绍 LOCAL_PRIVILEGED_MODULE 详解(3) 。看一下相关代码:

            // Just create the setting, don't add it yet. For already existing packages// the PkgSetting exists already and doesn't have to be created.pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,pkg.applicationInfo.primaryCpuAbi,pkg.applicationInfo.secondaryCpuAbi,pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags,user, false);

其中,传入的参数pkg.applicationInfo.privateFlags,正好接续在上一篇 LOCAL_PRIVILEGED_MODULE 详解(3) 中的分析:

        if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;}

这个关键的|=逻辑,正是对应使用LOCAL_PRIVILEGED_MODULE设置为true编译的app。

总结:
(1)使用LOCAL_PRIVILEGED_MODULE设置为true编译的app,即ROM中的system/priv-app/下的app,packages.xml中的privateFlags字段为8。这个数值由ApplicationInfo.PRIVATE_FLAG_PRIVILEGED(即1<<3)而来。
(2)除此之外,ROM中的system/framework/framework-res.apk,也具有上述特征。

LOCAL_PRIVILEGED_MODULE 详解(1)
LOCAL_PRIVILEGED_MODULE 详解(2)
LOCAL_PRIVILEGED_MODULE 详解(3)
LOCAL_PRIVILEGED_MODULE 详解(4)
LOCAL_PRIVILEGED_MODULE 详解(5)

LOCAL_PRIVILEGED_MODULE 详解(4)相关推荐

  1. LOCAL_PRIVILEGED_MODULE 详解(1)

    LOCAL_PRIVILEGED_MODULE 是Android ROM编译时的一个变量,其与编译.安装.权限管理等几个方面都有关系.本文整理一下与LOCAL_PRIVILEGED_MODULE有关的 ...

  2. LOCAL_PRIVILEGED_MODULE 详解(2)

    2.安装时作用 2.1 准备知识 在介绍LOCAL_PRIVILEGED_MODULE在安装时的作用之前,先介绍几个关键的准备知识: (1)packages.xml 这个文件位于ROM设备的 data ...

  3. 从命令行到IDE,版本管理工具Git详解(远程仓库创建+命令行讲解+IDEA集成使用)

    首先,Git已经并不只是GitHub,而是所有基于Git的平台,只要在你的电脑上面下载了Git,你就可以通过Git去管理"基于Git的平台"上的代码,常用的平台有GitHub.Gi ...

  4. JVM年轻代,老年代,永久代详解​​​​​​​

    秉承不重复造轮子的原则,查看印象笔记分享连接↓↓↓↓ 传送门:JVM年轻代,老年代,永久代详解 速读摘要 最近被问到了这个问题,解释的不是很清晰,有一些概念略微模糊,在此进行整理和记录,分享给大家.在 ...

  5. docker常用命令详解

    docker常用命令详解 本文只记录docker命令在大部分情境下的使用,如果想了解每一个选项的细节,请参考官方文档,这里只作为自己以后的备忘记录下来. 根据自己的理解,总的来说分为以下几种: Doc ...

  6. 通俗易懂word2vec详解词嵌入-深度学习

    https://blog.csdn.net/just_so_so_fnc/article/details/103304995 skip-gram 原理没看完 https://blog.csdn.net ...

  7. 深度学习优化函数详解(5)-- Nesterov accelerated gradient (NAG) 优化算法

    深度学习优化函数详解系列目录 深度学习优化函数详解(0)– 线性回归问题 深度学习优化函数详解(1)– Gradient Descent 梯度下降法 深度学习优化函数详解(2)– SGD 随机梯度下降 ...

  8. CUDA之nvidia-smi命令详解---gpu

    nvidia-smi是用来查看GPU使用情况的.我常用这个命令判断哪几块GPU空闲,但是最近的GPU使用状态让我很困惑,于是把nvidia-smi命令显示的GPU使用表中各个内容的具体含义解释一下. ...

  9. Bert代码详解(一)重点详细

    这是bert的pytorch版本(与tensorflow一样的,这个更简单些,这个看懂了,tf也能看懂),地址:https://github.com/huggingface/pytorch-pretr ...

最新文章

  1. anaconda创建一个虚拟环境
  2. 0/0型极限等于多少_求极限时是否可以进行代入?
  3. 10句“金玉良言”,助你面试成功!
  4. 10 个免费的服务器监控工具推荐
  5. 妙趣横生算法 3:寻找相同元素的指针
  6. 三、gridView增删改查
  7. java常见的gc回收器_一篇文章让你了解GC垃圾回收器
  8. rocketmq 消息 自定义_rocketmq中的自定义消息头
  9. 在Oracle中删除用户时提示:ORACLE无法删除当前连接用户
  10. python-获取满足条件的索引值np.where
  11. RuntimeError: Legacy autograd function with non-static forward method is deprecated. Please use new-
  12. 【数据挖掘算法与应用】——数据挖掘导论
  13. 蚂蚁课堂视频笔记思维导图-3期 七、互联网高并发解决方案
  14. 一款好看+极简到不行的HTML5音乐播放器-skPlayer
  15. wps演示怎么提高列表级别_wps文字如何设置标题级别
  16. 微软.NET平台OA办公解决方案
  17. 李阳音标速成MP3文本
  18. 手把手教用matlab做无人驾驶(二十三)--LMPC
  19. HIbernate关联映射小案例(CRUD)
  20. 基于Unity的2D像素风闯关游戏Demo——SunnyLand

热门文章

  1. php smart str,致命错误:ext/standard/php_smart_str.h:没有那个文件或目录
  2. STM32跑MicroPython的链接脚本分析
  3. 勿以身贵而贱人,勿以独见而违众,勿以辩说为必然
  4. l开头的英文车标是什么车_l开头的车标一串英文(车标里面带个大写L,看外观是辆跑车,是什么牌子啊,不是雷克萨斯?)...
  5. 让星空极速彻底下岗 熊坛高手放出破解秘技
  6. 软件行业中的鱼骨图运用
  7. js13位时间戳转换,10位时间戳转换
  8. 光流估计(三) PWC-Net 模型介绍
  9. optimization method (理论)
  10. fp函数式编程_全面了解函数式编程(FP)