Możliwości wyświetlacza (np. tryby wyświetlania i obsługiwane typy HDR) mogą się dynamicznie zmieniać na urządzeniach z zewnętrznie podłączonymi wyświetlaczami (za pomocą HDMI lub DisplayPort), takich jak dekodery Android TV i urządzenia OTT. Ta zmiana może nastąpić w wyniku sygnału hotplug HDMI, na przykład gdy użytkownik przełączy się z jednego wyświetlacza na drugi lub uruchomi urządzenie bez podłączonego wyświetlacza. Android 12 i nowsze zawiera zmiany w ramach, które umożliwiają obsługę funkcji dynamicznego podłączania i dynamicznego wyświetlania.
Na tej stronie opisujemy obsługę podłączania i odłączania wyświetlacza oraz zmiany w możliwościach wyświetlacza w ramach implementacji interfejsu programowego sprzętu (HAL) Composer. Dodatkowo omawiamy w nim, jak zarządzać powiązanym framebufferem i zapobiegać sytuacjom wyścigu w takich przypadkach.
Aktualizowanie możliwości wyświetlania
W tej sekcji opisano, jak platforma Android obsługuje zmiany w możliwościach wyświetlania inicjowane przez interfejs HAL usługi Composer.
Zanim Android będzie mógł prawidłowo obsługiwać zmiany w możliwościach wyświetlania, OEM musi zaimplementować interfejs Composer HAL, który używa onHotplug(display, connection=CONNECTED)
do powiadamiania platformy o wszelkich zmianach w możliwościach wyświetlania. Po jego wdrożenie Android będzie obsługiwać zmiany w możliwościach wyświetlania w ten sposób:
- Po wykryciu zmiany możliwości wyświetlania framework otrzymuje powiadomienie
onHotplug(display, connection=CONNECTED)
. - Po otrzymaniu powiadomienia framework usuwa stan wyświetlania i tworzy go ponownie z nowymi funkcjami z HAL za pomocą metod
getActiveConfig
,getDisplayConfigs
,getDisplayAttribute
,getColorModes
,getHdrCapabilities
igetDisplayCapabilities
. - Gdy framework odtworzy nowy stan wyświetlania, wyśle wywołanie zwrotne
onDisplayChanged
do aplikacji, które nasłuchują takich zdarzeń.
Framework przydziela ponownie framebuffery w kolejnych zdarzeniach onHotplug(display, connection=CONNECTED)
. Więcej informacji o prawidłowym zarządzaniu pamięcią framebuffera, aby uniknąć błędów podczas przydzielania nowych framebufferów, znajdziesz w artykule Zarządzanie framebufferem klienta.
Obsługa typowych scenariuszy połączeń
W tej sekcji omawiamy, jak prawidłowo obsługiwać różne scenariusze połączeń w implementacjach, gdy wyświetlacz główny jest podłączony lub odłączony.
Platforma Android została stworzona z myślą o urządzeniach mobilnych i nie obsługuje wbudowanego wyświetlacza głównego. Zamiast tego HAL musi zastąpić główny wyświetlacz wyświetlaczem zastępczym podczas interakcji z platformą w przypadku, gdy główny wyświetlacz jest fizycznie odłączony.
W przypadku dekoderów i dongli telewizyjnych, które mają zewnętrzne wyświetlacze, które można odłączyć, mogą wystąpić następujące scenariusze. Aby wdrożyć obsługę tych scenariuszy, skorzystaj z informacji w tabeli poniżej:
Scenariusz | Obsługa |
---|---|
Brak podłączonego wyświetlacza podczas uruchamiania |
|
Wyświetlacz główny jest fizycznie podłączony. |
|
Wyświetlacz główny jest fizycznie odłączony. |
|
Informacje o połączeniach innych niż HDMI
Android TV obsługuje tylko te rozdzielczości:
- 720 x 1280
- 1080 x 1920
- 2160 x 3840
- 4320 x 7680
Gdy dekoder STB lub TV dongle próbuje wyświetlić rozdzielczość niedostępną dla danego urządzenia, np. 480i przez połączenie CVBS, użytkownik widzi komunikat o błędzie.
Jeśli dekoder lub urządzenie do telewizji ma zarówno złącza HDMI, jak i inne niż HDMI, złącze HDMI jest głównym wyświetlaczem, a inne niż HDMI jest nieaktywne. Jeśli w rezultacie połączenie HDMI zostanie odłączone, a połączenie nie-HDMI nadal będzie aktywne, do SurfaceFlinger zostanie wysłane zdarzenie, a funkcje wyświetlacza nie-HDMI muszą być odzwierciedlone za pomocą interfejsu getDisplayAttribute
i innych interfejsów iComposerClient
(takich jak getHdrCapabilities
).
Używanie sekwencyjnych identyfikatorów konfiguracji do zapobiegania sytuacjom wyścigu
Warunki wyścigu mogą wystąpić, jeśli HAL usługi Composer aktualizuje obsługiwane konfiguracje wyświetlacza równolegle z ramami wywołania setActiveConfig
lub setActiveConfigWithConstraints
.
Rozwiązaniem jest wdrożenie HAL usługi Composer, aby używać identyfikatorów sekwencyjnych i uniknąć tego problemu.
W tej sekcji opisano, jak mogą wystąpić warunki wyścigu, a następnie podano szczegóły implementacji interfejsu HAL usługi Composer, który używa identyfikatorów sekwencyjnych, aby zapobiegać takim warunkom.
Rozważ tę sekwencję zdarzeń, gdy nowe, kolejne identyfikatory NIE są przypisywane do nowych konfiguracji wyświetlania, co powoduje stan rywalizacji:
Obsługiwane identyfikatory konfiguracji wyświetlania:
- id=1, 1080 x 1920 60 Hz
- id=2, 1080 x 1920 50 Hz
Platforma wywołuje funkcję
setActiveConfig(display, config=1)
.Równocześnie interfejs HAL kompozytora przetwarza zmiany konfiguracji wyświetlacza i aktualizuje stan wewnętrzny na nowy zestaw konfiguracji wyświetlacza w ten sposób:
- id=1, 2160 x 3840 60 Hz
- id=2, 2160 x 3840 50 Hz
- id=3, 1080 x 1920 60 Hz
- id=4, 1080 x 1920 50 Hz
HAL kompozytora wysyła do frameworku zdarzenie
onHotplug
, aby powiadomić o zmianie zestawu obsługiwanych trybów.HAL usługi Composer otrzymuje
setActiveConfig(display, config=1)
(z etapu 2).HAL interpretuje to jako prośbę o zmianę konfiguracji na 2160x3840 60 Hz, chociaż w rzeczywistości chodziło o 1080x1920 60 Hz.
Proces przypisywania identyfikatorów niesekwencyjnych kończy się tu błędnym zinterpretowaniem żądanej zmiany konfiguracji.
Konfigurowanie HAL Composera do używania identyfikatorów sekwencyjnych
Aby uniknąć takich warunków wyścigu, OEM musi zaimplementować interfejs HAL usługi Composer w ten sposób:
- Gdy interfejs HAL usługi komponowania zaktualizuje obsługiwane konfiguracje wyświetlacza, przypisze do nowych konfiguracji nowe, sekwencyjne identyfikatory.
- Gdy framework wywołuje metodę
setActiveConfig
lubsetActiveConfigWithConstraints
z nieprawidłowym identyfikatorem konfiguracji, interfejs HAL usługi Composer ignoruje to wywołanie.
Te kroki służą do zapobiegania warunkom wyścigu, jak pokazano w następującej dyskusji.
Gdy do nowych konfiguracji wyświetlania zostaną przypisane nowe, kolejne identyfikatory, nastąpi następująca sekwencja zdarzeń:
Obsługiwane identyfikatory konfiguracji wyświetlania:
- id=1, 1080 x 1920 60 Hz
- id=2, 1080 x 1920 50 Hz
Platforma wywołuje funkcję
setActiveConfig(display, config=1)
.Gdy przetwarzana jest zmiana konfiguracji wyświetlania, przypisujemy kolejny zestaw identyfikatorów konfiguracji, zaczynając od kolejnej nieużytej wartości całkowitej, jak pokazano poniżej:
id=3, 2160x3840 60 Hz
id=4, 2160 x 3840 50 Hz
id=5, 1080 x 1920 60 Hz
id=6, 1080 x 1920 50 Hz
HAL kompozytora wysyła do frameworku zdarzenie
onHotplug
, aby powiadomić o zmianie zestawu obsługiwanych trybów.HAL usługi Composer otrzymuje
setActiveConfig(display, config=1)
(z etapu 2).Interfejs HAL usługi tworzenia kompozyturu ignoruje wywołanie, ponieważ identyfikator jest już nieważny.
Framework odbiera i przetwarza zdarzenie
onHotplug
z kroku 4. Wykonuje wywołanie do interfejsu Composer HAL za pomocą funkcjigetDisplayConfigs
igetDisplayAttribute
. Dzięki tym funkcjom platforma identyfikuje nowy identyfikator (5) dla wybranej rozdzielczości i częstotliwości odświeżania 1080 x 1920 i 60 Hz.Framework wysyła kolejne zdarzenie
setActiveConfig
z aktualnym identyfikatorem 5.HAL usługi Composer otrzymuje
setActiveConfig(display, config=5)
z kroku 5.HAL prawidłowo interpretuje, że framework poprosił o zmianę konfiguracji na 1080 x 1920 60 Hz.
Jak widać w powyższym przykładzie, proces przy użyciu przypisania identyfikatorów sekwencyjnych zapobiega wystąpieniu warunków wyścigu i zapewnia, że zostanie zastosowana prawidłowa zmiana konfiguracji wyświetlania.