熱插拔處理

在具備 HDMI 或 DisplayPort 外接螢幕的裝置 (例如 Android TV 機上盒 (STB) 和 over-the-top (OTT) 裝置),顯示模式和支援的 HDR 類型等顯示模式可能會動態改變。這項變更可能會因 HDMI 熱插頭信號而發生,例如使用者切換螢幕時,或是在沒有連接的螢幕的情況下啟動裝置。Android 12 以上版本包含用於處理熱插拔和動態顯示功能的架構變更。

本頁面說明如何在 Composer HAL 實作中處理螢幕熱點和顯示功能變更。此外,也會探討如何管理相關聯的 framebuffer,以及如何避免發生這類情況。

更新顯示功能

本節說明 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) 事件上重新分配 framebuffer。如要進一步瞭解如何正確管理 Framebuffer 記憶體,以免在配置新的 framebuffer 期間發生故障,請參閱「用戶端 framebuffer 管理」。

處理常見的連線情境

本節說明當主要螢幕連接和中斷連線時,如何正確處理實作中的各種連線情境。

Android 架構為行動裝置所設計,因此無法內建支援中斷的主要螢幕。相反地,在主要螢幕中斷連線時,HAL 必須在與架構互動時,將主要螢幕替換為預留位置螢幕。

STB 和電視連接器如果已連線至外部連接螢幕 (可中斷連線),可能會發生以下情況。如要實作這些情境的支援功能,請使用下表的資訊:

情境 使用方式
啟動時未連接任何螢幕
  • onHotplug(display, connection=CONNECTED) 信號從 Composer HAL 傳送至架構。
  • 將 Composer HAL 內的實體顯示狀態替換成預留位置顯示狀態。
主要螢幕已實際連線
主要螢幕已中斷連線
  • 將另一個 onHotplug(display, connection=CONNECTED) 事件從 Composer HAL 傳送至架構。
  • 將 Composer HAL 內的實體顯示狀態替換成預留位置顯示狀態。預留位置顯示模式必須提供單一顯示模式,這樣架構才能將 onDisplayChanged 回呼傳送至應用程式 (因為支援的模式組合已變更)。這個單顯示模式必須與實體螢幕的最後使用模式相符,才能中斷連線,確保應用程式不會收到設定變更事件

非 HDMI 連線注意事項

Android TV 僅支援下列解析度:

  • 720x1280
  • 1080x1920
  • 2160x3840
  • 4320x7680

當 STB 或電視 Dongle 嘗試顯示不支援的解析度 (例如透過 CVBS 連線使用 480i 時),系統會向使用者顯示錯誤訊息。

如果 STB 或電視 Dongle 同時具有 HDMI 和非 HDMI 連線,則 HDMI 連線會成為主要螢幕,且非 HDMI 連線處於未啟用狀態。因此,在非 HDMI 連線保持連線的情況下,如果 HDMI 連線中斷,事件會傳送至 SurfaceFlinger,且非 HDMI 螢幕的功能必須透過 getDisplayAttribute 和其他 iComposerClient API (例如 getHdrCapabilities) 反映。

使用序列設定 ID 防止競爭狀況

如果 Composer HAL 與呼叫 setActiveConfigsetActiveConfigWithConstraints 的架構同時更新支援的顯示設定,可能會發生競爭狀況。解決方法是導入 Composer HAL,以便使用依序 ID 並避免這個問題。

本節說明競爭狀況的發生方式,接著會詳細說明如何實作 Composer HAL,使其使用依序 ID 來避免發生這類狀況。

當「未」將新的依序 ID 指派給新的顯示設定時,請考慮以下事件順序,進而導致競爭狀況:

  1. 支援的顯示設定 ID 如下:

    • id=1,1080x1920 60 Hz
    • id=2,1080x1920 50 Hz
  2. 架構會呼叫 setActiveConfig(display, config=1)

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

    • id=1、2160x3840 60 Hz
    • id=2、2160x3840 50 Hz
    • id=3,1080x1920 60 Hz
    • id=4,1080x1920 50 Hz
  4. Composer HAL 會傳送 onHotplug 事件至架構,以通知支援的模式集已變更。

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

  6. HAL 解讀架構要求將設定變更要求為 2160x3840 60 Hz,但實際上需要 1080x1920 60 Hz

使用非循序 ID 指派的程序在此結束,但對於所需的設定變更有錯誤解讀。

設定 Composer HAL 以使用序列 ID

為避免發生這種競爭狀況,原始設備製造商 (OEM) 必須實作 Composer HAL,如下所示:

  • Composer HAL 更新支援的顯示設定時,會將新的依序 ID 指派給新的顯示設定。
  • 如果架構使用無效的設定 ID 呼叫 setActiveConfigsetActiveConfigWithConstraints,Composer HAL 會忽略呼叫。

這些步驟可以用來避免競爭狀況,如以下討論所示。

將新的序列 ID 指派給新的顯示設定時,請考慮以下事件順序:

  1. 支援的顯示設定 ID 如下:

    • id=1,1080x1920 60 Hz
    • id=2,1080x1920 50 Hz
  2. 架構會呼叫 setActiveConfig(display, config=1)

  3. 處理顯示設定的變更時,系統會從下一個未使用的整數開始指派下一組設定 ID,如下所示:

    • id=3,2160x3840 60 Hz

    • id=4、2160x3840 50 Hz

    • id=5,1080x1920 60 Hz

    • id=6,1080x1920 50 Hz

  4. Composer HAL 會傳送 onHotplug 事件至架構,以通知支援的模式集已變更。

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

  6. 由於 ID 已失效,Composer HAL 會忽略呼叫。

  7. 架構接收及處理步驟 4 的 onHotplug 事件。這個函式會使用 getDisplayConfigsgetDisplayAttribute 函式呼叫 Composer HAL。有了這些功能,架構就能識別所需的解析度和刷新率 1080x1920 和 60 Hz 的新 ID (5)。

  8. 架構會傳送另一個 setActiveConfig 事件 (更新 ID 為 5)。

  9. Composer HAL 會收到步驟 5 的 setActiveConfig(display, config=5)

  10. HAL 正確解讀架構要求將設定變更為 1080x1920 60 Hz。

如上例所示,使用依序 ID 指派的程序可確保競爭條件已避免,並更新正確的顯示設定變更。