Android的PackageManagerService10.0源碼解讀(AndroidManifest.xml解析)

Android的ActivityManagerService(簡稱AMS)的源碼分析

Android的PackageManagerService10.0源碼解讀(AndroidManifest.xml解析)

Android判斷Activity是否在AndroidManifest.xml裏面註冊(源碼分析)

Android的PackageManagerService10.0源碼解讀

PackageManagerService 簡稱 PKMS

PKMS簡介


PackageManagerService(簡稱 PKMS),是 Android 系統中核心服務之一,負責應用程序的安 裝,卸載,信息查詢,等工作。
Android系統啓動時,會啓動(應用程序管理服務器PKMS),此服務負責掃描系統中特定的目錄,尋找裏面的APK格式的文件,並對這些文件進行解析,然後得到應用程序相關信息,最後完成應用程序的安裝。

PKMS在安裝應用過程中, 會全面解析應用程序的AndroidManifest.xml文件, 來得到Activity,
Service, BroadcastReceiver, ContextProvider 等信息, 在結合PKMS服務就可以在OS中正常的使用應用程序了。

在Android系統中, 系統啓動時由SystemServer啓動PKMS服務, 啓動該服務後會執行應用程序的安裝過程。

PKMS主要作用

PKMS 與 AMS 一樣,也是Android系統核心服務之一
1.解析AndroidNanifest.xml清單文件,解析清單文件中的所有節點信息
2.掃描.apk文件,安裝系統應用,安裝本地應用等
3.管理本地應用,主要有, 安裝,卸載,應用信息查詢 等
源碼路徑在 /frameworks/base/core/java/android/ 和 /frameworks/base/services/java/com/android/

PKMS角色


客戶端可通過Context.getPackageManager()獲得ApplicationPackageManager對象, 而
mPM指向的是Proxy代理,當調用到mPM.方法後,將會調用到IPackageManager的Proxy代理方法,然後通過Binder機制中的mRemote與服務端PackageManagerService通信 並調用到PackageManagerService的方法。
簡單來說:PKMS是屬於Binder機制的服務端角色.

PKMS的啓動

PKMS啓動過程描述:

SystemServer啓動PKMS: 先是在SystemServer.startBootstrapServices()函數中啓動PKMS服務,再調用startOtherServices()函數中對dex優化,磁盤管理功能,讓PKMS進入systemReady狀態。

第一步:啓動Installer服務
SystemServer.startBootstrapServices()
Installer installer = mSystemServiceManager.startService(Installer.class);
第二步:獲取手機是否加密
String cryptState = VoldProperties.decrypt().orElse("");
第三步:調用PKMS的main方法,實列化
 PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest);
        t.traceEnd(); // "create package manager"
        m.installWhitelistedSystemPackages();
        ServiceManager.addService("package", m);
    final PackageManagerNative pmn = m.new PackageManagerNative();
        ServiceManager.addService("package_native", pmn);
第四步:

如果設備沒有加密,直接操作,管理A/B OTA dexopting
SystemServer啓動服務,使核心服務處於ready狀態,startOtherServices

 if(!mOnlyCore)
    {
        boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt", false);
        OtaDexoptService.main(mSystemContext, mPackageManagerService);
    }
第五步:

如果設備沒有加密,執行performDexOptUpgrade完成dex優化, PKMS.updatePackagesIfNeeded()

mPackageManagerService.updatePackagesIfNeeded();
第六步:

執行performFstrimIfNeeded(),完成磁盤維護,

第七步:

執行systemReady(),PKMS準備就緒
主要是PKMS的main()方法
(1) 檢查Package編譯相關係統屬性
(2) 調用PackageManagerService構造方法
(3) 啓用部分應用服務於多用戶場景
(4) 在ServiceManager中註冊”package”和”package_native”。

 public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
        // (1)檢查Package編譯相關係統屬性 
        PackageManagerServiceCompilerMapping.checkProperties();
        // (2)調用PackageManagerService構造方法, 
        PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore);
        //(3)啓用部分應用服務於多用戶場景 
        m.enableSystemUserPackages();
        //(4)往ServiceManager中註冊”package”和”package_native”。 
        ServiceManager.addService("package", m);
        final PackageManagerNative pmn = m.new PackageManagerNative();
        ServiceManager.addService("package_native", pmn);
        return m;
    }
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore)

PKMS的構造函數主要作用,具體可以看源碼
(1) 構造 DisplayMetrics ,保存分辨率等相關信息;
(2) 創建Installer對象,與installd交互;
(3) 創建mPermissionManager對象,進行權限管理;
(4) 構造Settings類,保存安裝包信息,清除路徑不存在的孤立應用,主要涉及/data/system/目錄的packages.xml,packages-backup.xml,packages.list,packages-stopped.xml,packagesstopped�backup.xml等文件。
(5) 構造PackageDexOptimizer及DexManager類,處理dex優化;
(6) 創建SystemConfig實例,獲取系統配置信息,配置共享lib庫;
(7) 創建PackageManager的handler線程,循環處理外部安裝相關消息。

APK的掃描


主要是PKMS構造方法,總結一下:
第一步:掃描APK,解析AndroidManifest.xml文件,得到清單文件各個標籤內容
第二步:解析清單文件到的信息由 Package 保存。從該類的成員變量可看出,和 Android 四大組件相關的信息分別由 activites、receivers、providers、services 保存,由於一個 APK 可聲明多個組件,因此activites 和 receivers等均聲明爲 ArrayList。
這下我們就知道了何時解析了AndroidManifest.xml文件,以及裏面的四大組件信息。

簡要說下APK的安裝

安裝步驟一: 把Apk的信息通過IO流的形式寫入到PackageInstaller.Session中
安裝步驟二: 調用PackageInstaller.Session的commit方法, 把Apk的信息交給PKMS處理
安裝步驟三: 進行Apk的Copy操作, 進行安裝



我們看到的安裝界面其實是入PackageInstallerActivity這個。

安裝的原理:

PKMS權限掃描

PackageManagerService執行systemReady()時,通過SystemConfig的readPermissionsFromXml()來掃描讀取/system/etc/permissions中的xml文件,包括platform.xml和系統支持的各種硬件模塊的feature主要工作:
[圖片上傳失敗...(image-cd0e9f-1624121551347)]

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等成員變量中,供其他進行調用.
看下/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>
        <library name="android.test.base" file="/system/framework/android.test.base.jar" />
    </permissions>
總結:權限掃描,掃描/system/etc/permissions中的xml,存入相應的結構體中,供之後權限管理使用

以上是PackageManagerService的主要源碼解析,當然還有很多細節沒有說到,看源碼先看主線,再去看看支線,可以對着源碼和這篇文章一起看看,能夠更加清晰明瞭。

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