Android程序包管理(2)--使用adb install執行安裝過程

2、程序安裝過程
1.使用adb install執行安裝過程
使用adb install執行安裝過程總體流程圖以下:shell

1、使用adb install命令安裝apkapp

1.adb指令對應源文件system/core/adb/commandline.c。異步

2.指令參數解析:根據傳入參數install判斷是安裝指令,直接調用到install_app();函數

3.執行文件拷貝:在install_app()中:ui

首先定義兩個拷貝位置:分別對應拷貝到內部或者外部存儲。這裏須要根據傳入參數肯定拷貝位置。默認是拷貝到內部存儲中。this

執行拷貝:將制定的apk文件從電腦端拷貝到制定的目錄處。.net

執行安裝:調用pm_command()函數開始去安裝。code

刪除文件:當安裝結束時刪除該apk文件。server

4.開始去安裝:在pm_command()中:對象

構造shell指令:將參數憑藉成爲shell指令。

去執行shell:使用send_shellcommand()去執行pm腳本,使用app_process運行pm.jar。

2、跨進程去執行安裝

1.執行前準備:

獲取Binder:首先獲取PKMS對應的Binde對象。

解析傳入參數:判斷是install指令肯定是安裝指令。調用runinstall()。

2.準備跨進程安裝:在runinstall()中:

解析參數:while循環依次解析參數肯定installFlags,接着獲取apk文件路徑構造apkURI經過它讀取文件。

跨進程調用:首先新建PackageInstallObserver回調接收PKMS安裝結果,而後使用mPm.installPackageWithVerificationAndEncryption()跨進程調用到PKMS該函數執行。

等待安裝結果:循環判斷PackageInstallObserver.finished狀態,等待安裝結果根據結果提示用戶信息。

3、PKMS執行具體安裝

1.執行安裝準備工做:在installPackageWithVerificationAndEncryption()中:

檢查權限:首先檢查調用者進程是否存在安裝應用的權限。

獲取uid,設置filteredFlags:獲取調用者uid根據uid作後續判斷。若是uid是SHELL_UID爲filteredFlags設置INSTALL_FROM_ADB表示不然取消該表示,這裏是須要設置該標識。

發生異步消息:獲取INIT_COPY標識的Message對象,設置obj爲新建對象InstallParams,該對象分裝了安裝須要的參數及信息。而後發送該Message。

InstallParams類圖關係以下: 


2.執行異步消息:在PackageHandler中:

處理消息:異步消息都會調用doHandleMessage()處理具體邏輯。

判斷在INIT_COPY標識下:

首先獲取安裝請求對象:obj即HandlerParams的子類InstallParams。

判斷是否啓動服務:mBound表示是否啓動DefaultContainerService服務,該服務由DefaultContainerService.apk提供,主要做用是拷貝文件到應用程序目錄。若是已啓動則將該安裝請求對象添加到隊列mPendingInstalls中該隊列若是爲空則發生消息MCS_BOUND執行安裝。若是未啓動調用connectToService()啓動該服務。

判斷在MCS_BOUND標識下:該標識在DefaultContainerService啓動成功後也會回調。

獲取mContainerService對象:若是是DefaultContainerService啓動成功後的回調,直接獲取obj即爲該對象。判斷mContainerService是否爲空,若是爲空表明DefaultContainerService服務未啓動不能執行安裝操做,不爲空判斷若是mPendingInstalls隊列存在請求則開始執行。

獲取安裝請求:使用mPendingInstalls.get(0)獲取一個待安裝請求HandlerParams。

執行安裝請求:調用該HandlerParams.startCopy()函數,判斷函數返回結果,返回爲true表明處理成功。

請求處理成功:請求處理成功時,首先從mPendingInstalls隊列中移除該請求,若是mPendingInstalls隊列此時大小爲0表明全部請求已完成則回調MCS_UNBIND斷開服務。若是還存在請求則繼續回調MCS_BOUND消息執行安裝請求。

3.執行安裝請求邏輯:HandlerParams.startCopy()中:

嘗試次數判斷:安裝請求執行失敗後有重試機制。判斷mRetries是否大於最大嘗試次數,超過最大次數發生異步消息MCS_GIVE_UP放棄執行返回false。未超過則執行安裝行爲。

執行拷貝操做:調用handleStartCopy()執行拷貝請求,具體是實如今InstallParams中。

執行安裝操做:調用handleReturnCode()執行安裝請求,具體是實如今InstallParams中。

4.執行apk的拷貝:在HandlerParams.handleStartCopy()中:

獲取指定的安裝位置:首先從flags中獲取指定的安裝位置,這裏的flags來自於以前解析參數傳入的filteredFlags。判斷若是同時指定既在sd卡安裝又在內部存儲安裝則賦值ret安裝失敗。

獲取手機存儲情況:經過dsm服務調用getMemoryLowThreshold()獲取當前內部存儲最小余量。小於這個值就是空間不足。

授予apk讀取權限:授予DefContainerService URI讀權限,使其能夠執行apk的拷貝操做。

獲取PackageInfoLite對象並判斷:首先獲取待安裝apk的packageFile對象,根據該對象調用mContainerService.getMinimalPackageInfo()獲取其對應的PackageInfoLite對象,該對象描述apk的包名、版本、推薦安裝位置、簽名等信息。而後判斷該apk的安裝推薦位置是RECOMMEND_FAILED_INSUFFICIENT_STORAGE表明當前存儲空間不足須要釋放空間,計算該apk安裝須要的空間而後使用mInstaller.freeCache()釋放空間,以後在嘗試獲取一次PackageInfoLite對象。

撤銷apk讀取權限:撤銷對uri的讀取權限mContext.revokeUriPermission()。

肯定最終安裝的位置:根據pkgLite.recommendedInstallLocation肯定ret值,而且最終肯定安裝位置sd卡或者是內部存儲,並設置flags值。

新建安裝參數對象InstallArgs:調用createInstallArgs(this)建立一個安裝參數對象,根據flag對安裝位置區別處理。這裏若是是安裝在sd卡上返回AsecInstallArgs對象,反之是FileInstallArgs對象。它們都繼承自InstallArgs。注意這裏構造的時候傳入的是當前的安裝請求對象HandlerParams,該對象分裝了此次請求須要的全部信息參數。

判斷一系列驗證檢查:若是設置了包驗證開啓,則收集信息發送廣播給包校驗器檢查,檢查經過才能接着進行安裝。若是未設置則直接調用安裝參數對象InstallArgs.copyApk()執行拷貝apk。

5.具體開始執行apk的拷貝操做:在InstallArgs.copyApk()中,假設安裝位置在內部存儲則該方法具體實如今FileInstallArgs中:

判斷temp:temp表明拷貝到/data/app下的文件名是否須要隨機,這裏咱們傳入的true是要隨機,由於若是不隨機以apk結尾,PKMS會監聽到該文件以後直接執行安裝操做,咱們不須要直接進行該安裝操做,因此設置隨機名。

執行apk拷貝操做:首先獲取建立apk對應File對象codeFile,爲DCM服務受權讀取權限。接着使用imcs.copyResource()拷貝資源到codeFile文件。同時爲該apk建立native目錄而且拷貝native庫到該位置。最後返回安裝結果ret。

至此安裝操做完成HandlerParams.handleStartCopy()執行完畢賦值安裝結果給mRet變量。

6.拷貝完成執行安裝操做:在HandlerParams.handleReturnCode()中:

判斷安裝參數對象InstallArgs:首先判斷InstallArgs對象若是不爲null則開始執行安裝流程,調用processPendingInstall()。安裝結束以後刪除臨時文件,若是未開啓包驗證則該文件不存在不須要刪除。

執行安裝操做:使用Hanlder發佈異步任務,新建安裝結果對象PackageInstalledInfo,接着調用installPackageLI()執行安裝操做,傳入安裝參數對象InstallArgs及PackageInstalledInfo獲取安裝結果。安裝完成以後新建對象PostInstallData分裝InstallArgs及PackageInstalledInfo而後放入mRunningInstalls這個map中,新建一個token爲索引。最後發生一個異步消息POST_INSTALL並攜帶索引token,通知安裝結果。

7.安裝完成執行通知操做:在PackageHandler中:

判斷在POST_INSTALL標識下:

獲取安裝結果對象:在mRunningInstalls中根據token獲取安裝結果PostInstallData。若是存在則分別取出對應的InstallArgs和PackageInstalledInfo。

處理安裝成功狀況:判斷PackageInstalledInfo.returnCode是安裝成功,首先發送安裝成功廣播ACTION_PACKAGE_ADDED,若是是應用更新操做還要發送ACTION_PACKAGE_REPLACED廣播。而後進行資源清理,接着取出InstallArgs.observer不爲空表明存在安裝結果回調對象,則回調其對應結果。

至此adb install安裝程序流程完成。

簡單總結流程:

將電腦端apk資源拷貝到制定的臨時文件夾下。

將apk拷貝到/data/app目錄下,可是文件名須要隨機處理。

調用PKMS函數執行apk安裝。

相關文章
相關標籤/搜索