天天看點

Android 9.0 SystemUI Notification

本文主要分享 systemui notification 具體如何呈現的?基于 aosp 9.0 分析。

Android 9.0 SystemUI Notification

在《android 9.0 systemui 主要視圖 systembars》知道通知在折疊時狀态欄、下拉狀态欄、鎖屏都有通知,其中鎖屏和下拉狀态欄是一個布局,折疊狀态欄 是在 <code>collapsedstatusbarfragment,status_bar.xml,phonestatusbarview</code>,鎖屏是 <code>notificationstackscrolllayout,@+id/notification_stack_scroller</code>,先來看看鎖屏的通知,notificationstackscrolllayout 是 viewgroup,如果來了條通知,肯定是有地方進行 addview,我們就沿着這個思路去 aosp 尋找答案。

Android 9.0 SystemUI Notification

序列圖為來通知到 systemui 鎖屏通知呈現整個流程。

鎖屏是 notificationstackscrolllayout,直接找 notificationstackscrolllayout,看到有個 addcontainerview方法,一看,果然是目标 addview:

反查,看到  addcontainerview 被 notificationviewhierarchymanager#updatenotificationviews 方法調用了。

這裡 mlistcontainer 是 notificationlistcontainer,notificationstackscrolllayout#addcontainerview 進行了重寫。

反查, notificationviewhierarchymanager#updatenotificationviews 被 statusbar#updatenotificationviews 方法調用了。

statusbar#updatenotificationviews 被 notificationentrymanager#updatenotifications 調用了。

presenter 是 notificationpresenter 對象,從 statusbar#makestatusbarview 傳過來了,繼續看 notificationentrymanager#updatenotifications 哪裡被調用了,是 notificationentrymanager#addnotificationviews。

notificationentrymanager#addentry 由 notificationentrymanager#onasyncinflationfinished 調用了。

問題來了,notificationentrymanager#onasyncinflationfinished 哪裡被調到了,似乎斷掉了,是怎麼和來通知關聯起來的?這得需要看看通知的流程。

這部分分析按照正常的調用順序來分析。

notificationmanager 調用 notify 方法發送 notification,最後調用到 notifyasuser() 方法:

這裡 service 是 inotificationmanager,對應的是 notificationmanagerservice,看 notificationmanagerservice#enqueuenotificationwithtag,又調用了 notificationmanagerservice#enqueuenotificationinternal。

mlisteners 是 notificationlisteners,調用 notificationmanagerservice#notifypostedlocked。

這裡 service 是 inotificationlistener,對應的是 notificationlistenerwrapper,看 notificationlistenerwrapper#onnotificationposted。

看 myhandler 進行中的 msg_on_notification_posted。

notificationlistenerservice 是抽象類,notificationlistenerservice#onnotificationposted 在 notificationlistener##onnotificationposted 有重寫。

調用了 notificationentrymanager#addnotification。

從 notificationentrymanager#addnotification 到 notificationentrymanager#addnotificationinternal 再到 notificationentrymanager#inflateviews 方法。

再看 rowinflatertask#oninflatefinished:

看 notificationentrymanager#row 會調用 bindrow 和 updatenotification,看 updatenotification方法最終會調用 expandablenotificationrow#updatenotification。

繼續跟,到 notificationinflater#inflatenotificationviews。

看 asyncinflationtask 執行的結果:

調用 notificationinflater#apply,最終會到 notificationinflater#applyremoteview

繼續看 notificationinflater#finishifdone,這個方法看到最後的<code>endlistener.onasyncinflationfinished(row.getentry());</code> 實作方法在 notificationentrymanager#onasyncinflationfinished。

這裡的 addentry 方法調用了addnotificationviews,好了,終于和 systemui 的通知關聯起來了,這樣,鎖屏來通知分析結束。

Android 9.0 SystemUI Notification

有了以上鎖屏通知分析,再來分析折疊狀态欄通知就簡單很多了,先看來折疊狀态欄初始化部分。

折疊狀态欄對應的布局檔案是 status_bar.xml:

如果來通知,就在 notification_icon_area 進行 addview 填充。再看看代碼初始化。

看到這裡的<code>notificationiconarea.addview(mnotificationiconareainner);</code> ,notificationiconarea 被 mnotificationiconareainner 填充,是以我們要重點關注 notificationiconareacontroller 什麼時候被填充。

有以上鎖屏通知分析知道有通知來最後會調用 statusbar#updatenotificationviews。

調用 notificationiconareacontroller#updatenotificationicons。

ok,折疊狀态欄通知分析結束。

本篇梳理了 systemui notification 大緻流程,分為鎖屏的通知和狀态欄通知,代碼很多,細節沒有去糾結,省略了很多代碼,有興趣,可以自己去 aosp 檢視。