Android 10.0 PackageManagerService(二)權限掃描-[Android取經之路]

摘要:PackageManagerService在systemReady()後,進行了/system/etc/permissions中的各種xml進行掃描,進行相應的權限存儲,供以後使用

 

閱讀本文大約需要花費15分鐘。

文章的內容主要還是從源碼進行分析,雖然又臭又長,但是如果想要學習Android系統源碼,這是必要走的路,沒有捷徑。

相對於碎片學習,我更傾向於靜下心來花費1個小時認真的學習一段內容。

文章首發微信公衆號:IngresGe

專注於Android系統級源碼分析,Android的平臺設計,歡迎關注我,謝謝!

[Android取經之路] 的源碼都基於Android-Q(10.0) 進行分析

[Android取經之路] 系列文章:

《系統啓動篇》

  1. Android系統架構
  2. Android是怎麼啓動的
  3. Android 10.0系統啓動之init進程
  4. Android10.0系統啓動之Zygote進程
  5. Android 10.0 系統啓動之SystemServer進程
  6. Android 10.0 系統服務之ActivityMnagerService
  7. Android10.0系統啓動之Launcher(桌面)啓動流程
  8. Android10.0應用進程創建過程以及Zygote的fork流程
  9. Android 10.0 PackageManagerService(一)工作原理及啓動流程
  10. Android 10.0 PackageManagerService(二)權限掃描
  11. Android 10.0 PackageManagerService(三)APK掃描
  12. Android 10.0 PackageManagerService(四)APK安裝流程

《日誌系統篇》

  1. Android10.0 日誌系統分析(一)-logd、logcat 指令說明、分類和屬性
  2. Android10.0 日誌系統分析(二)-logd、logcat架構分析及日誌系統初始化
  3. Android10.0 日誌系統分析(三)-logd、logcat讀寫日誌源碼分析
  4. Android10.0 日誌系統分析(四)-selinux、kernel日誌在logd中的實現​

《PackageManagerService系列文章》

  1. Android 10.0 PackageManagerService(一)工作原理及啓動流程
  2. Android 10.0 PackageManagerService(二)權限掃描
  3. Android 10.0 PackageManagerService(三)APK掃描
  4. Android 10.0 PackageManagerService(四)APK安裝流程

《Binder通信原理》

  1. Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
  2. Android10.0 Binder通信原理(二)-Binder入門篇
  3. Android10.0 Binder通信原理(三)-ServiceManager篇
  4. Android10.0 Binder通信原理(四)-Native-C\C++實例分析
  5. Android10.0 Binder通信原理(五)-Binder驅動分析
  6. Android10.0 Binder通信原理(六)-Binder數據如何完成定向打擊
  7. Android10.0 Binder通信原理(七)-Framework binder示例
  8. Android10.0 Binder通信原理(八)-Framework層分析
  9. Android10.0 Binder通信原理(九)-AIDL Binder示例
  10. Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub設計模式​​​​​​​​​​​​​​
  11. 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章