1. 程式人生 > >Android Fk-PKMS(2) PackageManagerService之應用的安裝與解除安裝

Android Fk-PKMS(2) PackageManagerService之應用的安裝與解除安裝

Android Fk-PKMS(2) PackageManagerService之應用的安裝與解除安裝

原文:http://blog.csdn.net/taylorpotter/article/details/76166788

一、Apk安裝解除安裝學習

1.應用的解除安裝概述

  android應用安裝流程已經有很多大神分析過,而且寫的相當詳細精緻,關於應用安裝的詳細流程可以看這篇部落格,Android7.0 PackageManagerService (3) APK安裝。博主結合程式碼流程圖分析的相當詳細,不乏經典之處,可以看出博主應該也是看過鄧凡平的《深入理解Android》系列叢書,在鄧凡平分析的基礎上添加了自己的更深入的程式碼跟蹤與理解,用來學習跟蹤PKMS的安裝流程相當好了;
  應用的安裝方式主要有::


  1.應用市場下載進行靜默安裝;
  2.瀏覽器中下載點選安裝,或者拷貝來apk點選安裝
  3.adb install,adb shell pm install方式
  4.adb push/開機掃描安裝方式
  5.三方應用呼叫PKMS安裝介面進行安裝
  
  其中前兩種使用者操作使用較多,後三種開發者使用的可能比較多些;
  應用市場的安裝方式是採用了靜默安裝的方式,在應用市場中會呼叫種安裝方式,如果第一種安裝失敗則使用第二種直至安裝成功返回,而應用市場為達到靜默安裝的效果使用的安裝方式無非就是使用指令碼pm install的方式,或者呼叫pkms的靜默安裝介面,如果無法靜默安裝即無許可權的話就只得呼叫系統自帶的PackageInstaller進行安裝,這種場景經常可以見到,比如手機Rom自帶的市場就可以做到靜默安裝,而使用三方的市場就很大機率調出安裝介面進行安裝,使用者體驗的確差了很多,可見做平臺廠商的優勢;
  點選apk進行安裝,呼叫的是PackageInstaller進行安裝,瀏覽器下載apk完成有時為了提高使用者體驗也會主動去呼叫PackageInstaller進行安裝,這種方式有安裝介面;
  adb install 和adb shell pm install方式都是執行了system/bin/pm指令碼進行安裝;
  adb push多用於對系統應用的安裝驗證,需要開機重啟才能完成安裝生效;
  而呼叫PKMS介面進行安裝就不多敘述了,應用市場也會使用這樣的方式;
  事實上最終都需要呼叫PKMS的方法進行安裝,只是到達PKMS的方式不同而已,下面將從PackageInstaller方式,adb install方式,adb push方式,及PKMS的通用安裝過程來總結應用的安裝流程。

2.應用解除安裝概述

  應用解除安裝方式主要分兩類:
  1.普通三方應用的解除安裝,我們拖動桌面圖示到垃圾桶即可以解除安裝;
  2.系統應用的解除安裝(即system/目錄下的應用),當用戶手動升級了系統應用,當用戶覺得升級後的系統應用不好用時可以通過settings裡的應用詳情頁上選單按鈕中的解除安裝還原進行系統應用的解除安裝,這個解除安裝操作菜單隻在升級系統應用之後才會顯示出來,並且解除安裝後會重新安裝原始版本及ROM自帶的該系統應用;
  
  本文主要基於Android 7.1.1的原始碼進行分析總結。

二、 APK安裝總結

  首先應該如何定義apk的安裝,自己理解,apk的安裝就是需要將apk的執行檔案拷貝到安裝目錄,然後解析apk,將apk中的元件資訊統計起來,用於以後的元件呼叫管理,另外由於應用會產生使用者資料,需要建立使用者資料儲存的地方,這樣升級apk時只需要升級執行檔案,使用者資料還在。

1.呼叫PackageInstaller安裝方式

1.1 從PKMS安裝應用log開始

  檢視將PKMS的log debug開關開啟後列印的log,操作內容是將百度地圖的apk拷貝到手機中,然後點選手機中的apk,調出PackageInstaller的安裝介面進行安裝:

