Android 包管理流程之包的解析

定義

   包管理服務( PackageManagerService)是ANDROID的系統服務之一,主要功能實現應用包的解析、安裝、更新、移動、卸載等服務。

   PackageManagerService系統類圖如下:


PackageManagerService類圖剖析:

   PackageManagerService主要通過Installer、UserManager、AppDirObserver、Settings、DefaultContainerService、PackageHelper、NativeLibraryHelper、PackageHandler、PackageParser等類實現相應的功能。

各個類的功能解析:

       Installer:與本地服務installd建立LocalSocket連接,藉助installd實現包的install、remove、dexopt等功能。


        UserManager:實現與用戶相關的用戶數據和包的安裝、創建和管理,包括用戶及用戶數據的創建、刪除。


        AppDirObserver:實現對/system/framework,/system/app、 /vendor/app、/data/app、/data/app-private等目錄的add和remove事件的監聽,實現包的動態安裝和卸載。


       Settings:實現data/system/目錄下的包安裝信息相關的文件的讀取和管理(創建、更新等),解析和讀取如下packages.xml、"packages-backup.xml"、"packages.list"、"packages-stopped.xml"、"packages-stopped-backup.xml"  XML文件。


        packages.xml:是在解析apk時由 writeLP()創建的,裏面記錄了系統的permissions以及每個apk的name ,codePath, pkgFlags, timeStamp, versionCode,uesrid等信息,這些信息主要通過apk的 AndroidManifest.xml解析獲取,解析完apk後將更新信息寫入這個文件並保存到flash,下次開機直接從裏面讀取相關信息添加到內存相關列表中。當有apk升級,安裝或刪除時會更新這個文件。


        packages.list:記錄瞭如下數據:pkgName,userId,debugFlag,dataPath(包的數據路徑)。


        packages-stopped.xml:記錄處於停止狀態的包的信息,主要包括包名、notLaunched狀態等信息。


       DefaultContainerService:是一個應用服務,具體負責實現APK等相關資源文件在內部或外部存儲器上的存儲工作。DefaultContainerService服務中提供了一個IMediaContainerService.Stub樁對象。PackageManagerService包管理服務在PackageHandler對象接收到應用安裝消息後首先與該服務建立連接(通過BINDSERVICE)。在服務建立連接後onServiceConnected回調被調用,在onServiceConnected回調函數中根據參數傳進來的IMediaContainerService.Stub的對象引用創建一個遠程代理對象。以後PackageManagerService服務通過該代理對象訪問DefaultContainerService服務。

        PackageHelper:是提供包安裝用到的 MountService的API方法的幫助類。


        NativeLibraryHelper:是提供APK包含的庫文件安裝、刪除、空間大小計算等方法的幫助類。


       PackageHandler:實現包處理相關的消息的處理,如apk安裝請求消息,如adb install等。PackageHandler運行在獨立的線程。


       PackageHandler:對象對應用包的處理請求使用了模板和命令模式,把要處理的請求作爲對象通過消息傳遞給處理函數;包的安裝、移動及獲得包的大小消息請求分別打包爲InstallParams、MoveParams、MeasureParams對象,三個類都繼承自HandlerParams超類,HandlerParams超類中定義了一個模板函數startCopy,模板函數startCopy中使用的三個函數在超類中沒有實現,是虛函數,具體實現的功能由具體類確定;如虛函數handleStartCopy對於InstallParams類實現的是包的安裝工作,對於MoveParams類實現的是包的移動工作,而MeasureParams類中的handleStartCopy函數實現的是包的測量工作。


        InstallParams、MoveParams、MeasureParams:三個類中提供了對應的觀察者接口IPackageInstallObserver、IPackageMoveObserver、IPackageStatsObserver,三個接口在PackageManagerService的客戶端對象調用PackageManagerService服務的包的安裝、移動及獲得包的大小等相關API時作爲參數傳進來,並在InstallParams、MoveParams、MeasureParams三個對象實例化時賦值給對應的觀察者接口。因此三個觀察者接口指向的對象實際是客戶端提供的觀察者對象(樁對象)的遠程代理對象,InstallParams、MoveParams、MeasureParams三個對象通過對應的觀察者接口向遠端客戶端發送通知。採用的模式是代理模式和觀察者模式的複合模式。


      POST_INSTALL:消息的處理也採用了命令設計模式,把請求的參數打包爲PostInstallData對象,PostInstallData對象中包括InstallArgs和PackageInstalledInfo對象,InstallArgs是一個虛類,提供copyApk等接口,接口的具體實現在其具體類FileInstallArgs和SdInstallArgs中完成。


      PackageParser:實現應用包的解析功能,主要是解析每個apk的AndroidManifest.xml文件,處理asset/res等資源文件,建立起每個apk的配置結構信息。PackageParser是其它類功能實現的基礎,是包管理服務最重要的一個類。PackageParser類在實現應用包的解析時採用瞭解釋器模式,對於應用包中的每種語法結構都創建了對應的類,來分別蒐集應用包中的相應信息。

