close

這是 JsonChao 的第231期分享

此前我用較長的篇幅來介紹Android應用程序的啟動過程(根Activity的啟動過程),這一篇我們接着來分析Service的啟動過程。建議閱讀此篇文章前,請先閱讀Android深入四大組件(一)應用程序啟動過程這篇文章。

1.ContextImpl到ActivityManageService的調用過程

要啟動Service,我們會調用startService方法,它的實現在ContextWrapper中,代碼如下所示。frameworks/base/core/java/android/content/ContextWrapper.java在startService方法中會調用mBase的startService方法,Context類型的mBase對象具體指的是什麼呢?在Android深入四大組件(一)應用程序啟動過程這篇文章中我們講過ActivityThread啟動Activity時會調用如下代碼創建Activity的上下文環境。

frameworks/base/core/java/android/app/ActivityThread.java在注釋1處創建上下文對象appContext ,並傳入Activity的attach方法中,將Activity與上下文對象appContext 關聯起來,這個上下文對象appContext 的具體類型是什麼,我們接着查看createBaseContextForActivity方法,代碼如下所示。

frameworks/base/core/java/android/app/ActivityThread.java

這裡可以得出結論,上下文對象appContext 的具體類型就是ContextImpl 。Activity的attach方法中將ContextImpl賦值給ContextWrapper的成員變量mBase中,因此,mBase具體指向就是ContextImpl 。那麼,我們緊接着來查看ContextImpl的startService方法,代碼如下所示。frameworks/base/core/java/android/app/ContextImpl.java.java

startService方法中會return startServiceCommon方法,在startServiceCommon方法中會在注釋1處調用ActivityManageService(AMS)的代理對象ActivityManagerProxy(AMP)的startService方法,最終會調用AMS的startService方法。至於注釋1處的代碼為何會調用AMS的startService方法,在Android深入四大組件(一)應用程序啟動過程這篇文章中已經講過,這裡不再贅述。ContextImpl到ActivityManageService的調用過程如下面的時序圖所示。

2.ActivityThread啟動Service

我們接着來查看AMS的startService方法。frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java注釋1處調用mServices的startServiceLocked方法,mServices的類型是ActiveServices,ActiveServices的startServiceLocked方法代碼如下所示。

frameworks/base/services/core/java/com/android/server/am/ActiveServices.javastartServiceLocked方法的末尾return了startServiceInnerLocked方法,而startServiceInnerLocked方法中又調用了bringUpServiceLocked方法:

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java在注釋1處得到ServiceRecord的processName的值賦值給procName ,其中ServiceRecord用來描述Service的android:process屬性。注釋2處將procName和Service的uid傳入到AMS的getProcessRecordLocked方法中,來查詢是否存在一個與Service對應的ProcessRecord類型的對象app,ProcessRecord主要用來記錄運行的應用程序進程的信息。注釋5處判斷Service對應的app為null則說明用來運行Service的應用程序進程不存在,則調用注釋5處的AMS的startProcessLocked方法來創建對應的應用程序進程。注釋3處判斷如果用來運行Service的應用程序進程存在,則調用注釋4處的realStartServiceLocked方法:

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java在realStartServiceLocked方法中調用了app.thread的scheduleCreateService方法。其中app.thread是IApplicationThread類型的,它的實現是ActivityThread的內部類ApplicationThread,其中ApplicationThread繼承了ApplicationThreadNative,而ApplicationThreadNative繼承了Binder並實現了IApplicationThread接口。ApplicationThread的scheduleCreateService方法如下所示。

frameworks/base/core/java/android/app/ActivityThread.java首先將要啟動的信息封裝成CreateServiceData 對象並傳給sendMessage方法,sendMessage方法向H發送CREATE_SERVICE消息,H是ActivityThread的內部類並繼承Handler。這個過程和應用程序的啟動過程(根Activity啟動過程)是類似的。我們接着查看H的handleMessage方法。

frameworks/base/core/java/android/app/ActivityThread.javahandleMessage方法根據消息類型,調用了handleCreateService方法:

frameworks/base/core/java/android/app/ActivityThread.java注釋1處獲取要啟動Service的應用程序的LoadedApk,LoadedApk是一個APK文件的描述類。注釋2處通過調用LoadedApk的getClassLoader方法來獲取類加載器。接着在注釋3處根據CreateServiceData對象中存儲的Service信息,將Service加載到內存中。注釋4處創建Service的上下文環境ContextImpl對象。注釋5處通過Service的attach方法來初始化Service。注釋6處調用Service的onCreate方法,這樣Service就啟動了。在注釋7處將啟動的Service加入到ActivityThread的成員變量mServices中,其中mServices是ArrayMap類型。

最後給出ActivityThread啟動Service的時序圖。

END


往期推薦



國慶返工日,捲起來!

如何系統構建你的思維認知模型?

如何從零到一掌控習慣?

那兩年沉澱的時間增值心法

Android 技術面試如何做好準備?

歡迎關注我的微信:bcce5360,群人數已超200,無法掃碼入群,加我微信拉你進群。

點擊下方卡片關注JsonChao,為你構建一套

未來Android開發必備的知識體系


▲點擊上方卡片關注JsonChao,構建一套

未來Android開發必備的知識體系

歡迎把文章分享到朋友圈

很感謝您閱讀這篇文章,希望您能將它分享給您的朋友或技術群,這對我意義重大。

你若喜歡,為JsonChao點個在看哦

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()