深入安卓Package Manager和Package Installer

LauriZ49 8年前發布 | 28K 次閱讀 Android開發 移動開發

 我們每天都在安裝和卸載APK(安卓應用程序包文件),或許一天會有好幾次,但是你有想過下面問題嗎?

  1. 什么是Package Manager(包管理器)和Package Installer(程序安裝包)?

  2. APK文件保存在Android的哪個地方?

  3. APK文件安裝過程的細節是怎樣的?

  4. Package Manager(包管理器)是怎樣保存數據的?

  5. 我應該去哪里找Package Manager和Package Installer的源碼?

1、什么是Package Manager和Package Installer

PackageInstaller是安卓上默認的應用程序,用它來交互式地安裝普通包文件。PackageInstaller提供了用戶界面來管理應用或者包文件。PackageInstaller調用一個叫InstallAppProgress的activity來獲取用戶發出的指令。InstallAppProgress會請求Package Manager服務,然后通過indalld來安裝包文件。源碼提供在/packages/apps/PackageInstaller上。

Installd這個系統守護程序的首要角色是獲取來自Package Manager服務的請求,而該請求是通過Linux套接字/dev/socket/installed獲得的。
Installd使用管理員權限執行一系列的步驟來安裝APK。參考:commands.c

Package Manger是一個實際上管理應用程序安裝、卸載和升級的API。當我們安裝APK文件時,Package Manager會解析APK包文件和顯示確認信息。當我們點擊OK按鈕后,Package Manger會調用一個叫“InstallPackage”的方法,這個方法有四個參數,也就是uri、installFlags、observer和installPackagename。Package Manger會啟動一個叫“package”的service(服務),現在所有模糊的東西會發生在這個service中。你可以在PackageInstaller源碼中查看“PackageInstallAcitivity.java”和“InstallAppProgress.java”。Package Manger服務運行在系統服務進程中,而安裝守護程序(installd)作為一個本地進程運行著,他們都在系統啟動時開始運行。

2、APK文件保存在Android的哪個地方?

  1. 預裝程序(即相機,日歷和瀏覽器等)保存在/system/app/中。

  2. 用戶安裝程序(APIDemo,Any.do等)保存在/data/app/中。

  3. Package Manager創建數據目錄/data/data//來保存數據庫、shared preference、本地函數庫和緩存數據。

你可能會看到apk文件和同一個APK的*.odex文件,而ODEX文件是完全不同的討論和目的了。

3、APK文件安裝過程的細節是怎樣的?

下面的過程執行在Package Manger服務中。

  • 等待;

  • 添加一個包文件到安裝進程的隊列中;

  • 確定合適的地方來安裝包文件;

  • 復制apk文件到一個給定的目錄下;

  • 確定應用的UID;

  • 請求installd守護程序進程;

  • 創建應用目錄和設置權限;

  • 提取dex代碼到緩存目錄中;

  • 解析packages.list、system、data和packages.xml的最新狀態;

  • 向系統發送廣播消息,消息帶有安裝完成效果的名字Intent.ACTION_PACKAGE_ADDED:如果是更新,會帶有新的(Intent.ACTION_PACKAGE_REPLACED)。

Package Installer

4、Package Manager(包管理器)是怎樣保存數據的?

Package Manager保存應用程序的信息在/data/system目錄下的三個文件里。下面的例子是從Android 4 ICS(Ice Cream Sandwich)模擬器提取出來的圖片。

1. packages.xml:這個文件包含所有的權限和Packages/Applications。

<packages>
<last-platform-version external="15" internal="15">
<permission-trees>
<permissions>
<item name="android.permission.CHANGE_WIFI_MULTICAST_STATE" package="android" protection="1">
<item name="android.permission.CLEAR_APP_USER_DATA" package="android" protection="2">
.
.
.
.
</item></item></permissions>