類結構圖如下:

        

       圖中除了Resources及XmlPullParser兩個類外其餘的類都是PackageParser類的內部類,應用包的每個語法結構的對應類都派生自componet類或屬於componet類的內部成員,Package類(一個包一個Package對象)是一個聚合類,把解析出來的一個應用包中的componet聚合到Package類中進行統一管理,PackageParser類將解析出的每個componet及其它信息添加到Package中。Resources及XmlPullParser兩個類負責XML資源讀取的工作。


android包整個解析流程:

         1、  在PackageManagerService服務的構造函數中調用scanDirLI函數對如下FrameworkDir(/system/framework)、SystemAppDir(/system/app)、VendorAppDir(/vendor/app)、AppInstallDir(/data/app)、DrmAppPrivateInstallDir(/data/app-private)五個目錄下的APK文件進行掃描;


         2、  scanDirLI函數對掃描目錄下的每個APK文件調用scanPackageLI(file,        flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime)函數對每個APK文件進行解析,返回包含解析信息的PackageParser.Package對象。scanDirLI函數在解析失敗後還刪除解析的無效APK文件;


         3、  在函數scanPackageLI中首先實例化一個PackageParser對象,接着調用PackageParser對象的parsePackage(scanFile,scanPath, mMetrics, parseFlags)函數對待解析文件進行解析;


         4、  在parsePackage函數中對文件進行一些判斷後,先實例化一個AssetManager對象,並調用AssetManager對象的addAssetPath函數把被解析文件的路徑添加到AssetManager對象,添加成功後實例化一個Resources對象,然後調用AssetManager對象的openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME)函數打開一個解析AndroidManifest.xml文件的XML解析器,接着調用parsePackage(res, parser, flags, errorText)函數開始具體解析工作;


        5、   parsePackage函數先調用parsePackageName函數解析出包名,接着根據包名實例化一個Package對象,接着從AndroidManifest.xml文件中解析出被解析包的VersionCode、VersionName、installLocation等全局屬性信息;然後根據XML文件的標籤循環解析XML文件包含的其它組成部分,對於tagName名稱爲application標籤時調用parseApplication函數解析該application標籤下包含的組件等信息(只能對一個application標籤進行解析);對於tagName名稱爲"permission-group"時調用parsePermissionGroup函數進行解析;對於tagName名稱爲"permission"時調用parsePermission函數進行解析;對於tagName名稱爲"permission-tree"時調用parsePermissionTree函數進行解析;對於tagName名稱爲"permission-tree"時調用parsePermissionTree函數進行解析;對於tagName名稱爲"instrumentation"時調用parseInstrumentation函數進行解析;並解析或跳過其它標籤,如"uses-feature"、"uses-configuration"、"uses-sdk"、"supports-screens"等標籤,獲得應用包的其它屬性;


         6、  在parseApplication函數中首先解析出應用標籤下的包含的應用屬性信息,然後根據XML文件的標籤循環解析應用標籤下包含的其它組件;對於"activity"標籤調用parseActivity函數進行解析,並返回一個Activity對象,添加到Package對象的activities列表中;對於"receiver"標籤也調用parseActivity函數進行解析,返回一個Activity對象,添加到Package對象的receivers列表中;對於"service"標籤調用parseService函數進行解析,並返回一個Service對象,添加到Package對象的services列表中;對於"provider"標籤調用parseProvider函數進行解析,並返回一個Provider對象,添加到Package對象的providers列表中;對於"activity-alias"標籤調用parseActivityAlias函數進行解析,並返回一個Activity對象,添加到Package對象的activities列表中;對於"meta-data"標籤調用parseMetaData函數進行解析,解析出應用的MetaData;解析或跳過其它標籤,如"uses-library"、"uses-package"等標籤;


         7、  在parseApplication函數中會調用parseActivity()來進行解析, 在parseActivity函數中先實例化一個ParseComponentArgs對象和ActivityInfo對象,再實例化Activity對象(實例化的ParseComponentArgs對象和ActivityInfo對象作爲參數傳給Activity對象的構造函數),然後解析"activity"標籤包含的各種屬性信息並賦值給Activity對象的內部ActivityInfo對象的相應屬性;然後根據XML文件的標籤循環解析"activity"標籤下包含的其它部分,對於"intent-filter"標籤先實例化一個ActivityIntentInfo對象,並調用parseIntent解析"intent-filter"部分,解析出的信息放在作爲參數傳給parseIntent函數的ActivityIntentInfo對象中,解析後把包含解析信息的ActivityIntentInfo對象添加到Activity對象的intents列表中;對於"meta-data"標籤調用parseMetaData函數進行解析,解析出Activity對應的MetaData,並跳過其它標籤;標籤循環解析完成後返回已包含解析信息的Activity對象;


         8、  對於其它組件進行同樣過程的解析過程。componet類的每個派生類內部都有一個對應的info對象,具體指向每個componet包含的信息,具體類圖如下:

       

每個componet的信息類都派生自PackageItemInfo類和PackageItemInfo的子類ComponentInfo,而PackageInfo類一個容器類,應用包中解析出的信息都被聚合到PackageInfo類中進行統一管理。

原文轉自:http://blog.csdn.net/goohong/article/details/7881509

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