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安裝。