<package codepath="/system/app/Contacts.apk" flags="1" ft="136567b3990" it="136567b3990" name="com.android.contacts" nativelibrarypath="/data/data/com.android.contacts/lib" shareduserid="10001" ut="136567b3990" version="15"> <sigs count="1"> <cert index="2"> </cert></sigs> </package> . . . . <package codepath="/data/app/com.project.t2i-2.apk" flags="0" ft="13a837c2068" it="13a83704ea3" name="com.project.t2i" nativelibrarypath="/data/data/com.project.t2i/lib" userid="10040" ut="13a837c2ecb" version="1"> <sigs count="1"> <cert index="3" key="308201e53082014ea0030201020204506825ae300d06092a86 4886f70d01010505003037310b30090603550406130255533110300e060355040a13074 16e64726f6964311630140603550403130d416e64726f6964204465627567301e170d31 32303933303130353735305a170d3432303932333130353735305a3037310b300906035 50406130255533110300e060355040a1307416e64726f6964311630140603550403130d 416e64726f696420446562756730819f300d06092a864886f70d010101050003818d003 08189028181009ce1c5fd64db794fd787887e8a2dccf6798ddd2fd6e1d8ab04cd8cdd9e bf721fb3ed6be1d67c55ce729b1e1d32b200cbcfc91c798ef056bc9b2cbc66a396aed6b a3629a18e4839353314252811412202500f11a11c3bf4eb41b2a8747c3c791c89391443 39036345b15b5e080469ac5f536fd9edffcd52dcbdf88cf43c580abd0203010001300d0 6092a864886f70d01010505000381810071fa013b4560f16640ed261262f32085a51fca 63fa6c5c46fde9a862b56b6d6f17dd49643086a39a06314426ba9a38b784601197246f8 d568e349a93bc6af315455de7a8923f40d4051a51e1658ee34aca41494ab94ce978ae38 609803dfb3004806634e6e78dd0be26fe75843958711935ffc85f9fcf81523ce23c86bc c5c7a"> </cert></sigs> <perms> <item name="android.permission.WRITE_EXTERNAL_STORAGE"> </item></perms> </package> . . . . . </permission-trees></last-platform-version></packages></pre>

這個xml文件包含兩種信息,權限和package(application)。 權限是保存在標簽里的。每個Permission(權限)有三個屬性,即name、package和protection。Name屬性包含權限的名字,也就是我們在AndroidManifest.xml所用的,Package屬性表明權限所屬的包。在大多數情況下,“android”是一個值,因為標簽包含默認的權限,以及protection表明安全的等級。

package標簽包含10個屬性和一些子標簽。

Sr 屬性 描述
1 name 包名
2 codePath APK文件安裝路徑(/system/app/ 或 /data/app/)
3 nativeLibraryPath 本地函數庫(*.so文件),默認路徑/data/data/<package name>/lib/
4 flag 存儲ApplicationInfo標記[http://developer.android.com/reference/android/content/pm/ApplicationInfo.html](http://developer.android.com/reference/android/content/pm/ApplicationInfo.html)
5 ft 十六進制時間戳timestamp
6 lt 首次安裝十六進制時間戳
7 ut 最后更新十六進制時間戳
8 version AndroidManifest.xml文件中的版本代碼
[http://developer.android.com/guide/topics/manifest/manifest-element.html#vcode]
9 sharedUserId Linux用戶ID名稱,其他應用可查看此ID。與在AndroidManifest.xml中的定義一致[http://developer.android.com/guide/topics/manifest/manifest-element.html#uid]
10 userId Linux用戶ID名稱

子標簽

  • sigs 簽名信息,count屬性代表cert標簽的數量。

  • cert 包含證書的key,index屬性代表證書的全局索引,當新的證書安裝時,我發現index會隨著增加。

  • perms 包含開發者已經在AndroidManifest.xml中設置好的權限。

2. packages.list: 這是一個簡單的文本文件,包含了包名、用戶id、flag和數據目錄,我找不到更加完美的描述了,但是我設想它可提供更快速的已安裝包的查找,因為這個文件一直只保存重要的信息。

com.android.launcher 10013 0 /data/data/com.android.launcher
com.android.quicksearchbox 10033 0 /data/data/com.android.quicksearchbox
com.android.contacts 10001 0 /data/data/com.android.contacts
com.android.inputmethod.latin 10006 0 /data/data/com.android.inputmethod.latin

3.packages-stoped.xml:這個文件包含了已經是停止狀態的包的列表,停止狀態的應用是不能接收任何的廣播的。參考這個鏈接來了解更多關于停止狀態應用的信息。http://yuki312.blogspot.in/2012/03/androidbroadcaststop.html

<stopped-packages>
<pkg name="com.android.widgetpreview" nl="1"></pkg>
<pkg name="com.example.android.livecubes" nl="1"></pkg>
<pkg name="com.android.gesture.builder" nl="1"></pkg>
<pkg name="com.example.android.softkeyboard" nl="1"></pkg>
</stopped-packages>

5、去哪里可以找到Package Manager和Package Installer的源碼?

Package Manger
frameworks/base/services/java/com/android/server/pm/Settings.java
frameworks/base/services/java/com/android/server/pm/PackageManagerService.java
frameworks/base/services/java/com/android/server/pm/IPackageManager.aidl
frameworks/base/services/java/com/android/server/pm/PackageSignatures.java
frameworks/base/services/java/com/android/server/pm/PreferredActivity.java
frameworks/services/java/com/android/server/PreferredComponent.java
frameworks/core/java/android/content/IntentFilter.java
frameworks/base/core/java/android/content/pm/PackageParser.java
frameworks/base/services/java/com/android/server/pm/Installer.java
frameworks/base/core/java/com/android/internal/app/IMediaContainerService.aidl
frameworks/base/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java

Package Installer
packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java
packages/apps/PackageInstaller/src/com/android/packageinstaller/InstallAppProgress.java

 

 本文由用戶 LauriZ49 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!