Android隨筆隨想-GUI-事件分發先導篇

Android隨筆隨想-GUI-事件分發先導篇

爲了瞭解Android的事件分發,我們先需要了解一下GUI的上下文涉及的內容,這篇只是做簡單的介紹,在分析完事件後,會詳細的分析總結這些內容

基於Android 2.3源碼的分析總結

1. GUI系統結構圖

GUI其實是爲了做了幾件事情:

  1. 將Android進行繪製
  2. 對於用戶的按鍵操作,觸摸操作進行響應,並且交給對應的內容進行處理

是否還有其他???

涉及到的相關內容

  • Ams(ActivityManagerService(以下簡稱Ams))
  • Wms(WindowManagerService(以下簡稱Wms))
  • SurfaceFlinger

因爲需要找到一個突破口,如果但從SurfaceFlinger或者Wms入口的話,很難看到具體的調用的地方,於是還是從Ams入手是最好的

  1. 能夠知道整體的流轉,整體的數據和邏輯控制的序列
  2. 因爲Ams是與開發者,直接能夠接觸和使用的,瞭解了之後會更加輕車熟路的來了解其他

GUI系統結構圖

GUI系統結構圖

2. Ams的介紹

2.1 Ams是什麼

Ams: ActivityManagerService, 這個名字感覺還是不夠明確的,這個並不單單做這個事情,ActivityManagerService 是作爲server端,管理系統中的四大組件的

  • Activity
  • Service
  • BroadcastReceiver
  • ContentProvider

2.2 Ams用來做什麼用

控制管理四大基本組件

2.3 Ams的相關圖示

2.3.1 Ams相關類圖

Ams相關類圖

這裏也只是將Activity相關的部分,進行了一些類圖的彙總

總結如下:

Client

  1. Activity通過Instrumentation來調用服務端的Ams相關動作,比如說我們常見的從Launcher啓動一個應用,Activity來啓動另外一個Activity,Instrumentation起到了和Ams通訊的中間橋樑
  2. Instrumentation在和Ams進行主動通訊時,是跨進程的,跨進程通訊使用的是IPC,而IPC的套路是,Client和Server共同實現相同的接口,然後通過Binder來調用,這裏也是符合Android自己定義的Binder的流程的

    • Instrumentation使用的是ActivityManagerNative.gDefault(),通過查看源碼得知,這裏使用的是一個Ams的代理: ActivityManagerProxy, 在調用ActivityManagerProxy的方法時,便是通過Binder來調用ActivityManagerService

Server

  1. ActivityManagerService在收到了客戶端的請求操作後,會做一些邏輯的處理,以通過Launcher來啓動一個應用爲例

    • 會通知原來的Launcher的activity做對應狀態的更改,比如說,Activity應該做onPause,onStop的操作
    • 啓動一個新的進程,會調用ActivityThread的main()函數

Client

  1. ActivityThread在收到這個請求後,會做初始化,將初始化的ApplicationThread通知給Ams

Server

  1. Ams在收到這個請求後,會保存ApplicationThread的一個代理
  2. bind對應的application,即Application的初始化

    • 將Application初始化,由於已經建立了callback的通道,即ApplicationThreadProxy,便直接通過這個來通知Client進行啓動綁定
  3. 將要啓動的Activity來繼續操作,通過ApplicationThreadProxy通知啓動Activity,activity便進行了launch

  4. 端上在launch時,會通過Instrument來通知Activity進行attach,onCreate以及生命週期相關方法onStart(), onResume()的調用

2.3.2 內容總結

  1. Ams只是控制Activity的堆棧以及應用之間應該如何操作,自己並不做Activity的啓動以及銷燬等操作,因爲這個是具體應用來控制的,即Client的事情

  2. 數據的通道: 這個與我們常見寫的callback的方式其實沒有太大的差異,只不過涉及的類以及內容複雜了些,Activity通過Ams的proxy來請求服務端,我想做什麼,服務端在處理了之後,通過ApplicationThread的Proxy來通知端上,你應該做什麼.

