古詩詞大全網 - 藝術簽名 - APK安裝(壹)—— PMS原理分析

APK安裝(壹)—— PMS原理分析

在 APK安裝概述 中曾提及apk有四種安裝場景,但無論是哪壹種方式,最終會提交給 PackageManagerService 處理,只是前置的處理鏈路 不同,所以本篇先對 PMS 這壹主要過程進行分析。 frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java 基於Android 9.0

1、對特定的壹些系統進程信息進行設置處理,並保存到 Settings

2、解析 /etc/permissions 下相關xml文件取得系統相關權限、系統具備的相關功能等信息

3、解析 /data/system/package.xml 文件獲取已安裝應用的相關信息

4、對相關的 apk 和 jar 進行 dex 優化處理,主要是 /system/framework 目錄下的相關jar和apk

5、依據 sharedUserId 這個配置來確定 apk 運行在哪個進程,然後把運行的相關進程信息加入到 Settings 中,使得系統可以知道每個 apk 運行在哪個進程中

6、解析 AndroidManifest.xml 文件,提煉文件中的節點信息

7、掃描本地文件,主要針對系統應用、本地安裝應用等等

8、管理本地 apk ,包括安裝、刪除等

前面說到 APK 的信息會提交給 PMS 進行安裝的壹系列工作,具體是通過 PackageHandler 發送消息來驅動 APK 的復制和安裝,其時序圖如下:

上相過程中有幾點需要說明:

1、在 installStage 方法中創建了 InstallParams 對象,它對應於包的安裝數據,並創建 INIT_COPY 消息並發送給 PackageHandler 進行處理;

2、 PackageHandler 在處理 INIT_COPY 消息時,會先判斷是否綁定了 DefaultContainerService ,這是用於檢查和賦值可移動文件的服務,比較耗時,所以和 PMS 並沒有運行在同壹個進程中,它們之間通過 IMediaContainerService 進行 IPC 通信,沒有綁定則會進行綁定,之後

DefaultContainerConnection 同樣是定義在 PMS 中,執行鏈路如下:

3、發送 MCS_BOUND 消息時,根據發送的 Message 是否帶 Object 分為兩種,如下所示:

4、 MCS_BOUND 消息的處理:

HandlerParams PMS 中的抽象類,它的實現類為 PMS 的內部類 InstallParams HandlerParams startCopy 方法如下所示:

PackageManagerService.java#HandlerParams

註釋① 處調用抽象方法 handleStartCopy ,具體實現在 InstallParams 中,如下所示:

PackageManagerService.java#InstallParams

1、 註釋① 處確定了 APK 的安裝位置。

2、 註釋② 處創建 InstallArgs 對象,此對象是壹個抽象類,定義了 APK 的復制和重命名APK等安裝邏輯,在 Android 8.x 及之前的版本中有三個子類: FileInstallArgs、AsecInstallArgs、MoveInstallArgs 。其中 FileInstallArgs 用於處理安裝到非ASEC的存儲空間的APK,即內部存儲空間(Data分區); AsecInstallArgs 用於處理安裝到ASEC(mnt/asec)即SD卡中的APK; MoveInstallArgs 用於處理已安裝APK的移動的邏輯;但在 Android 9.x 之後已經去掉了 AsecInstallArgs

3、 註釋③ 處調用 InstallArgs copyApk 方法,這裏以 FileInstallArgs 的實現為例,內部會調用 FileInstallArgs doCopyApk 方法:

1、 註釋① 處用於創建臨時存儲目錄,比如 /data/app/vmdl18300388.tmp ,其中 18300388 是安裝的 sessionId

2、 註釋② 處通過 IMediaContainerService 跨進程調用 DefaultContainerService copyPackage 方法,這個方法會在 DefaultContainerService 所在的進程中將 APK 復制到臨時存儲目錄,比如 /data/app/vmdl18300388.tmp/base.apk ,至此 APK 的復制工作結束。

在上述 APK 的賦值調用鏈的過程中,在 HandlerParams startCopy 方法中,會調用 handleReturnCode 方法,時序圖如下:

PackageManagerService#handleReturnCode :

註釋① 處檢查APK的狀態,在安裝前確保安裝環境的可靠,如果不可靠會清除復制的APK文件, 註釋③ 處會檢測是否安裝成功,失敗則刪除安裝相關的目錄和文件。安裝完成之後在 註釋⑤ 處會發送 POST_INSALL 消息通知已安裝完成,此處稍後會說明。

註釋② 處的 installPackageTracedLI 會調用 PMS installPackageLI 方法:

PackageManagerService.java#installPackageLI :

這裏需要說明幾點:

1、 註釋③ 處,會先檢測 Settings 中保存有要安裝的 APK 信息,則說明安裝該 APK ,因此需要檢驗APK 的簽名信息,確保安全的進行替換。

2、 註釋④ 處,會對臨時文件重新命名,例如 /data/app/vmdl18300388.tmp/base.apk ,重命名為 /data/app/包名-oONlnRRPYyleU63AveqbYA==/base.apk 。新的包名後面帶上的壹串字母和數字的混合字符串,是使用MD5的方式對隨機生成的16個字符進行加密之後的產物。

3、 註釋⑤ 處,根據 replace 來做區分,如果是替換安裝就會調用replacePackageLIF方法,其方法內部還會對系統APP和非系統APP進行區分處理,如果是新安裝APK會調用installNewPackageLIF方法

PackageManagerService.java#installNewPackageLIF

在上面 processPendingInstall 方法的源碼分析中,在 註釋⑤ 處會發送 POST_INSTALL 消息通知安裝完成,那麽接下來就來具體看壹看在 PackageHandler 中是怎麽處理這個消息的。

以上為主要的方法摘要,具體可總結為:

1、第壹步:這裏主要是先將安裝信息從安裝列列表中移除,這個也是前面在processPendingInstall中添加的

2、第二步:安裝成功後,獲取運行時權限

3、第三步:獲取權限後,發送ACTION_PACKAGE_ADDED廣播,告訴Laucher之流,更新icon

4、第四步:如果是升級更新則在發送兩條廣播

5、第五步:如果安裝包中設置了PRIVATE_FLAG_FORWARD_LOCK或者被要求安裝在SD卡上,則調用sendResourcesChangedBroadcast方法來發送壹個資源更改的廣播

6、第六步:如果該應用是壹個瀏覽器,則要清除瀏覽器設置,重新檢查瀏覽器設置

7、第七步:強制調用gc,出發JVM進行垃圾回收操作

8、第八步:刪除舊的安裝信息

9、回調回調 IPackageInstallObserver2 的 packageInstalled 方法。告訴 PackageInstaller 安裝結果。從而實現了安裝回調到UI層

上述幾部分大致說明 PMS 處理 APK 的主要步驟,可總結如下:

1、當 PackageInstaller APK 的信息提交給 PMS 處理, PMS 會通過向 PackageHandler 發送消息來驅動 APK 的復制和安裝工作

2、 PMS 發送 INIT_COPY MCS_BOUND 類型的消息,控制 PackageHandler 來綁定 DefaultContainerService 來完成 APK 的復制等工作

3、復制 APK 完成之後,則開始進行安裝 APK 的流程,包括安裝前的檢查、安裝 APK 和安裝後的收尾工作。

[ 1 ] /framework/pms/3-pms-install.html

[ 4 ] /article/5119749905/

[ 5 ] /p/9ddb930153b7