熱插拔處理

在具有外接螢幕 (使用 HDMI 或 DisplayPort) 的裝置上,顯示功能 (例如顯示模式和支援的 HDR 類型) 可以動態變更,例如 Android TV 機上盒 (STB) 和 OTT 裝置。這項變更可能會因 HDMI 熱插信號而發生,例如使用者從一個螢幕切換到另一個螢幕,或是在未連接螢幕的情況下啟動裝置。Android 12 以上版本的架構中包含了一些變更,可處理熱插和動態顯示功能。

本頁說明如何在 Composer HAL 實作中處理螢幕熱插拔和螢幕功能變更。此外,本文也會說明如何管理相關的 framebuffer,並在這些情況下避免競爭狀態。

更新顯示功能

本節說明 Android 架構如何處理 Composer HAL 啟動的顯示功能變更。

在 Android 能夠妥善處理顯示功能變更之前,原始設備製造商必須實作 Composer HAL,讓系統使用 onHotplug(display, connection=CONNECTED) 通知架構顯示功能的任何變更。實作完畢後,Android 會處理顯示功能的變更,如下所示:

  1. 偵測到顯示功能變更時,架構會收到 onHotplug(display, connection=CONNECTED) 通知。
  2. 收到通知後,架構會捨棄其顯示狀態,並使用 HAL 的新功能重新建立顯示狀態,方法是使用 getActiveConfiggetDisplayConfigsgetDisplayAttributegetColorModesgetHdrCapabilitiesgetDisplayCapabilities 方法。
  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,並透過 getDisplayAttribute 和其他 iComposerClient API (例如 getHdrCapabilities) 反映非 HDMI 螢幕的功能。

使用連續的設定 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 指派的程序可確保競爭條件已避免,並更新正確的顯示設定變更。