2.3.3 相關資料

Ams相關講解

老羅的Android之旅 activity相關

2.4 隨想

2.4.1 360的DroidPlugin

DroidPlugin github地址

個人之前也在之前公司的app中集成過360的DroidPlugin,這個插件實現的挺巧妙的,而且各種hook,也看出了360的hook與hack的精神,插科打諢一下~

個人之前的DroidPluigin的隨筆,寫的很散,而且條理性不是很清晰,但是是個人學習的蹤跡,現在來看,還是別有一番趣味的

2.4.1.1 Ams超級簡化

在說360的這個插件框架之前,再來簡化的說一下Ams相關的流程圖

圖示如下:

Ams超級簡化圖

根據這個圖,我們再來梳理一下:

  1. Activity通過Instrumentation來向ActivityManager的Proxy來和ActivityManagerService來請求通訊,類似於request
  2. ActivityManagerService收到請求後,做出對應的響應,不同應用或者相同應用之間,進程,ActivityRecord,ProcessRecord等的控制,在處理完成後,通過客戶端給自己的ApplicationThread的代理,發送響應消息
  3. ApplicationThread將對應的響應在Handler中做順序排隊,然後取出給ActivityThread,ActivityThread再通過Instrumentation來和Activity來交互

這個圖只是以Activity的啓動爲例,其實Service,ContentProvider,BroadcastReceiver等組件均由ActivitiyManagerService來控制,Client均是通過ActivityManagerProxy來做這些請求操作,然後ActivityManagerService來通過ApplicationThreadProxy來通知客戶端應該做如何的響應的.

2.4.1.2 DroidPlugin的舉例分析

DroidPlugin的偷樑換柱

我們知道,Android的四大組件,除了廣播,其他的組件,Activity,Service,ContentProvider都是需要在資源清單文件中註冊的,那麼對於動態加載,肯定是這些資源清單文件中,沒有的這幾個組件,通過查看上節中的分析,得知這四大組件的通訊模型,是否能夠做些手腳,便可以實現這些,360的DroidPlugin便實現了這些.

上圖中,我已經標註了Client和Server的分界線,而且進出口都是明確的,進入ActivityManagerService的入口是ActivityManagerProxy,查看ActivityManagerProxy的源碼,看到了我們垂涎欲滴的方法,startActivity, startService,那麼更改下這個代理,把我們要啓動的Activity換位已有的Activity,這樣系統就認爲我們啓動的Activity是合法的了.參數如何處理呢?直接將參數以其他的方式存入到Intent中即可

這個只是啓動合法了,那麼Activity在通過ApplicationThreadProxy時通知我們啓動Activity時,這個Acitivy是我們欺騙系統用的Activity,這時,通過Instrumentation是要啓動我們想要的Activity的,那麼我們再將Instrumentation中的要啓動的Activity我們自己加載,便可以Activity的動態加載了.

如下圖:

偷樑換柱的DroidPlugin

2.4.2 設計模式

這個後續再分享吧,todo一下

2.4.3 程序設計時的邏輯流向要明確

其實包括我們接下來要說的View的事件分發,其實能看出來,單方向的數據流設計是最簡單的,而且是最不容易出問題的.

A 請求B,我要做什麼,B經過處理後,通知A,你可以做什麼,其實Ams的模型就是這個的複雜化.
A想要請求B,但是A摸不到B,A只能通過B的代理來請求B,B經過自己的N多處理流程,最終通過其他方式來通知A,你可以做什麼.
其實說白了,這個就是請求響應的複雜化,
A request B, B response A

我們最常見的寫代碼的邏輯,舉例如下:

A是UI的控件,B是處理邏輯的控制器,A點擊後,調用B的方法,告訴B我想做什麼
B在收到這個事件後,經過自己的處理邏輯,告訴A處理的結果.

以上內容部分參考老羅的android之旅以及柯元旦的源碼分析

相關圖位於個人的github

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章