在具有外接螢幕 (使用 HDMI 或 DisplayPort) 的裝置上,顯示功能 (例如顯示模式和支援的 HDR 類型) 可以動態變更,例如 Android TV 機上盒 (STB) 和 OTT 裝置。這類變更可能會因 HDMI 熱插信號而發生,例如使用者從一個螢幕切換到另一個螢幕,或是在未連接螢幕的情況下啟動裝置。Android 12 以上版本的架構中包含了一些變更,可處理熱插和動態顯示功能。
本頁說明如何在 Composer HAL 實作中處理螢幕熱插拔和螢幕功能變更。此外,本文也會說明如何管理相關的 framebuffer,並在這些情況下避免競爭狀態。
更新顯示功能
本節說明 Android 架構如何處理 Composer HAL 啟動的顯示功能變更。
在 Android 能夠妥善處理顯示功能變更之前,原始設備製造商必須實作 Composer HAL,讓系統使用 onHotplug(display, connection=CONNECTED)
通知架構顯示功能的任何變更。實作後,Android 會依下列方式處理顯示功能的變更:
- 偵測到顯示功能變更時,架構會收到
onHotplug(display, connection=CONNECTED)
通知。 - 收到通知後,架構會捨棄其顯示狀態,並使用 HAL 的新功能重新建立顯示狀態,方法是使用
getActiveConfig
、getDisplayConfigs
、getDisplayAttribute
、getColorModes
、getHdrCapabilities
和getDisplayCapabilities
方法。 - 架構重新建立新的顯示狀態後,就會將
onDisplayChanged
回呼傳送至正在監聽這類事件的應用程式。
架構會在後續 onHotplug(display, connection=CONNECTED)
事件中重新分配 framebuffer。如要進一步瞭解如何妥善管理 framebuffer 記憶體,以免在配置新 framebuffer 時發生錯誤,請參閱「用戶端 framebuffer 管理」。
處理常見的連線情境
本節將說明如何在主要螢幕連線和斷線時,在實作中妥善處理各種連線情境。
由於 Android 架構是為行動裝置建構,因此並未內建支援中斷連線的主螢幕。相反地,如果主要螢幕已實際中斷連線,則 HAL 必須在與架構互動時,將主要螢幕替換為預留位置螢幕。
在 STB 和電視隨身碟中,如果有外接螢幕且可斷開連線,就可能發生下列情況。如要為這些情況實作支援功能,請參考下表中的資訊:
情境 | 使用方式 |
---|---|
開機時沒有連接的螢幕 |
|
主要螢幕已連線 |
|
主要螢幕已實際中斷連線 |
|
非 HDMI 連線注意事項
Android TV 僅支援下列解析度:
- 720x1280
- 1080x1920
- 2160x3840
- 4320x7680
如果 STB 或 TV 轉接器嘗試顯示不支援的解析度 (例如透過 CVBS 連線的 480i),系統會向使用者顯示錯誤訊息。
如果 STB 或電視轉接器同時有 HDMI 和非 HDMI 連線,HDMI 連線會是主要螢幕,而非 HDMI 連線則會處於停用狀態。因此,如果 HDMI 連線中斷,而非 HDMI 連線仍處於連線狀態,系統會將事件傳送至 SurfaceFlinger,且非 HDMI 螢幕的功能必須透過 getDisplayAttribute
和其他 iComposerClient
API (例如 getHdrCapabilities
) 反映。
使用連續的設定 ID 避免競爭狀況
如果 Composer HAL 同時更新支援的顯示設定,並且呼叫 setActiveConfig
或 setActiveConfigWithConstraints
的架構,就可能發生競爭條件。解決方法是實作 Composer HAL,以便使用序列 ID 並避免發生這個問題。
本節將說明競態狀態可能發生的情況,並詳細說明如何實作 Composer HAL,以便使用序列 ID 避免發生這種情況。
請考慮下列事件序列,如果未將新的連續 ID 指派給新的顯示設定,就會導致競爭狀態:
支援的顯示設定 ID 如下:
- id=1、1080x1920 60 Hz
- id=2、1080x1920 50 Hz
同時,Composer HAL 會處理顯示設定的變更,並將其內部狀態更新為一組新的顯示設定,如下所示:
- id=1,2160x3840 60 Hz
- id=2, 2160x3840 50 Hz
- id=3、1080x1920 60 Hz
- id=4,1080x1920 50 Hz
Composer HAL 會將
onHotplug
事件傳送至架構,通知支援的模式集合已變更。Composer HAL 會接收
setActiveConfig(display, config=1)
(來自步驟 2)。HAL 會解讀為架構已要求將設定變更為 2160x3840 60 Hz,但實際上應為 1080x1920 60 Hz。
使用非順序 ID 指派的程序就此結束,並誤解所需的設定變更。
設定 Composer HAL 以使用序列 ID
為避免這種競爭狀態,OEM 必須按照下列方式實作 Composer HAL:
- 當 Composer HAL 更新支援的顯示設定時,會為新顯示設定指派新的連續 ID。
- 當架構使用無效的設定 ID 呼叫
setActiveConfig
或setActiveConfigWithConstraints
時,Composer HAL 會忽略該呼叫。
這些步驟可避免競爭狀況,如後文討論所示。
請考慮以下事件順序,當新的顯示設定配置指派新的連續 ID 時:
支援的顯示設定 ID 如下:
- id=1、1080x1920 60 Hz
- id=2、1080x1920 50 Hz
處理顯示設定的變更時,系統會從下一個未使用的整數開始指派下一個設定 ID 組合,如下所示:
id=3, 2160x3840 60 Hz
id=4,2160x3840 50 Hz
id=5,1080x1920 60 Hz
id=6,1080x1920 50 Hz
Composer HAL 會將
onHotplug
事件傳送至架構,通知支援的模式集合已變更。Composer HAL 會接收
setActiveConfig(display, config=1)
(來自步驟 2)。由於 ID 已失效,因此 Composer HAL 會忽略呼叫。
架構會接收並處理步驟 4 中的
onHotplug
事件。它會使用getDisplayConfigs
和getDisplayAttribute
函式呼叫 Composer HAL。透過這些函式,架構會為所需的解析度和刷新率 (1080x1920 和 60 Hz) 識別新 ID (5)。架構會傳送另一個
setActiveConfig
事件,其中 ID 已更新為 5。Composer HAL 會從步驟 5 接收
setActiveConfig(display, config=5)
。HAL 正確解讀架構已要求將設定變更為 1080x1920 60 Hz。
如上例所示,使用序列 ID 指派作業可確保避免競爭狀況,並更新正確的顯示設定變更。