07-30 10:33:44.409272  1646  1825 I PackageManager: init_copy idx=0: InstallParams{7ae63a2 file=/data/app/vmdl760150628.tmp cid=null}
07-30 10:33:44.775723  1646  1825 I PackageManager: mcs_bound
07-30 10:33:44.776727  1646  1825 I PackageManager: startCopy UserHandle{0}: InstallParams{7ae63a2 file=/data/app/vmdl760150628.tmp cid=null}
07-30 10:33:44.810103  1646  1825 D PackageManager: /data/app/vmdl760150628.tmp already staged; skipping copy
07-30 10:33:44.811681  1646  1825 D PackageManager: installPackageLI: path=/data/app/vmdl760150628.tmp
07-30 10:33:45.263513  1646  1825 D PackageManager: cluster install info.nativeLibraryRootDir:/data/app/vmdl760150628.tmp/lib
07-30 10:33:45.264690  1646  1825 D PackageManager: cluster install info.nativeLibraryDir:/data/app/vmdl760150628.tmp/lib/arm64
07-30 10:33:45.264996  1646  1825 D PackageManager: getPrimaryInstructionSetarm64
07-30 10:33:45.265373  1646  1825 D PackageManager: nativeLibraryRootStr:/data/app/vmdl760150628.tmp/lib
07-30 10:33:45.265727  1646  1825 D PackageManager: cpuAbiOverridenull
07-30 10:33:45.272850  1646  1825 D PackageManager: primaryCpuAbi already determined by nativeLibraryRootDir
07-30 10:33:45.274112  1646  1825 D PackageManager: cluster install info.nativeLibraryRootDir:/data/app/vmdl760150628.tmp/lib
07-30 10:33:45.275442  1646  1825 D PackageManager: cluster install info.nativeLibraryDir:/data/app/vmdl760150628.tmp/lib/arm
07-30 10:33:45.276030  1646  1825 D PackageManager: getPrimaryInstructionSetarm
07-30 10:34:07.310109  1646  1825 I PackageManager.DexOptimizer: DexoptNeeded for /data/app/vmdl760150628.tmp/base.apk@interpret-only is 1
07-30 10:34:07.359918  1646  1825 I PackageManager.DexOptimizer: Running dexopt (dex2oat) on: /data/app/vmdl760150628.tmp/base.apk pkg=com.baidu.BaiduMap isa=arm vmSafeMode=false debuggable=false target-filter=interpret-only oatDir = /data/app/vmdl760150628.tmp/oat sharedLibraries=null
07-30 10:35:18.565479  1646  1825 D PackageManager: Renaming /data/app/vmdl760150628.tmp to /data/app/com.baidu.BaiduMap-1
07-30 10:35:18.621789  1646  1825 D PackageManager: installNewPackageLI: Package{a3988b2 com.baidu.BaiduMap}
07-30 10:35:18.633012  1646  1825 D PackageManager: Scanning package com.baidu.BaiduMap
07-30 10:35:18.781099  1646  1825 D PackageManager: pkg.cpuAbiOverridenull
07-30 10:35:18.781787  1646  1825 D PackageManager: cluster install info.nativeLibraryRootDir:/data/app/com.baidu.BaiduMap-1/lib
07-30 10:35:18.782241  1646  1825 D PackageManager: cluster install info.nativeLibraryDir:/data/app/com.baidu.BaiduMap-1/lib/arm
07-30 10:35:18.782460  1646  1825 D PackageManager: getPrimaryInstructionSetarm
07-30 10:35:18.782792  1646  1825 D PackageManager: Resolved nativeLibraryRoot for com.baidu.BaiduMap to root=/data/app/com.baidu.BaiduMap-1/lib, isa=true
07-30 10:35:18.783156  1646  1825 D PackageManager: Abis for package[com.baidu.BaiduMap] are primary=armeabi-v7a secondary=null
07-30 10:35:18.830131  1646  1825 D PackageManager: Registered content provider: com.baidu.BaiduMap.bdpush, className = com.baidu.android.pushservice.PushInfoProvider, isSyncable = false
07-30 10:35:18.831063  1646  1825 D PackageManager: Registered content provider: com.baidu.lbs.offlinelocationprovider, className = com.baidu.location.OfflineLocationV1Provider, isSyncable = false
07-30 10:35:18.831458  1646  1825 D PackageManager:   Providers: com.baidu.android.pushservice.PushInfoProvider com.baidu.location.OfflineLocationV1Provider
07-30 10:35:18.838816  1646  1825 D PackageManager:   Services: com.baidu.baidunavis.ForegroundService com.baidu.baiduwalknavi.util.WbForegroundService com.baidu.mapframework.open.MapOpenService com.baidu.android.pushservice.CommandService com.baidu.sofire.MyService com.baidu.mapframework.sandbox.SandBoxService com.baidu.sapi2.share.ShareService com.baidu.location.f com.indooratlas.android.sdk.IALocationService com.baidu.location.wifihistory.SManager com.xiaomi.mipush.sdk.PushMessageHandler com.xiaomi.mipush.sdk.MessageHandleService com.baidu.android.pushservice.PushService com.baidu.mapframework.component3.update.ComUpdateService com.baidu.needle.loader.NeedleService com.baidu.needle.loader.NeedleService$InnerService com.baidu.baidumaps.route.RouteConditionService com.baidu.baidumaps.common.app.startup.StartMapService com.baidu.mapframework.favorite.database.FavDataService com.mapbox.telemetry.TelemetryService com.baidu.baiduwalknavi.routebook.database.RBDataService com.baidu.baidumaps.tra...
07-30 10:35:18.846468  1646  1825 D PackageManager:   Receivers: com.baidu.sofire.MyReceiver com.baidu.baidumaps.base.localmap.LMBroadcastReceiver com.baidu.mapframework.location.LocationStartListener com.baidu.baidumaps.push.BMPushMessageReceiver com.baidu.baidumaps.push.BMPushMainReceiver com.baidu.android.pushservice.PushPatchMessageReceiver com.baidu.android.pushservice.PushServiceReceiver com.baidu.android.pushservice.RegistrationReceiver com.baidu.mapframework.component3.update.ComUpdateReceiver com.baidu.needle.work.NeedleReceiver com.baidu.needle.work.PatchProcessReceiver com.baidu.baidumaps.track.receiver.CustomTrackReceiver com.baidu.baidumaps.route.util.ArrivalRemindReceiver com.baidu.baidumaps.alarm.AlarmReceiver com.baidu.mapframework.common.galaxy.GalaxyReceiver com.baidu.mecp.link.bc.server.MecpBcReceiver
07-30 10:35:18.868776  1646  1825 D PackageManager:   Activities: com.baidu.baidumaps.WelcomeScreen com.baidu.baidumaps.guide.NewGuideScreen com.baidu.scenedemo.demo.SceneActivity com.baidu.mapframework.common.video.BMLRRecordVideoActivity com.baidu.mapframework.common.video.BMLRVideoPlayActivity com.baidu.baidumaps.guide.NewUserGuide com.baidu.mapframework.ui.SinaWeiboTask com.baidu.baidumaps.MapsActivity com.baidu.baidunavis.ui.BNVoiceMainActivity com.baidu.baidunavis.ui.BNVoiceDetailActivity com.baidu.baidunavis.ui.BNVoiceSquareActivity com.baidu.baidunavis.ui.widget.WebShellActivity com.baidu.BaiduMap.wxapi.WXEntryActivity com.baidu.BaiduMap.wxapi.WXPayEntryActivity com.baidu.sapi2.ui.activity.LoginActivity com.baidu.sapi2.ui.activity.FillUnameActivity com.baidu.sapi2.ui.activity.ImagePickerActivity com.baidu.sapi2.ui.activity.ImageCropActivity com.baidu.sapi2.ui.activity.ImageRecommendActivity com.baidu.sapi2.ui.activity.UserProfileActivity com.baidu.sapi2.ui.activity.SmsLoginActivity ...
07-30 10:35:18.870555  1646  1825 D PackageManager:   Permissions: baidu.push.permission.WRITE_PUSHINFOPROVIDER.com.baidu.BaiduMap com.baidu.BaiduMap.CALL_MAIN_PROCESS_RECEIVER com.baidu.BaiduMap.permission.MIPUSH_RECEIVE com.baidu.BaiduMap.permission.SANDBOX_PERMISSION
07-30 10:35:24.430637  1646  1825 D PackageManager: New package installed in /data/app/com.baidu.BaiduMap-1
07-30 10:35:31.348520  1646  1825 V PackageManager: prepareAppData for com.baidu.BaiduMap u0 0x3
07-30 10:35:31.453326  1646  1825 V PackageManager: + starting restore round-trip 1
07-30 10:35:31.453696  1646  1825 V PackageManager: No restore - queue post-install for 1
07-30 10:35:31.454134  1646  1825 I PackageManager: mcs_unbind
07-30 10:35:31.454256  1646  1825 I PackageManager: calling disconnectService()
07-30 10:35:31.503445  1646  1825 D PackageManager: Checking for userId:0 if any IntentFilter from the 106 Activities needs verification ...
07-30 10:35:31.640530  1646  1825 D PackageManager: No filters or not all autoVerify for com.baidu.BaiduMap
07-30 10:35:31.641580  1646  1825 V PackageManager: Handling post-install for 1

  從上面的log中已經可以看出應用安裝的大概過程:
