Android分屏顯示總結

1. 基礎原理

1.1 ActivityRecord、TaskRecord、ActivityStack關系


一個ActivityRecord對應著一個Activity,而一個Activity可能對應著不同的ActivityRecord(因為Activity可能被實例化多次)。一系列的ActivityRecord存在于TaskRecord(一個Task就是用戶體驗上的一個“應用”,它將相關的Activity組合在一起,以ArrayList存儲),而一系列TaskRecord存在于ActivityStack。ActivityStackSupervisor是用來管理這些ActivityStack的。

ActivityRecord對應Activity的三種類型:
static final int APPLICATION_ACTIVITY_TYPE = 0;//普通應用類型
static final int HOME_ACTIVITY_TYPE = 1;//桌面類型
static final int RECENTS_ACTIVITY_TYPE = 2;//最近任務類型
ActivityStack有五種靜態棧:
0 HOME_STACK_ID //Home應用以及recents app所在的棧
1 FULLSCREEN_WORKSPACE_STACK_ID //一般應用所在的棧
2 FREEFORM_WORKSPACE_STACK_ID //類似桌面操作系統
3 DOCKED_STACK_ID //分屏的應用所在的棧
4 PINNED_STACK_ID //畫中畫棧

1.2 為什么要定義多個ActivityStack?

ActivityStack主要用于給TaskRecord的顯示類型分類。
在Android系統中,無論是普通的Activity窗口,還是特殊的輸入法窗口和壁紙窗口,它們都是被WindowManagerService服務組織在一個窗口堆棧中的,其中,Z軸位置較大的窗口排列在Z軸位置較小的窗口的上面。
通過ActivityStack中定義的棧類型,WMS可以方便的指定ActivityStack中各個Activity窗口顯示的z軸位置。比如ActivityStack為DOCKED_STACK_ID的一系列Activity窗口就要顯示在ActivityStack為FULLSCREEN_WORKSPACE_STACK_ID的所有Activity窗口之上。

1.3 Activity繪制

每一個Activity組件都有一個關聯的Window對象(PhoneWindow),用來描述一個應用程序窗口。每一個應用程序窗口內部又包含有一個View對象(DecorView),用來描述應用程序窗口的視圖。



控制Acivity的顯示,就是通過PhoneWindow控制顯示區域,通過DecorView控制顯示樣式和布局。

2. 原生分屏顯示功能

2.1 Recents中的任務管理

Recents界面結構

任務列表界面中的每一個任務對應一個TaskView,TaskView通過一個對應的Task類存儲Activity的包名類名等信息。

2.2 分屏操作流程

分屏操作流程

1,通過AMS將要分屏的TaskRecord放入DOCKED_STACK_ID所在的ActivityStack
2,計算分屏后窗口大小(首先以對半分的形式顯示)
3,要分屏的TaskRecord中的Activity重新啟動,并在WMS中根據新窗口大小進行繪制
4,將RecentActivity放入DOCKED_STACK_ID所在的ActivityStack并同樣根據新窗口進行繪制,顯示在另一半邊
5,繪制分割線DividerView。拖動分割線會重新計算窗口大小,釋放觸摸后重繪窗口

另外,分屏顯示流程中使用了EventBus進行消息傳遞。

2.3 EventBus

SystemUI的Recents相關代碼,使用EventBus進行消息傳遞。大致原理是首先向EventBus注冊回調,當通過EventBus傳遞消息時,會遍歷注冊的回調,通知所有符合的回調。
分屏主要使用了以下Event(基于android8.0源碼):
DragEndEvent消息,將一個TaskView分屏;
LaunchTaskEvent消息,在任務列表中打開應用;
UndockingTaskEvent消息,分屏分割線的拖動消息

3. SF的生產者消費者模型


SF的Client對象創建了一個圖元生產者,并且賦值給SurfaceControl中,SurfaceControl生產Surface對象。
Surface通過Binder和BufferQueue通信,申請buffer,往這個buffer中填入想要顯示的內容,再塞回BufferQueue,BufferQueue會通知SuefaceFlinger進行渲染顯示。

4.開機自動分屏的簡單實現

基本思想就是查找目標Activity的TaskView和Task,使用DragEndEvent消息模擬TaskView的拖動進行分屏,然后通過LaunchTaskEvent消息在另一個分屏區域打開目標應用。還可以通過自定義Event模擬分屏分割線的拖動,實現分屏比例修改。


參考:

Android7.1.1上下/左右分屏的策略分析
Android8.0多窗口調研
Android 重學系列 渲染圖層-圖元緩沖隊列初始化

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372