Android学习心得(22) --- PackageManagerService源码解析platfrom.xml
2016-10-17 22:21
274 查看
新博客地址
blog.marssecure.complatform.xml
Android中沿用Linux用户和组的来限制系统资源的访问,查看从Android真机pull出/etc/permissions/platform.xml权限初始化
PackageManagerService构造函数会解析platform.xml,建立android权限和gid的对应关系。然后,扫描apk时,会由请求的权限找到对应的gid,并保存在Package类中。由于Android很多都是使用permission来进行保护,需要在AndroidManifest中显示声明对应权限,有些在platfrom.xml中定义的权限须由特定用户组使用
下面来解析一下在该构造方法中对于plafrom.xml解析
源码分析
初始化处理permission文件
创建的时候,在构造方法中初始化systemConfigpublic PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { ... SystemConfig systemConfig = SystemConfig.getInstance() ... }
getInstance()是创建一个SystemConfig对象
public static SystemConfig getInstance() { synchronized (SystemConfig.class) { if (sInstance == null) { sInstance = new SystemConfig(); } return sInstance; } }
SystemConfig构造方法中,使用readPermissions处理了系统和OEM厂商的配置和系统权限
SystemConfig() { /system/etc/sysconfig readPermissions(Environment.buildPath( Environment.getRootDirectory(), "etc", "sysconfig"), false); /system/etc/permissions readPermissions(Environment.buildPath( Environment.getRootDirectory(), "etc", "permissions"), false); /oem/etc/sysconfig readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "sysconfig"), true); /oem/etc/permissions readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "permissions"), true); }
对于上面四个目录都使用了readPermissions函数读取
void readPermissions(File libraryDir, boolean onlyFeatures) { // 从给定的文件夹中读取权限 .... // 迭代方式读取xml文件 File platformFile = null; for (File f : libraryDir.listFiles()) { // 最后单独处理platform.xml if (f.getPath().endsWith("etc/permissions/platform.xml")) { platformFile = f; continue; } ... // 取到的xml结尾的文件,使用readPermissionsFromXml读取 readPermissionsFromXml(f, onlyFeatures); } // 最后读取平台权限以致其能最优先 if (platformFile != null) { readPermissionsFromXml(platformFile, onlyFeatures); } }
不管是platform.xml还是其他的xml文件,都是调用readPermissionsFromXml函数处理,assign-permission解析后存放到mSystemPermissions中,uid和permission对应
ArraySet<String> perms = mSystemPermissions.get(uid); if (perms == null) { perms = new ArraySet<String>(); mSystemPermissions.put(uid, perms); } perms.add(perm); permission将permission和gid存放到mPermissions中 PermissionEntry perm = mPermissions.get(name); if (perm == null) { perm = new PermissionEntry(name); mPermissions.put(name, perm); }
整体方法源代码
private void readPermissionsFromXml(File permFile, boolean onlyFeatures) { FileReader permReader = null; permReader = new FileReader(permFile); // 当前系统是否对低内存支持 final boolean lowRam = ActivityManager.isLowRamDeviceStatic(); try { XmlPullParser parser = Xml.newPullParser(); parser.setInput(permReader); int type; while ((type=parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) { ; } if (type != parser.START_TAG) { throw new XmlPullParserException("No start tag found"); } if (!parser.getName().equals("permissions") && !parser.getName().equals("config")) { throw new XmlPullParserException("Unexpected start tag in " + permFile + ": found " + parser.getName() + ", expected 'permissions' or 'config'"); } while (true) { XmlUtils.nextElement(parser); String name = parser.getName(); if ("group".equals(name) && !onlyFeatures) { String gidStr = parser.getAttributeValue(null, "gid"); if (gidStr != null) { int gid = android.os.Process.getGidForName(gidStr); mGlobalGids = appendInt(mGlobalGids, gid); } else { Slog.w(TAG, "<group> without gid in " + permFile + " at " + parser.getPositionDescription()); } XmlUtils.skipCurrentTag(parser); continue; } else if ("permission".equals(name) && !onlyFeatures) { String perm = parser.getAttributeValue(null, "name"); perm = perm.intern(); readPermission(parser, perm); } else if ("assign-permission".equals(name) && !onlyFeatures) { String perm = parser.getAttributeValue(null, "name"); String uidStr = parser.getAttributeValue(null, "uid"); int uid = Process.getUidForName(uidStr); perm = perm.intern(); ArraySet<String> perms = mSystemPermissions.get(uid); if (perms == null) { perms = new ArraySet<String>(); mSystemPermissions.put(uid, perms); } perms.add(perm); XmlUtils.skipCurrentTag(parser); } else if ("library".equals(name) && !onlyFeatures) { String lname = parser.getAttributeValue(null, "name"); String lfile = parser.getAttributeValue(null, "file"); if (lname == null) { Slog.w(TAG, "<library> without name in " + permFile + " at " + parser.getPositionDescription()); } else if (lfile == null) { Slog.w(TAG, "<library> without file in " + permFile + " at " + parser.getPositionDescription()); } else { //Log.i(TAG, "Got library " + lname + " in " + lfile); mSharedLibraries.put(lname, lfile); } XmlUtils.skipCurrentTag(parser); continue; } else if ("feature".equals(name)) { String fname = parser.getAttributeValue(null, "name"); boolean allowed; if (!lowRam) { allowed = true; } else { String notLowRam = parser.getAttributeValue(null, "notLowRam"); allowed = !"true".equals(notLowRam); } if (fname == null) { Slog.w(TAG, "<feature> without name in " + permFile + " at " + parser.getPositionDescription()); } else if (allowed) { //Log.i(TAG, "Got feature " + fname); FeatureInfo fi = new FeatureInfo(); fi.name = fname; mAvailableFeatures.put(fname, fi); } XmlUtils.skipCurrentTag(parser); continue; } else if ("unavailable-feature".equals(name)) { String fname = parser.getAttributeValue(null, "name"); if (fname == null) { Slog.w(TAG, "<unavailable-feature> without name in " + permFile + " at " + parser.getPositionDescription()); } else { mUnavailableFeatures.add(fname); } XmlUtils.skipCurrentTag(parser); continue; } else if ("allow-in-power-save".equals(name) && !onlyFeatures) { String pkgname = parser.getAttributeValue(null, "package"); if (pkgname == null) { Slog.w(TAG, "<allow-in-power-save> without package in " + permFile + " at " + parser.getPositionDescription()); } else { mAllowInPowerSave.add(pkgname); } XmlUtils.skipCurrentTag(parser); continue; } else if ("fixed-ime-app".equals(name) && !onlyFeatures) { String pkgname = parser.getAttributeValue(null, "package"); if (pkgname == null) { Slog.w(TAG, "<fixed-ime-app> without package in " + permFile + " at " + parser.getPositionDescription()); } else { mFixedImeApps.add(pkgname); } XmlUtils.skipCurrentTag(parser); continue; } else { XmlUtils.skipCurrentTag(parser); continue; } } } catch (XmlPullParserException e) { ... } finally { IoUtils.closeQuietly(permReader); } for (String fname : mUnavailableFeatures) { if (mAvailableFeatures.remove(fname) != null) { Slog.d(TAG, "Removed unavailable feature " + fname); } } }
看platfrom.xml文件中内容,permission将属性name中权限赋予group中gid用户组,assign-permission把属性name中权限赋予uid用户
<permissions> <permission name="android.permission.BLUETOOTH_ADMIN" > <group gid="net_bt_admin" /> </permission> <permission name="android.permission.BLUETOOTH" > <group gid="net_bt" /> </permission> <permission name="android.permission.INTERNET" > <group gid="inet" /> </permission> ... <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" /> <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" /> <assign-permission name="android.permission.WAKE_LOCK" uid="media" /> <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="media" /> <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="media" /> <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" /> <library name="android.test.runner" file="/system/framework/android.test.runner.jar" /> <library name="javax.obex" file="/system/framework/javax.obex.jar"/> <library name="javax.btobex" file="/system/framework/javax.btobex.jar"/> <!--网络访问的白名单,即使他们不在前面--> <allow-in-power-save package="com.android.providers.downloads" /> </permissions>
未来:
下一步会去研究一下安装apk时候权限解析的源代码,更好理解权限在整个系统中的运用。希望对大家有所帮助,也希望你可以一直支持我们MarsSecure。相关文章推荐
- Android学习心得(一)——绘图
- Android学习心得
- 2011年8月21日学习心得,Android中Intent的注意
- Android学习心得
- Android学习系列(22)--App主界面比较
- Android学习心得(六)——位置服务
- Android学习心得 一
- android 学习心得---webview使用得到网页加载时间
- android 学习心得1---网络编程
- android的startActivityForResult学习心得
- android学习的历史心得
- 快乐分享Android学习心得---为App签名(为apk签名)
- android_学习心得
- android学习心得
- android Gallery的学习心得
- Android学习心得(一)——绘图(转别个的)
- Mars Android视频学习笔记——01_21/22_广播机制
- 快乐分享Android学习心得---模型学习方探究App布局学习
- android最佳学习路线,学习心得
- android近期学习心得