Composer HAL 中的熱插拔處理

顯示功能(例如顯示模式和支持的 HDR 類型)可以在具有外部連接顯示器(通過 HDMI 或 DisplayPort)的設備上動態更改,例如 Android 電視機頂盒 (STB) 和機頂盒 (OTT)設備。這種變化可能是 HDMI 熱插拔信號的結果,例如當用戶從一個顯示器切換到另一個顯示器或在沒有連接顯示器的情況下啟動設備時。從 Android 12 開始,在框架中進行了更改以處理熱插拔和動態顯示功能。

本頁介紹如何處理 Composer HAL 實現中的顯示熱插拔和顯示功能更改。此外,它還討論瞭如何管理相關的幀緩衝區並防止在這些情況下出現競爭條件。

更新顯示功能

本節介紹 Android 框架如何處理由 Composer HAL 發起的顯示功能更改。

在 Android 可以正確處理顯示功能的更改之前,OEM 必須實現 Composer HAL,以便它使用onHotplug(display, connection=CONNECTED)來通知框架顯示功能的任何更改。一旦實現,Android 會按如下方式處理對顯示功能的更改:

  1. 在檢測到顯示功能的變化時,框架會收到onHotplug(display, connection=CONNECTED)通知。
  2. 收到通知後,框架會刪除其顯示狀態,並通過使用getActiveConfiggetDisplayConfigsgetDisplayAttributegetColorModesgetHdrCapabilitiesgetDisplayCapabilities方法從 HAL 重新創建它。
  3. 一旦框架重新創建了新的顯示狀態,它就會將onDisplayChanged回調發送到正在偵聽此類事件的應用程序。

框架在後續的onHotplug(display, connection=CONNECTED)事件上重新分配幀緩衝區。有關如何處理此問題的更多信息,請參閱管理幀緩衝內存

處理常見的連接場景

本節介紹如何在主顯示器連接和斷開連接時正確處理實施中的各種連接場景。

Android 框架是為移動設備構建的,它沒有內置對斷開連接的主顯示器的支持。相反,在主顯示器物理斷開的情況下,HAL 在與框架的交互中必須用佔位符顯示器替換主顯示器。

在具有可斷開連接的外接顯示器的機頂盒和電視棒中可能會出現以下情況。為了實現對這些方案的支持,請使用下表中的信息:

設想處理
開機時沒有連接顯示器
  • 從 Composer HAL 向框架發送onHotplug(display, connection=CONNECTED)信號。
  • 將 Composer HAL 內的物理顯示狀態替換為佔位符顯示狀態。

    注意:我們建議佔位符顯示具有單一支持的模式,分辨率為 1080x1920,刷新率為 60hz,因為大多數應用程序都支持此顯示模式。

主顯示器物理連接
主顯示器物理斷開
  • 從 Composer HAL 向框架發送另一個onHotplug(display, connection=CONNECTED)事件。
  • 將 Composer HAL 內的物理顯示狀態替換為佔位符顯示狀態。佔位符顯示必須具有單一顯示模式,以便框架將onDisplayChanged回調發送到應用程序(因為支持的模式集已更改)。這種單一顯示模式必須與斷開前物理顯示的最後一個活動模式匹配,以便應用程序不會收到配置更改事件

管理幀緩衝內存

當已連接的顯示器收到後續的onHotplug(display, connection=CONNECTED)通知事件時,框架會重新分配與此顯示器關聯的幀緩衝區。設備實現必須預見到這種行為並正確管理幀緩衝內存。在您的實施中使用以下準則:

  • 在發送後續onHotplug(display, connection=CONNECTED)通知事件之前,請確保釋放幀緩衝區的句柄,以便系統可以在重新分配它們之前正確地釋放它們。如果釋放不成功,則重新分配可能由於內存不足而失敗。

  • 我們建議為獨立於圖形內存緩衝區的其餘部分的幀緩衝區分配一個專用內存池。

這很重要,因為在幀緩衝區的重新分配和重新分配之間,第三方進程可以嘗試分配圖形內存。如果幀緩衝區使用相同的顯存池並且顯存已滿,則第三方進程可以佔用幀緩衝區先前分配的顯存,從而為幀緩衝區重新分配留下足夠的內存(或可能將內存空間碎片化) .

使用順序配置 ID 來防止競爭條件

如果 Composer HAL 與調用setActiveConfigsetActiveConfigWithConstraints的框架同時更新支持的顯示配置,則可能會出現競爭條件。解決方案是實現 Composer HAL 以使用順序 ID 並防止此問題。

本節描述了競爭條件可能如何發生,隨後詳細介紹瞭如何實現 Composer HAL 以便它使用順序 ID 來防止這種情況。

考慮以下事件序列,當新的順序 ID 未分配給新的顯示配置時,會導致競爭條件:

  1. 支持的顯示配置 ID 為:

    • id=1 , 1080x1920 60hz
    • id=2 , 1080x1920 50hz
  2. 框架調用setActiveConfig(display, config=1)

  3. 同時,Composer HAL 處理顯示配置的更改並將其內部狀態更新為一組新的顯示配置,如下所示:

    • id=1 , 2160x3840 60hz
    • id=2 , 2160x3840 50hz
    • id=3 , 1080x1920 60hz
    • id=4 , 1080x1920 50hz
  4. Composer HAL 向框架發送一個onHotplug事件,以通知支持的模式集已更改。

  5. Composer HAL 接收setActiveConfig(display, config=1) (來自步驟 2)。

  6. HAL 解釋說框架已請求將配置更改為2160x3840 60hz ,儘管實際上需要1080x1920 60hz

使用非順序 ID 分配的過程以對所需配置更改的誤解結束。

將 Composer HAL 配置為使用順序 ID

為避免此類競爭條件,OEM 必須按如下方式實施 Composer HAL:

  • 當 Composer HAL 更新支持的顯示配置時,它會為新的顯示配置分配新的連續 ID。
  • 當框架使用無效的配置 ID 調用setActiveConfigsetActiveConfigWithConstraints時,Composer HAL 會忽略該調用。

這些步驟用於防止競爭條件,如下面的討論所示。

考慮以下事件序列,當新的順序 ID 分配給新的顯示配置時:

  1. 支持的顯示配置 ID 為:

    • id=1 , 1080x1920 60hz
    • id=2 , 1080x1920 50hz
  2. 框架調用setActiveConfig(display, config=1)

  3. 當處理顯示配置的更改時,將從下一個未使用的整數開始分配下一組配置 ID,如下所示:

    • id=3 , 2160x3840 60hz

    • id=4 , 2160x3840 50hz

    • id=5 , 1080x1920 60hz

    • id=6 , 1080x1920 50hz

  4. Composer HAL 向框架發送onHotplug事件,以通知支持的模式集已更改。

  5. Composer HAL 接收setActiveConfig(display, config=1) (來自步驟 2)。

  6. Composer HAL 忽略調用,因為 ID 不再有效。

  7. 框架接收並處理來自步驟 4 的onHotplug事件。它使用函數getDisplayConfigsgetDisplayAttribute調用 Composer HAL。借助這些功能,框架可以識別新 ID (5),以獲得 1080x1920 和 60Hz 的所需分辨率和刷新率。

  8. 框架發送另一個setActiveConfig事件,更新後的 ID 為 5。

  9. Composer HAL 從第 5 步接收setActiveConfig(display, config=5)

  10. HAL 正確解釋框架已請求將配置更改為 1080x1920 60hz。

如上例所示,使用順序 ID 分配的過程可確保防止競爭條件並更新正確的顯示配置更改。