Ⅰ.拷貝安裝包至data/app下的臨時資料夾下
  顯示startcopy將資料拷貝到/data/app/,由於已經拷過跳過拷貝動作:

PackageManager: init_copy idx=0: InstallParams{7ae63a2 file=/data/app/vmdl760150628.tmp cid=null}
07-30 10:33:44.775723  1646  1825 I PackageManager: mcs_bound
07-30 10:33:44.776727  1646  1825 I PackageManager: startCopy UserHandle{0}: InstallParams{7ae63a2 file=/data/app/vmdl760150628.tmp cid=null}
07-30 10:33:44.810103  1646  1825 D PackageManager: /data/app/vmdl760150628.tmp already staged; skipping copy

  此時拷貝後的是vmdl965216119.tmp,它是拷貝生成中間資料夾,在”data/app”下,用來下一步的安裝操作,至於為什麼要使用這個名字這裡有篇文章指出:

07-30 10:33:44.811681  1646  1825 D PackageManager: installPackageLI: path=/data/app/vmdl760150628.tmp

  我們可以看到這個資料夾中有拷貝過來的apk和抽取出來的lib資料夾:




Ⅱ.為apk做dexopt優化

07-30 10:34:07.310109  1646  1825 I PackageManager.DexOptimizer: DexoptNeeded for /data/app/vmdl760150628.tmp/base.apk@interpret-only is 1
07-30 10:34:07.359918  1646  1825 I PackageManager.DexOptimizer: Running dexopt (dex2oat) on: /data/app/vmdl760150628.tmp/base.apk pkg=com.baidu.BaiduMap isa=arm vmSafeMode=false debuggable=false target-filter=interpret-only oatDir = /data/app/vmdl760150628.tmp/oat sharedLibraries=null

  通過log來看應該是生成在vmdl965216119.tmp/oat下,我們檢視下檔案,果然生成了優化後的odex檔案:



Ⅲ.臨時資料夾重新命名為包名
  然後就是重新命名了重新命名後vmdl965216119.tmp/變成/data/app/com.demo.mytest-1:

07-30 10:35:18.565479  1646  1825 D PackageManager: Renaming /data/app/vmdl760150628.tmp to /data/app/com.baidu.BaiduMap-1

  再檢視”data/app”下的檔案,發現的確重新命名成了包名:




Ⅳ.統計apk元件資訊
  檔案拷貝好了開始了元件資訊的統計,通過解析apk的AndroidManifest.xml檔案來進行元件的解析統計。這裡統計到PKMS中的變數,也更新到settings中:

07-30 10:35:18.621789  1646  1825 D PackageManager: installNewPackageLI: Package{a3988b2 com.baidu.BaiduMap}
07-30 10:35:18.633012  1646  1825 D PackageManager: Scanning package com.baidu.BaiduMap
...
7-30 10:35:18.830131  1646  1825 D PackageManager: Registered content provider: com.baidu.BaiduMap.bdpush, className = com.baidu.android.pushservice.PushInfoProvider, isSyncable = false
07-30 10:35:18.831063  1646  1825 D PackageManager: Registered content provider: com.baidu.lbs.offlinelocationprovider, className = com.baidu.location.OfflineLocationV1Provider, isSyncable = false
07-30 10:35:18.831458  1646  1825 D PackageManager:   Providers: com.baidu.android.pushservice.PushInfoProvider com.baidu.location.OfflineLocationV1Provider
07-30 10:35:18.838816  1646  1825 D PackageManager:   Services: com.baidu.baidunavis.ForegroundService com.baidu.baiduwalknavi.util.WbForegroundService com.baidu.mapframework.open.MapOpenService com.baidu.android.pushservice.CommandService com.baidu.sofire.MyService com.baidu.mapframework.sandbox.SandBoxService com.baidu.sapi2.share.ShareService com.baidu.location.f com.indooratlas.android.sdk.IALocationService com.baidu.location.wifihistory.SManager com.xiaomi.mipush.sdk.PushMessageHandler com.xiaomi.mipush.sdk.MessageHandleService com.baidu.android.pushservice.PushService com.baidu.mapframework.component3.update.ComUpdateService com.baidu.needle.loader.NeedleService com.baidu.needle.loader.NeedleService$InnerService com.baidu.baidumaps.route.RouteConditionService com.baidu.baidumaps.common.app.startup.StartMapService com.baidu.mapframework.favorite.database.FavDataService com.mapbox.telemetry.TelemetryService com.baidu.baiduwalknavi.routebook.database.RBDataService com.baidu.baidumaps.tra...
07-30 10:35:18.846468  1646  1825 D PackageManager:   Receivers: com.baidu.sofire.MyReceiver com.baidu.baidumaps.base.localmap.LMBroadcastReceiver com.baidu.mapframework.location.LocationStartListener com.baidu.baidumaps.push.BMPushMessageReceiver com.baidu.baidumaps.push.BMPushMainReceiver com.baidu.android.pushservice.PushPatchMessageReceiver com.baidu.android.pushservice.PushServiceReceiver com.baidu.android.pushservice.RegistrationReceiver com.baidu.mapframework.component3.update.ComUpdateReceiver com.baidu.needle.work.NeedleReceiver com.baidu.needle.work.PatchProcessReceiver com.baidu.baidumaps.track.receiver.CustomTrackReceiver com.baidu.baidumaps.route.util.ArrivalRemindReceiver com.baidu.baidumaps.alarm.AlarmReceiver com.baidu.mapframework.common.galaxy.GalaxyReceiver com.baidu.mecp.link.bc.server.MecpBcReceiver
07-30 10:35:18.868776  1646  1825 D PackageManager:   Activities: com.baidu.baidumaps.WelcomeScreen com.baidu.baidumaps.guide.NewGuideScreen com.baidu.scenedemo.demo.SceneActivity com.baidu.mapframework.common.video.BMLRRecordVideoActivity com.baidu.mapframework.common.video.BMLRVideoPlayActivity com.baidu.baidumaps.guide.NewUserGuide com.baidu.mapframework.ui.SinaWeiboTask com.baidu.baidumaps.MapsActivity com.baidu.baidunavis.ui.BNVoiceMainActivity com.baidu.baidunavis.ui.BNVoiceDetailActivity com.baidu.baidunavis.ui.BNVoiceSquareActivity com.baidu.baidunavis.ui.widget.WebShellActivity com.baidu.BaiduMap.wxapi.WXEntryActivity com.baidu.BaiduMap.wxapi.WXPayEntryActivity com.baidu.sapi2.ui.activity.LoginActivity com.baidu.sapi2.ui.activity.FillUnameActivity com.baidu.sapi2.ui.activity.ImagePickerActivity com.baidu.sapi2.ui.activity.ImageCropActivity com.baidu.sapi2.ui.activity.ImageRecommendActivity com.baidu.sapi2.ui.activity.UserProfileActivity com.baidu.sapi2.ui.activity.SmsLoginActivity ...
07-30 10:35:18.870555  1646  1825 D PackageManager:   Permissions: baidu.push.permission.WRITE_PUSHINFOPROVIDER.com.baidu.BaiduMap com.baidu.BaiduMap.CALL_MAIN_PROCESS_RECEIVER com.baidu.BaiduMap.permission.MIPUSH_RECEIVE com.baidu.BaiduMap.permission.SANDBOX_PERMISSION

Ⅴ.為該apk準備data的資料夾

07-30 10:35:31.348520  1646  1825 V PackageManager: prepareAppData for com.baidu.BaiduMap u0 0x3

  檢視data/data下的生成了使用者資料的資料夾:




Ⅵ.安裝完成執行post-install結束

07-30 10:35:31.453696  1646  1825 V PackageManager: No restore -