閱讀本文大約需要花費15分鐘。
專注於Android系統級源碼分析,Android的平臺設計,歡迎關注我,謝謝!
系列文章:
6 掃描APK目錄
PackageManagerService的構造函數中調用了scanDirTracedLI方法來掃描某個目錄的apk文件。
Android 10.0中,PKMS主要掃描以下路徑的APK信息:
<code>/vendor/overlay
/product/overlay
/product_services/overlay
/odm/overlay
/oem/overlay
/system/framework
/system/priv-app
/system/app
/vendor/priv-app
/vendor/app
/odm/priv-app
/odm/app
/oem/app
/oem/priv-app
/product/priv-app
/product/app
/product_services/priv-app
/product_services/app
/product_services/priv-app/<code>
我們就scanDirTracedLI()為入口來進行分析:
6.1 [ParallelPackageParser.java] scanDirTracedLI()
從下面的函數可見,scanDirTracedLI的入口很簡單,首先加入了一些systtrace的日誌追蹤,然後調用scanDirLI()進行分析
6.2 [ParallelPackageParser.java] scanDirLI()
scanDirLI()中使用了ParallelPackageParser的對象,ParallelPackageParser是一個隊列,我們這裡手機所有系統的apk,然後從這些隊列裡面取出apk,再調用PackageParser 解析進行解析
6.3 [ParallelPackageParser.java] submit
把掃描路徑中的APK等內容,放入隊列mQueue,並把parsePackage()賦給ParseResult,用於後面的調用
通過parsePackage 進行apk解析,如果傳入的packageFile是目錄,調用parseClusterPackage()解析,
如果傳入的是APK文件,就調用parseMonolithicPackage()解析
我們先來看看parseClusterPackage()
作用:解析給定目錄中包含的所有apk,將它們視為單個包。這還可以執行完整性檢查,比如需要相同的包名和版本代碼、單個基本APK和惟一的拆分名稱
首先通過parseClusterPackageLite()對目錄下的apk文件進行初步分析,主要區別是核心應用還是非核心應用。核心應用只有一個,非核心應用可以沒有,或者多個,非核心應用的作用主要用來保存資源和代碼。然後對核心應用調用parseBaseApk分析並生成Package。對非核心應用調用parseSplitApk,分析結果放在前面的Package對象中
再看parseMonolithicPackage(),它的作用是解析給定的APK文件,將其作為單個單塊包處理。
最終也是調用parseBaseApk()進行解析,我們接下來看下parseBaseApk()
從AndroidManifest.xml中獲取標籤名,解析標籤中的各個item的內容,存入Package對象中
例如獲取標籤"application"、"permission"
上面解析AndroidManifest.xml,
會得到"application"、"overlay"、"permission"、"uses-permission"等信息
我們下面就針對"application"進行展開分析一下,進入parseBaseApplication()函數
在 PackageParser 掃描完一個 APK 後,此時系統已經根據該 APK 中 AndroidManifest.xml,創建了一個完整的 Package 對象,
下一步就是將該 Package 加入到系統中。此時調用的函數就是另外一個 scanPackageChildLI
6.4 [PackageManagerService.java] scanPackageChildLI()
調用addForInitLI()在platform初始化時,把Package內容加入到內部數據結構
回顧一下整個APK的掃描過程:
- 按照core app >system app > other app 優先級掃描APK,解析AndroidManifest.xml文件,得到各個標籤內容
- 解析XML文件得到的信息由 Package 保存。從該類的成員變量可看出,和 Android 四大組件相關的信息分別由 activites、receivers、providers、services 保存。由於一個 APK 可聲明多個組件,因此 activites 和 receivers等均聲明為 ArrayList。
- 在 PackageParser 掃描完一個 APK 後,此時系統已經根據該 APK 中 AndroidManifest.xml,創建了一個完整的 Package 對象,下一步就是將該 Package 加入到系統中
- 非系統 Package 掃描失敗,刪除文件
下一節將會講解PKMS 的APK安裝等內容,歡迎關注我
閱讀更多 IngresGe 的文章