APK 安裝過程 及 原理 詳解
APK為AndroidPackage的縮寫
Android應用安裝有如下四種方式:
1.系統應用安裝――開機時完成,沒有安裝介面
2.網路下載應用安裝――通過market應用完成,沒有安裝介面
3.ADB工具安裝――沒有安裝介面。
4.第三方應用安裝――通過SD卡里的APK檔案安裝,有安裝介面,由 packageinstaller.apk 應用處理安裝及解除安裝。
-------------------------------------應用安裝涉及到如下幾個目錄:
system/app ---------------系統自帶的應用程式,獲得adb root許可權才能刪除
data/app ---------------使用者程式安裝的目錄。使用者 安裝時把apk檔案 複製 到此目錄
data/data ---------------存放應用程式的資料
data/dalvik-cache--------將apk中的dex檔案安裝到dalvik-cache目錄下(dex檔案是dalvik虛擬機器的可執行檔案,其大小約為原始apk檔案大小的四分之一)
安裝過程:
複製APK安裝包到data/app目錄下,解壓並掃描安裝包,把dex檔案(Dalvik位元組碼)儲存到dalvik-cache目錄,並data/data目錄下建立對應的應用資料目錄。
解除安裝過程:
刪除 安裝過程中在上述三個目錄下建立的檔案及目錄。
-------------------------
安裝應用的過程解析
一.開機安裝
PackageManagerService處理各種 應用的安裝,解除安裝,管理等工作,開機時 由systemServer啟動此服務
(原始檔路徑:android\frameworks\base\services\java\com\android\server\PackageManagerService.java)
PackageManagerService服務 啟動的流程:
1.首先 掃描安裝“system\framework”
<p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="com">// Find base frameworks (resource packages without code).</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mFrameworkInstallObserver = new AppDirObserver(</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mFrameworkDir.getPath(), OBSERVER_EVENTS, true);</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mFrameworkInstallObserver.startWatching();</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> | PackageParser.PARSE_IS_SYSTEM_DIR,</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> scanMode | SCAN_NO_DEX, 0);</span></span></p>
2.掃描 安裝系統system/app的應用程式
<p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="com">// Collect all system packages.</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mSystemAppDir = new File(Environment.getRootDirectory(), "app");</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mSystemInstallObserver = new AppDirObserver(</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mSystemAppDir.getPath(), OBSERVER_EVENTS, true);</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mSystemInstallObserver.startWatching();</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);</span></span></p>
3.製造商的目錄下/vendor/app應用包
<p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="com">// Collect all vendor packages.</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mVendorAppDir = new File("/vendor/app");</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mVendorInstallObserver = new AppDirObserver(</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mVendorAppDir.getPath(), OBSERVER_EVENTS, true);</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mVendorInstallObserver.startWatching();</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);</span></span></p>
4.掃描“data\app”目錄,即使用者安裝的第三方應用
<p><strong>scanDirLI</strong><span class="pun">(</span><span class="pln">mAppInstallDir</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> scanMode</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span></p>
5.掃描" data\app-private"目錄,即安裝DRM保護的APK檔案(一個受保護的歌曲或受保 護的視訊是使用 DRM 保護的檔案)
<p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span class="pln">scanDirLI</span><span class="pun">(</span><span class="pln">mDrmAppPrivateInstallDir</span><span class="pun">,</span><span class="pln"> </span><span class="typ">PackageParser</span><span class="pun">.</span><span class="pln">PARSE_FORWARD_LOCK</span><span class="pun">,</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span class="pln"> scanMode</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span></span></p>
掃描方法的程式碼清單
<p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="kwd">private</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> scanDirLI</span><span class="pun">(</span><span class="typ">File</span><span class="pln"> dir</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> flags</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> scanMode</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> currentTime</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="typ">String</span><span class="pun">[]</span><span class="pln"> files </span><span class="pun">=</span><span class="pln"> dir</span><span class="pun">.</span><span class="pln">list</span><span class="pun">();</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">files </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="typ">Log</span><span class="pun">.</span><span class="pln">d</span><span class="pun">(</span><span class="pln">TAG</span><span class="pun">,</span><span class="pln"> </span><span class="str">"No files in app dir "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> dir</span><span class="pun">);</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">return</span><span class="pun">;</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="pun">}</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="typ">Log</span><span class="pun">.</span><span class="pln">d</span><span class="pun">(</span><span class="pln">TAG</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Scanning app dir "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> dir</span><span class="pun">);</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="pun">}</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">int</span><span class="pln"> i</span><span class="pun">;</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i</span><span class="pun">=</span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i</span><span class="pun"><</span><span class="pln">files</span><span class="pun">.</span><span class="pln">length</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="typ">File</span><span class="pln"> file </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">File</span><span class="pun">(</span><span class="pln">dir</span><span class="pun">,</span><span class="pln"> files</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]);</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">isPackageFilename</span><span class="pun">(</span><span class="pln">files</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]))</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="com">// Ignore entries which are not apk's</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> continue;</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> PackageParser.Package pkg =<strong> scanPackageLI</strong>(file,</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // Don't mess around with apps in system partition.</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // Delete the apk</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> Slog.w(TAG, "Cleaning up failed install of " + file);</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> file.delete();</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p>
並且從該掃描方法中可以看出呼叫了scanPackageLI()
private PackageParser.Package scanPackageLI(File scanFile,
int parseFlags, int scanMode, long currentTime)
跟蹤scanPackageLI()方法後發現,程式經過很多次的if else 的篩選,最後判定 可以安裝apk後,呼叫了 mInstaller.install
<p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">mInstaller </span><span class="pun">!=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">int</span><span class="pln"> ret </span><span class="pun">=</span><span class="pln"> <strong>mInstaller</strong></span><strong><span class="pun">.</span><span class="pln">install</span></strong><span class="pun">(</span><span class="pln">pkgName</span><span class="pun">,</span><span class="pln"> useEncryptedFSDir</span><span class="pun">,</span><span class="pln"> pkg</span><span class="pun">.</span><span class="pln">applicationInfo</span><span class="pun">.</span><span class="pln">uid</span><span class="pun">,</span><span class="pln">pkg</span><span class="pun">.</span><span class="pln">applicationInfo</span><span class="pun">.</span><span class="pln">uid</span><span class="pun">);</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">ret </span><span class="pun"><</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="com">// Error from installer</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> return null;</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p>
mInstaller.install() 通過
LocalSocketAddress address = new LocalSocketAddress(
"installd", LocalSocketAddress.Namespace.RESERVED);
指揮installd在C語言的檔案中完成工作
PackageManagerService小節 :
1)從apk, xml中載入pacakge資訊, 儲存到內部成員變數中, 用於後面的查詢. 關鍵的方法是scanPackageLI().
2)各種查詢操作, 包括query Intent操作.
3)install package和delete package的操作. 還有後面的關鍵方法是installPackageLI().
二、從網路上下載應用:
下載完成後,會自動呼叫Packagemanager的安裝方法installPackage()
/* Called when a downloaded package installation has been confirmed by the user */
由英文註釋可見PackageManagerService 類的installPackage()函式為 安裝程式 的入口。
<p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> installPackage</span><span class="pun">(</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">final</span><span class="pln"> </span><span class="typ">Uri</span><span class="pln"> packageURI</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">final</span><span class="pln"> </span><span class="typ">IPackageInstallObserver</span><span class="pln"> observer</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">final</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> flags</span><span class="pun">,</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">final</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> installerPackageName</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> mContext</span><span class="pun">.</span><span class="pln">enforceCallingOrSelfPermission</span><span class="pun">(</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> android</span><span class="pun">.</span><span class="typ">Manifest</span><span class="pun">.</span><span class="pln">permission</span><span class="pun">.</span><span class="pln">INSTALL_PACKAGES</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">);</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="typ">Message</span><span class="pln"> msg </span><span class="pun">=</span><span class="pln"> mHandler</span><span class="pun">.</span><span class="pln">obtainMessage</span><span class="pun">(</span><span class="pln">INIT_COPY</span><span class="pun">);</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> msg</span><span class="pun">.</span><span class="pln">obj </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">InstallParams</span><span class="pun">(</span><span class="pln">packageURI</span><span class="pun">,</span><span class="pln"> observer</span><span class="pun">,</span><span class="pln"> flags</span><span class="pun">,</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> installerPackageName</span><span class="pun">);</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> <strong>mHandler</strong></span><strong><span class="pun">.</span><span class="pln">sendMessage</span></strong><span class="pun">(</span><span class="pln">msg</span><span class="pun">);</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="pun">}</span></span></span></p>
其中是通過PackageHandler的例項mhandler.sendMessage(msg)把資訊發給繼承Handler的類HandleMessage()方法
<p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="kwd">class</span><span class="pln"> </span><span class="typ">PackageHandler</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Handler</span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> </span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;">*****************省略若干********************</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> handleMessage</span><span class="pun">(</span><span class="typ">Message</span><span class="pln"> msg</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> doHandleMessage</span><span class="pun">(</span><span class="pln">msg</span><span class="pun">);</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">finally</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="typ">Process</span><span class="pun">.</span><span class="pln">setThreadPriority</span><span class="pun">(</span><span class="typ">Process</span><span class="pun">.</span><span class="pln">THREAD_PRIORITY_BACKGROUND</span><span class="pun">);</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="pun">}</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="pun">}</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="pun">******************省略若干**********************</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="pun">}</span></span></span></p>
把資訊發給doHandleMessage()方法,方法中用switch()語句進行判定傳來Message
<p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">void</span><span class="pln"> doHandleMessage</span><span class="pun">(</span><span class="typ">Message</span><span class="pln"> msg</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">msg</span><span class="pun">.</span><span class="pln">what</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> </span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">case</span><span class="pln"> INIT_COPY</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">DEBUG_SD_INSTALL</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Log</span><span class="pun">.</span><span class="pln">i</span><span class="pun">(</span><span class="pln">TAG</span><span class="pun">,</span><span class="pln"> </span><span class="str">"init_copy"</span><span class="pun">);</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="typ">HandlerParams</span><span class="pln"> </span><span class="kwd">params</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">HandlerParams</span><span class="pun">)</span><span class="pln"> msg</span><span class="pun">.</span><span class="pln">obj</span><span class="pun">;</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">int</span><span class="pln"> idx </span><span class="pun">=</span><span class="pln"> mPendingInstalls</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">DEBUG_SD_INSTALL</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Log</span><span class="pun">.</span><span class="pln">i</span><span class="pun">(</span><span class="pln">TAG</span><span class="pun">,</span><span class="pln"> </span><span class="str">"idx="</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> idx</span><span class="pun">);</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="com">// If a bind was already initiated we dont really</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // need to do anything. The pending install</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // will be processed later on.</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> if (!mBound) {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // If this is the only one pending we might</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // have to bind to the service again.</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> if (!connectToService()) {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> Slog.e(TAG, "Failed to bind to media container service");</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> params.serviceError();</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> return;</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> } else {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // Once we bind to the service, the first</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // pending request will be processed.</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mPendingInstalls.add(idx, params);</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> } else {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mPendingInstalls.add(idx, params);</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // Already bound to the service. Just make</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // sure we trigger off processing the first request.</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> if (idx == 0) {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mHandler.sendEmptyMessage(MCS_BOUND);</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> break;</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> case MCS_BOUND: {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_bound");</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> if (msg.obj != null) {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mContainerService = (IMediaContainerService) msg.obj;</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> if (mContainerService == null) {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // Something seriously wrong. Bail out</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> Slog.e(TAG, "Cannot bind to media container service");</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> for (HandlerParams params : mPendingInstalls) {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mPendingInstalls.remove(0);</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // Indicate service bind error</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> params.serviceError();</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> mPendingInstalls.clear();</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> } else if (mPendingInstalls.size() > 0) {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> HandlerParams params = mPendingInstalls.get(0);</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> if (params != null) {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> params.startCopy();</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> } else {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // Should never happen ideally.</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> Slog.w(TAG, "Empty queue");</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> break;</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> ****************省略若干**********************</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;">}</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;">} </span></span></p>
public final boolean sendMessage (Message msg)
public final boolean sendEmptyMessage (int what)
兩者引數有別。
然後呼叫抽象類HandlerParams中的一個startCopy()方法
abstract class HandlerParams {
final void startCopy() {
***************若干if語句判定否這打回handler訊息*******
handleReturnCode();
}
}
handleReturnCode()複寫了兩次其中有一次是刪除時要呼叫的,只列出安裝呼叫的一個方法
<p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="lit">@Override</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="kwd">void</span><span class="pln"> handleReturnCode</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"><span class="pln"> </span><span class="com">// If mArgs is null, then MCS couldn't be reached. When it</span></span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // reconnects, it will try again to install. At that point, this</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> // will succeed.</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> if (mArgs != null) {</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> processPendingInstall(mArgs, mRet);</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p><p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="font-size: 15px; line-height: 24px;"> }</span></span></p>
這時可以清楚的看見 processPendingInstall()被呼叫。
其中run()方法如下
<p style="margin-bottom: 0.21cm;"><span style="font-family: Arial;"><span style="fo
相關推薦
APK 安裝過程 及 原理 詳解
APK為AndroidPackage的縮寫 Android應用安裝有如下四種方式: 1.系統應用安裝――開機時完成,沒有安裝介面 2.網路下載應用安裝――通過market應用完成,沒有安裝介面 3.ADB工具安裝――沒有安裝介面。 4.第
Android中APK安裝過程及原理解析
應用安裝是智慧機的主要特點,即使用者可以把各種應用(如遊戲等)安裝到手機上,並可以對其進行解除安裝等管理操作。APK是Android Package的縮寫,即Android安裝包。APK是類似Symbian Sis或Sisx的檔案格式。通過將APK檔案直接傳到Android模擬器或Android手機中執行即可
常用 JavaScript 小技巧及原理詳解
this lin slice pen global 轉化 script lis fun 善於利用JS中的小知識的利用,可以很簡潔的編寫代碼 1. 使用!!模擬Boolean()函數 原理:邏輯非操作一個數據對象時,會先將數據對象轉換為布爾值,然後取反,兩個!!重復取反,就實
Intellij IDEA 安裝 lombok及使用詳解
junit equal 排查 code 數據 undefine img get 導致 在項目開發中會經常使用到bean,entity等類,絕大部分數據類中都需要get、set、toString、equals和hashCode方法,雖然eclipse和idea開發環境下都
Docker的安裝配置及使用詳解
yum ava 數據 進入容器 article symbol tracking 支付 資源 Docker的安裝配置及使用詳解 基本概念 Dock
Tomcat 端口配置,及原理詳解
request對象 dir 創建 分享圖片 編譯 sel tor 客戶 ces Tomcat 端口配置,及原理詳解 作者:Ezitai 如果想深入了解tomcat的各個端口及
Linux安裝vsftpd及配置詳解
技術 第一個 config vpd b2c 大端 工具 端口修改 系統 1 安裝vsftpd組件 安裝完後,有/etc/vsftpd/vsftpd.conf 文件,是vsftp的配置文件。[root@bogon ~]# yum -y install vsftpd 2、FTP
Intellij IDEA 安裝lombok及使用詳解
name equal logging for 自動 pack filesize 環境 1.3 項目中經常使用bean,entity等類,絕大部分數據類類中都需要get、set、toString、equals和hashCode方法,雖然eclipse和idea開發環境下都有自
Mysql中MVCC的使用及原理詳解
準備 測試環境:Mysql 5.7.20-log 資料庫預設隔離級別:RR(Repeatable Read,可重複讀),MVCC主要適用於Mysql的RC,RR隔離級別 建立一張儲存引擎為testmvcc的表,sql為: CREATE TABLE testmvcc ( id int
快速安裝Nginx及配置詳解(未完待續)
導讀: Nginx (engine x) 是一個高效能的HTTP和反向代理伺服器,也是一個IMAP/POP3/SMTP伺服器,從2007年被德國人開發出來後可以說在市場的佔有率一路飆升,因為它支援高併發,而且還能阻止dos攻擊,它是當前較具影響力的一個http伺服器軟體,像百度等大廠都使用它,所以這是作為一
[媒體轉碼]視訊內容誰來保護?阿里雲視訊加密架構及原理詳解
視訊行業的從業者——尤其是線上教育、財經分析等重視內容版權的播放平臺都知道,視訊安全是一個非常重要的基礎需求。使用者通過一次付費行為,就可以拿到付費視訊的播放URL,將播放URL進行二次分發,這種行為叫做盜鏈;使用者直接將視訊下載到本地,然後再進行二次上傳分發,這種行為叫做盜播,這兩種行為都會給內容
Intellij IDEA 安裝lombok及使用詳解(轉載)
最近專案中用到了 IDEA 的 Lombok 外掛,這裡做一個記錄。 Lombok 官方說明文件:http://plugins.jetbrains.com/plugin/6317-lombok-plugin 轉載原文地址:
Java類載入過程及static詳解
類從被載入到JVM中開始,到解除安裝為止,整個生命週期包括:載入、驗證、準備、解析、初始化、使用和解除安裝七個階段。 其中類載入過程包括載入、驗證、準備、解析和初始化五個階段。 類載入器的任務就是根據一個類的全限定名來讀取此類的二進位制位元組流到JVM中,然後轉換為一個與目
Linux 下Redis叢集安裝部署及使用詳解
一、應用場景介紹 本文主要是介紹Redis叢集在Linux環境下的安裝講解,其中主要包括在聯網的Linux環境和離線的Linux環境下是如何安裝的。因為大多數時候,公司的生產環境是在內網環境下,無外網,伺服器處於離線狀態(最近公司要上線專案,就是無外網環境的Linu
Nginx與PHP(php-fpm)工作機制及原理詳解
一、代理與反向代理 現實生活中的例子 1、正向代理:訪問google.com 如上圖,因為目前google已被和諧,我們需要vpn才能科學訪問google.com。 vpn對於“我們”來說,是可以感知到的(我們連線vpn)vpn對於”google伺服器”來說,是不可感知的(
CentOS7下的軟體安裝方法及策略詳解
使用了四年的 Linux,前三年都是在瞎折騰,浪費了不少時間,也得到了不少經驗與教訓。 現在可能是真的老了,已經不願意折騰了,只希望配置好一個系統之後,就一直使用下去。為什麼要寫/讀這一篇 使用 Linux 尤其是 CentOS 會遇到一些坑,或是一些有潔癖的人不能忍的事情:官方源中的軟體包版本太老,在功能上
CentOS系統下docker的安裝配置及使用詳解
http://www.server110.com/docker/201411/11105.html 1 docker簡介 Docker 提供了一個可以執行你的應用程式的封套(envelope),或者說容器。它原本是 dotCloud 啟動的一個業餘專案,並在前些時候開
Linux 下Redis叢集安裝部署及使用詳解(線上和離線兩種安裝+相關錯誤解決方案)
一、應用場景介紹 本文主要是介紹Redis叢集在Linux環境下的安裝講解,其中主要包括在聯網的Linux環境和離線的Linux環境下是如何安裝的。因為大多數時候,公司的生產環境是在內網環境下,無外網,伺服器處於離線狀態(最近公司要上線專案,就是無外網環境的Linux,被離線安裝坑慘了,走了很多彎路,說多
iOS最新Mac OS X 10.11之後 安裝cocoapods及使用詳解
iOS 最新版 CocoaPods 的安裝流程 一、安裝方法: 1、移除現有Ruby預設源 gem sources --remove https://rubygems.org/ 為了提高安裝的成功機率,大家可以多移除幾個源。 gem sources --remove https://rubygems.org
JS跨域(ajax跨域、iframe跨域)解決方法及原理詳解
js跨域是指通過js在不同的域之間進行資料傳輸或通訊,比如用ajax向一個不同的域請求資料,或者通過js獲取頁面中不同域的框架中(iframe)的資料。只要協議、域名、埠有任何一個不同,都被當作是不同的域。 要解決跨域的問題,我們可以使用以下幾種方法: 1、