/data/system/packages
1、/data/system/packages.list: 记录安装app的信息
com.android.cts.priv.ctsshim 10028 0 /data/user/0/com.android.cts.priv.ctsshim default:privapp:targetSdkVersion=24 none
com.qualcomm.qti.qms.service.telemetry 10096 0 /data/user/0/com.qualcomm.qti.qms.service.telemetry platform:targetSdkVersion=28
3003
com.google.android.youtube 10079 0 /data/user/0/com.google.android.youtube default:targetSdkVersion=28 3003
这里用空格符分了6列,分别包含了6个app相关的信息:
第一列是app的包名,也就是AndroidManifest.xml文件中的package=”xxx.xxx.xxx”设置的内容
第二列是app的使用的userid, 如果没有在AndroidManifext.xml里使用android:sharedUserId属性指定UID, 在app安装的时候,系统会给这个app自动分配一uid,以后app运行时,就用这个UID运行
第三列是app是否处于调试模式,由AndroidManifext.xml里android:debuggable指定
第四列是app的数据存放路径,一般是”/data/data/${package_name}”这样的文件夹
第五列是app的seinfo信息,这个好像和SEAndroid机制有关,它的值好像有platform, default之分
第六列是app所属的user group, 如果一个app不属于任何group, 这里的值是None
2、/data/system/packages.xml 文件详解
记录安装app的详细信息(权限,uid等)
文件结构简单介绍:
<packages>
<version sdkVersion="28" databaseVersion="3" fingerprint="htc/ocla1_sprout_00401/htc_ocla1_sprout:9/PPR1.180610.011/1048332.1:user/release-keys" />
<version volumeUuid="primary_physical" sdkVersion="28" databaseVersion="3"
fingerprint="htc/ocla1_sprout_00401/htc_ocla1_sprout:9/PPR1.180610.011/1048332.1:user/release-keys" />
<permission-trees>
<item name="com.google.android.googleapps.permission.GOOGLE_AUTH" package="com.google.android.gsf" />
</permission-trees>
<permissions>
<item name="com.htc.trimslow.permission.EDIT" package="com.htc.zero" protection="18" />
…
</permissions>
<package ***>
…
</package>
<updated-package ***>
…
</updated-package>
<shared-user name="android.media" userId="10033">
…
</shared-user>
<keyset-settings version="1">
…
</keyset-settings>
</packages>
packages.xml文件中主要的信息分为下面几个部分:
permission块: 里面包含了系统中所有定义的权限的信息
package块:里面包含了系统中所有安装的app的详细信息
shared-user块:里面包含了所有系统定义的shareuser的信息
keyset-settings块:里面包含了已安装app签名的public key信息
下面来详细介绍一下每个元素块里的具体内容.
2.1、permission块
permission内容结构如下:
<permissions>
<item name="com.htc.gc.companion.permission.USE_PROVIDER" package="com.htc.gc.companion" protection="2"
/>
<item name="android.permission.REAL_GET_TASKS" package="android" protection="18" />
</permissions>
它里面定义了系统中所有声明的权限信息,每个item代表一个权限.
nam: 权限名
package: 包名
protection:权限等级
permission的权限组:包含默认配置的权限和所有app的权限组去重之后的结果
2.2、package块
package块内容结构如下:
<package name="com.qualcomm.qti.qms.service.telemetry" codePath="/vendor/app/SSGTelemetryService"
nativeLibraryPath="/vendor/app/SSGTelemetryService/lib" primaryCpuAbi="armeabi-v7a" publicFlags="810073669"
privateFlags="262144" ft="1659f8a6d70" it="1659f8a6d70" ut="1659f8a6d70" version="789610" userId="10096"
isOrphaned="true">
<sigs count="1" schemeVersion="3">
<cert index="1" key="***" />
</sigs>
<perms>
<item name="android.permission.RECEIVE_BOOT_COMPLETED" granted="true" flags="0" />
<item name="android.permission.INTERNET" granted="true" flags="0" />
<item name="android.permission.ACCESS_NETWORK_STATE" granted="true" flags="0" />
</perms>
<proper-signing-keyset identifier="1" />
<domain-verification packageName="com.google.android.calendar" status="0">
<domain name="www.google.com" />
<domain name="calendar.google.com" />
</domain-verification>
</package>
package包含了每个app的详细信息
name: 应用的包名
codePath: apk存放位置
nativeLibraryPath: so库存放位置
primaryCpuAbi: 应用以哪种abi框架运行
publicFlags="810073669": pkg.applicationInfo.flags
privateFlags="262144":, pkg.applicationInfo.privateFlags
是根据AndroidManifest.xml里的设置生成的,例如:android:multiarch
ft="1659f8a6d70"=pkg.timeStamp: apk文件上次被更改的时间
it="1659f8a6d70"= pkg.firstInstallTime: app第一次安装的时间
ut="1659f8a6d70"=pkg.lastUpdateTime: app上次被更新时间. app重装之后,这里的ft和ut会改变
version="789610": app版本号
userId="10096": 为app分配的user id, 如果有使用shareUserId, 这里出现的就是SharedUserId
isOrphaned="true": (系统应用和预加载应用值为true)
sigs块里的count表示这个app有多少个签名信息,有的app可能会被多个证书签名。
cert里的index表示这个app使用的证书的序号,当系统发现一个新的证书,这个号就会加1,key是app使用的证书内容的ascii码值。PKMS在扫apk文件过程中,如果发现它和之前扫描到的apk使用的是相同的签名证书,这里就只会有个index的值,并没有key的值。拥有相同的index的package, 表明它们使用的是相同的签名
perms块里是这个app拥有的权限, 对于一般的app,这些权限是在AndroidManifest.xml里写明的;那些使用了相同UID(sharedUserId)的app, 这里的权限就是所有使用相同UID/(sharedUserId)的app申请的权限的总和。 granted表示这个权限是不是已经被允许。
proper-signing-keyset里的identifier就是keyset-settings的keysets里identifier的值。它是用来标明这个app使用的是哪个公钥。
内置的应用更新后会出现<updated-package>结构块
2.3、shared-user块
shared-user块结构如下:
<shared-user name="com.google.android.calendar.uid.shared" userId="10057">
<sigs count="1" schemeVersion="2">
<cert index="4" />
</sigs>
<perms>
…
<item name="android.permission.WAKE_LOCK" granted="true" flags="0" />
</perms>
</shared-user>
name表示这个shared-user的名字,userId表示这个user在系统中的编号,具体可以查看Process.java
sigs和package块里的意思相同
perms表示这个user所具有的权限。在开机扫描apk文件时,它会将所有使用了相同uid的app的权限收集到一起,然后放在这里。并且最后还会把这些权限再下发给那些使用了相同uid的app。最后的结果就是,系统中使用相同uid的app,它们具有一样的权限
2.4、keyset-settings块
keyset-settings的结构如下:
<keyset-settings version="1">
<keys>
<public-key identifier="29" value="***" />
</keys>
<keysets>
<keyset identifier="29">
<key-id identifier="29" />
</keyset>
</keysets>
<lastIssuedKeyId value="29" />
<lastIssuedKeySetId value="29" />
</keyset-settings>
keyset-settings块里收集了所有app签名的公钥信息,和上面介绍的package块中的信息有关联。
keysets块中包含了很多keyset, 每个keyset都有一个编号用identifier表示,keyset里包含的key-id里的identifier和上面keys中public-key的identifier的值相对应。
keys块中public-key里的value值就是从apk包里的签名文件里提取出来的的公钥的值。
lastIssuedKeyId和lastIssuedKeySetId表示的是最近一次取出来的公钥所属的set编号。
3、源码分析
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
systemserver.main()-->systemserver.startBootstrapServices()-->PackageManagerService.main-->PackageManagerService() -->mSettings.writeLPr();
void writeLPr(){
...
serializer.startTag(null, "permissions");//permissions
mPermissions.writePermissions(serializer);
serializer.endTag(null, "permissions");
for (final PackageSetting pkg : mPackages.values()) {//package
writePackageLPr(serializer, pkg);
}
for (final SharedUserSetting usr : mSharedUsers.values()) {//shared-user
serializer.startTag(null, "shared-user");
serializer.attribute(null, ATTR_NAME, usr.name);
serializer.attribute(null, "userId",
Integer.toString(usr.userId));
usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
writePermissionsLPr(serializer, usr.getPermissionsState()
.getInstallPermissionStates());
serializer.endTag(null, "shared-user");
}
mKeySetManagerService.writeKeySetManagerServiceLPr(serializer);//keyset
writePackageListLPr();// package.list
...
}
[gitbook] Android框架分析系列之Android PackageManager - Android移动开发技术文章_手机开发 - 红黑联盟