摘要:PackageManagerService在systemReady()後,進行了/system/etc/permissions中的各種xml進行掃描,進行相應的權限存儲,供以後使用
閱讀本文大約需要花費15分鐘。
文章的內容主要還是從源碼進行分析,雖然又臭又長,但是如果想要學習Android系統源碼,這是必要走的路,沒有捷徑。
相對於碎片學習,我更傾向於靜下心來花費1個小時認真的學習一段內容。
文章首發微信公衆號:IngresGe
專注於Android系統級源碼分析,Android的平臺設計,歡迎關注我,謝謝!
[Android取經之路] 的源碼都基於Android-Q(10.0) 進行分析
[Android取經之路] 系列文章:
《系統啓動篇》
- Android系統架構
- Android是怎麼啓動的
- Android 10.0系統啓動之init進程
- Android10.0系統啓動之Zygote進程
- Android 10.0 系統啓動之SystemServer進程
- Android 10.0 系統服務之ActivityMnagerService
- Android10.0系統啓動之Launcher(桌面)啓動流程
- Android10.0應用進程創建過程以及Zygote的fork流程
- Android 10.0 PackageManagerService(一)工作原理及啓動流程
- Android 10.0 PackageManagerService(二)權限掃描
- Android 10.0 PackageManagerService(三)APK掃描
- Android 10.0 PackageManagerService(四)APK安裝流程
《日誌系統篇》
- Android10.0 日誌系統分析(一)-logd、logcat 指令說明、分類和屬性
- Android10.0 日誌系統分析(二)-logd、logcat架構分析及日誌系統初始化
- Android10.0 日誌系統分析(三)-logd、logcat讀寫日誌源碼分析
- Android10.0 日誌系統分析(四)-selinux、kernel日誌在logd中的實現
《PackageManagerService系列文章》
- Android 10.0 PackageManagerService(一)工作原理及啓動流程
- Android 10.0 PackageManagerService(二)權限掃描
- Android 10.0 PackageManagerService(三)APK掃描
- Android 10.0 PackageManagerService(四)APK安裝流程
《Binder通信原理》
- Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
- Android10.0 Binder通信原理(二)-Binder入門篇
- Android10.0 Binder通信原理(三)-ServiceManager篇
- Android10.0 Binder通信原理(四)-Native-C\C++實例分析
- Android10.0 Binder通信原理(五)-Binder驅動分析
- Android10.0 Binder通信原理(六)-Binder數據如何完成定向打擊
- Android10.0 Binder通信原理(七)-Framework binder示例
- Android10.0 Binder通信原理(八)-Framework層分析
- Android10.0 Binder通信原理(九)-AIDL Binder示例
- Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub設計模式
- Android10.0 Binder通信原理(十一)-Binder總結
5 權限掃描
PKMS systemReady()時,通過SystemConfig的readPermissionsFromXml()來掃描讀取/system/etc/permissions中的xml文件,包括platform.xml和系統支持的各種硬件模塊的feature主要工作:
參考下圖:
下面就針對於上述內容,進行分析
5.1 [SystemConfig.java] readPermissions()
說明:掃描/system/etc/permissions中文件,調用
readPermissionsFromXml()進行解析,存入SsytemConfig相應的成員數組變量中
void readPermissions(File libraryDir, int permissionFlag) {
...
// Iterate over the files in the directory and scan .xml files
File platformFile = null;
for (File f : libraryDir.listFiles()) {
if (!f.isFile()) {
continue;
}
// 最後讀取platform.xml
if (f.getPath().endsWith("etc/permissions/platform.xml")) {
platformFile = f;
continue;
}
...
readPermissionsFromXml(f, permissionFlag);
}
// Read platform permissions last so it will take precedence
if (platformFile != null) {
readPermissionsFromXml(platformFile, permissionFlag);
}
}
解析xml的標籤節點,存入mGlobalGids、mPermissions、mSystemPermissions等成員變量中,供其他進行調用
private void readPermissionsFromXml(File permFile, int permissionFlag) {
FileReader permReader = null;
permReader = new FileReader(permFile);
...
XmlPullParser parser = Xml.newPullParser();
parser.setInput(permReader);
while (true) {
...
String name = parser.getName();
switch (name) {
//解析 group 標籤,前面介紹的 XML 文件中沒有單獨使用該標籤的地方
case "group": {
String gidStr = parser.getAttributeValue(null, "gid");
if (gidStr != null) {
int gid = android.os.Process.getGidForName(gidStr);
//轉換 XML 中的 gid字符串爲整型,並保存到 mGlobalGids 中
mGlobalGids = appendInt(mGlobalGids, gid);
} else {
Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at "
+ parser.getPositionDescription());
}
...
}break;
case "permission": { //解析 permission 標籤
if (allowPermissions) {
String perm = parser.getAttributeValue(null, "name");
if (perm == null) {
Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
+ parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
break;
}
perm = perm.intern();
readPermission(parser, perm); //調用 readPermission 處理,存入mPermissions
} else {
logNotAllowedInPartition(name, permFile, parser);
XmlUtils.skipCurrentTag(parser);
}
} break;
}
}
}
5.2 XML文件
/system/etc/permissions中會存在很多的xml文件,例如我們看下
android.software.webview.xml的文件,內容如下:
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<feature name="android.software.webview" />
</permissions>
裏面只只有一個feature "android.software.webview",大部分的xml都是類似的定義方式。
讓我們來簡單的看下/system/etc/permissions/platform.xml的內容
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<permission name="android.permission.BLUETOOTH_ADMIN" >
<group gid="net_bt_admin" />
</permission>
<permission name="android.permission.INTERNET" >
<group gid="inet" />
</permission>
<permission name="android.permission.READ_LOGS" >
<group gid="log" />
</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" />
...
<split-permission name="android.permission.ACCESS_FINE_LOCATION">
<new-permission name="android.permission.ACCESS_COARSE_LOCATION" />
</split-permission>
<split-permission name="android.permission.WRITE_EXTERNAL_STORAGE">
<new-permission name="android.permission.READ_EXTERNAL_STORAGE" />
</split-permission>
<split-permission name="android.permission.READ_CONTACTS"
targetSdk="16">
<new-permission name="android.permission.READ_CALL_LOG" />
</split-permission>
...
<library name="android.test.base"
file="/system/framework/android.test.base.jar" />
<library name="android.test.mock"
file="/system/framework/android.test.mock.jar"
dependency="android.test.base" />
<library name="android.test.runner"
file="/system/framework/android.test.runner.jar"
dependency="android.test.base:android.test.mock" />
<!-- In BOOT_JARS historically, and now added to legacy applications. -->
<library name="android.hidl.base-V1.0-java"
file="/system/framework/android.hidl.base-V1.0-java.jar" />
<library name="android.hidl.manager-V1.0-java"
file="/system/framework/android.hidl.manager-V1.0-java.jar"
dependency="android.hidl.base-V1.0-java" />
...
</permissions>
platform.xml中出現的標籤種類則較爲多樣,它們的含義分別是:
-
<group>:根據name獲取gid
-
<permission >標籤:把屬性name所描述的權限賦予給<group>標籤中屬性gid所表示的用戶組,一個權限可以有一個或多個group對象,當一個APK授權於這個這個權限時,它同時屬於這幾個組
-
<assign-permission>標籤:把屬性name所描述的權限賦予給uid屬性所表示的用戶
-
<split-permission>標籤:一個權限可以擴展出一個新的權限
-
<library>標籤:除framework中動態庫以外的,所有系統會自動加載的動態庫
-
<feature>標籤:硬件支持的一些feature
-
<oem-permission>標籤:oem廠商自己定義的一些權限
-
<privapp-permission>標籤:來自system、vendor、product、system_ext的privapp權限分別存儲,這是防止供應商分區中的xml授權於系統分區中的私有應用權限
最後將上面xml解析出來的數據做如下存儲:
-
<group>標籤gid屬性的值會存放在mGlobalGids數組中;
-
<permission>標籤,解析得到的值會存放在mPermissions集合中;
-
<assign-permission>標籤解析得到的值會存放在mSystemPermissions中;
-
<split-permission>存儲在mSplitPermissions
-
<library>標籤解析得到的值會存放在mSharedLibraries中;
-
<feature>存儲在mAvaliableFeatures
-
<oem-permission>存儲在mOemPermissions
-
<privapp-permission>會根據不同的存儲路徑,分別存儲在mVendorPrivAppPermissions、mProductPrivAppPermissions、mSystemExtPrivAppPermissions、mPrivAppPermissions
-
下一節將會講解PKMS 的APK掃描、安裝等內容,歡迎關注我
微信公衆號:IngresGe