閱讀本文大約需要花費40分鐘。
專注於Android系統級源碼分析,Android的平臺設計,歡迎關注我,謝謝!
上一節我們講完了應用進程的創建流程和Zygote fork流程,這一節來看看PackageManagerService的工作流程。
1.概述
PackageManagerService是Android系統核心服務之一,在Android中的非常重要,主要負責的功能如下:
- 解析 AndroidManifest.xml,主要包括AndroidManifest中節點信息的解析和target-name的分析和提煉
- 掃描本地文件,主要針對apk,主要是系統應用、本地安裝應用等等。這部分會在下面仔細講解。
- 管理本地apk,主要包括安裝、刪除等等。
下面稱PackageManagerService為PKMS。
2.核心源碼
<code>
/frameworks/base/core/java/android/app/ApplicationPackageManager.java
/frameworks/base/services/java/com/android/server/SystemServer.java
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/frameworks/base/services/core/java/com/android/server/pm/PackageDexOptimizer.java
/frameworks/base/services/core/java/com/android/server/pm/Installer.java
/frameworks/base/services/core/java/com/android/server/pm/Settings.java
/frameworks/base/services/core/java/com/android/server/pm/permission/BasePermission.java
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
/frameworks/base/core/java/android/content/pm/IPackageManager.aidl
/frameworks/base/core/java/android/content/pm/PackageManager.java
/frameworks/base/core/java/com/android/server/SystemConfig.java/<code>
3.架構
3.1 PKMS 啟動過程
3.2 PKMS 繼承關係
3.3 權限管理
3.4 APK掃描
掃描APK的AndroidManifest.xml中的各個標籤信息,
例如"application"、"overlay"、"permission"、"uses-permission"等信息。
再針對各個標籤的子標籤進程掃描,
例如application會掃描"activity"、"receiver"、"service"、"provider"等信息
後面會詳細講解掃描過程
4.啟動過程
4.1 啟動過程
PKMS服務由SystemServer進行啟動,在SystemServer中startBootstrapServices()啟動PKMS服務,再調用startOtherServices()進行dex優化,磁盤管理等功能,並讓PKMS進入systemready狀態。
啟動調用棧如下圖所示:
4.1.1 [SystemServer.java] startBootstrapServices()
說明:startBootstrapServices()首先啟動Installer服務,也就是安裝器,隨後判斷當前的設備是否處於加密狀態,如果是則只是解析核心應用,接著調用PackageManagerService的靜態方法main來創建pms對象
(1)啟動Installer服務
(2)獲取設備是否加密(手機設置密碼),如果設備加密了,則只解析"core"應用
(3)調用PKMS main方法初始化PackageManagerService,其中調用PackageManagerService()構造函數創建了PKMS對象
(4)如果設備沒有加密,操作它。管理A/B OTA dexopting。
源碼:
4.1.2 [SystemServer.java]
startOtherServices()
說明:
(5)執行 updatePackagesIfNeeded ,完成dex優化;
(6)執行 performFstrimIfNeeded ,完成磁盤維護;
(7)調用systemReady,準備就緒。
源碼:
4.1.3 [PackageManagerService.java] main()
說明:
main函數主要工作:
(1)檢查Package編譯相關係統屬性
(2)調用PackageManagerService構造方法
(3)啟用部分應用服務於多用戶場景
(4)往ServiceManager中註冊”package”和”package_native”。
源碼:
PKMS初始化時的核心部分為PackageManagerService()構造函數的內容,我們下面就來分析該流程
4.2 PKMS構造函數分析
PKMS的構造函數中由兩個重要的鎖(mInstallLock、mPackages) 和5個階段構成,下面會詳細的來分析這些內容。
mInstallLock :用來保護所有安裝apk的訪問權限,此操作通常涉及繁重的磁盤數據讀寫等操作,並且是單線程操作,故有時候會處理很慢。
此鎖不會在已經持有mPackages鎖的情況下火的,反之,在已經持有mInstallLock鎖的情況下,立即獲取mPackages是安全的
mPackages:用來解析內存中所有apk的package信息及相關狀態。
5個階段:
階段1: BOOT_PROGRESS_PMS_START
階段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
階段3:BOOT_PROGRESS_PMS_DATA_SCAN_START
階段4:BOOT_PROGRESS_PMS_SCAN_END
階段5:BOOT_PROGRESS_PMS_READY
PKMS服務也是通過binder進行通信,IPackageManager.aidl由工具轉換後自動生成binder的服務端IPackageManager.Stub和客戶端IPackageManager.Stub.Proxy,具體關係如圖:
Binder服務端:PackageManagerService繼承於IPackageManager.Stub;
Binder客戶端:ApplicationPackageManager(簡稱APM)的成員變量mPM繼承於IPackageManager.Stub.Proxy; 本身APM是繼承於PackageManager對象。
4.2.1 [PackageManagerService.java]
說明:IPackageManager.Stub是IPackageManager.aidl自動生成的,正好也說明了PKMS是service端的,通過binder交互
源碼:
4.2.2 [PackageManagerService.java] PackageManagerService()
說明:PackageManagerService構造函數
源碼:
4.2.3 階段1:BOOT_PROGRESS_PMS_START
主要工作:
(1)構造 DisplayMetrics ,保存分辨率等相關信息;
(2)創建Installer對象,與installd交互;
(3)創建mPermissionManager對象,進行權限管理;
(4)構造Settings類,保存安裝包信息,清除路徑不存在的孤立應用,主要涉及/data/system/目錄的packages.xml,packages-backup.xml,packages.list,packages-stopped.xml,packages-stopped-backup.xml等文件。
(5)構造PackageDexOptimizer及DexManager類,處理dex優化;
(6)創建SystemConfig實例,獲取系統配置信息,配置共享lib庫;
(7)創建PackageManager的handler線程,循環處理外部安裝相關消息。
源碼:
readLPw()會掃描下面5個文件
1) "/data/system/packages.xml"
2) "/data/system/packages-backup.xml"
3) "/data/system/packages.list"
4) "/data/system/packages-stopped.xml"
5) "/data/system/packages-stopped-backup.xml"
5個文件共分為三組,簡單的作用描述如下:
- packages.xml:PKMS 掃描完目標文件夾後會創建該文件。當系統進行程序安裝、卸載和更新等操作時,均會更新該文件。該文件保存了系統中與 package 相關的一些信息。
- packages.list:描述系統中存在的所有非系統自帶的 APK 的信息。當這些程序有變動時,PKMS 就會更新該文件。
- packages-stopped.xml:從系統自帶的設置程序中進入應用程序頁面,然後在選擇強制停止(ForceStop)某個應用時,系統會將該應用的相關信息記錄到此文件中。也就是該文件保存系統中被用戶強制停止的 Package 的信息。
這些目錄的指向,都在Settings中的構造函數完成, 如下所示,得到目錄後調用readLPw()進行掃描
解析上面這個幾個xml的內容,建立對應的數據結構
說明:創建 SharedUserSetting 對象並添加到 Settings 的成員變量 mSharedUsers 中,在 Android 系統中,多個 package 通過設置 sharedUserId 屬性可以運行在同一個進程,共享同一個 UID
源碼:
4.2.4 階段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
主要工作:
(1)從init.rc中獲取環境變量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH;
(2)對於舊版本升級的情況,將安裝時獲取權限變更為運行時申請權限;
(3)掃描system/vendor/product/odm/oem等目錄的priv-app、app、overlay包;
(4)清除安裝時臨時文件以及其他不必要的信息。
源碼:
4.2.5 階段3:BOOT_PROGRESS_PMS_DATA_SCAN_START
主要工作有:對於不僅僅解析核心應用的情況下,還處理data目錄的應用信息,及時更新,祛除不必要的數據。
源碼:
4.2.6 階段4:BOOT_PROGRESS_PMS_SCAN_END
主要工作:
(1)sdk版本變更,更新權限;
(2)OTA升級後首次啟動,清除不必要的緩存數據;
(3)權限等默認項更新完後,清理相關數據;
(4)更新package.xml
源碼:
4.2.7 階段5:BOOT_PROGRESS_PMS_READY
主要工作有:
(1)創建PackageInstallerService對象
(2)GC回收內存
源碼:
4.3 dex 優化
檢查是否需要去更新Packages並進行dex優化,如果沒有OTA升級、沒有大版本升級、沒有清楚過dalvik虛擬機的緩存,可以去更新packages,
最終調用的是Installer的dexopt()進行優化
調用棧如下:
4.3.1 [PackageManagerService.java] updatePackagesIfNeeded()
說明:
檢查是否需要去更新Packages並進行dex優化,如果沒有OTA升級、沒有大版本升級、沒有清楚過dalvik虛擬機的緩存,可以去更新packages
更新packages的優先級:core app >system app > other app,調用 performDexOptUpgrade()進行更新
源碼:
4.3.2 [PackageManagerService.java] performDexOptUpgrade()
說明:判斷是否需要對package進行更新,如果需要更新那麼按照優先級完成dex優化,最終調用Install的dexopt()進行dex優化,參考上面的調用棧
源碼:
4.4 磁盤維護
磁盤維護最終調用的是vold進程的 fstrim()進行清理操作
調用棧:
[PackageManagerService.java] performFstrimIfNeeded()
說明:主要是執行磁盤清理工作,釋放磁盤空間
源碼:
4.5 PKMS 準備就緒
[PackageManagerService.java] systemReady()
說明:systemReady主要完成的是默認授權和更新package的信息,通知在等待pms的一些組件
源碼:
下一節將會講解PKMS 的權限掃描、APK掃描、安裝等內容,歡迎關注我
閱讀更多 IngresGe 的文章