Możliwości wyświetlacza (np. tryby wyświetlania i obsługiwane typy HDR) mogą się zmieniać dynamicznie na urządzeniach z zewnętrznie podłączonymi wyświetlaczami (za pomocą HDMI lub DisplayPort), takich jak dekodery Android TV i urządzenia OTT. Może to być spowodowane sygnałem połączenia HDMI, na przykład przełączeniem się z jednego wyświetlacza na drugi lub uruchomieniem urządzenia 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ę wtyczek typu „displayowe wtyczki” i zmieniamy możliwości wyświetlania w implementacji HAL Composer. Dodatkowo omawia on, 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żenia Android obsługuje 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 platforma usuwa stan wyświetlania i tworzy go z nowymi możliwościami z HAL przy użyciu metod
getActiveConfig
,getDisplayConfigs
,getDisplayAttribute
,getColorModes
,getHdrCapabilities
igetDisplayCapabilities
. - Po odtworzeniu nowego stanu wyświetlania platforma wysyła wywołanie zwrotne
onDisplayChanged
do aplikacji, które nasłuchują takich zdarzeń.
Platforma ponownie przydziela bufory ramek 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 wyjaśniamy, 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ć wyświetlacz główny wyświetlaczem zastępczym w swoich interakcjach z platformą w przypadku, gdy wyświetlacz główny jest fizycznie odłączony.
Poniższe sytuacje mogą wystąpić w przypadku STB i kluczy sprzętowych TV z podłączonymi zewnętrznymi wyświetlaczami, które można odłączyć. Aby wdrożyć obsługę tych scenariuszy, skorzystaj z informacji w tabeli poniżej:
Scenariusz | Obsługa |
---|---|
Brak podłączonego wyświetlacza podczas uruchamiania |
|
Ekran 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 dongle TV 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 więc połączenie HDMI zostanie przerwane, 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żywaj sekwencyjnych identyfikatorów konfiguracji, aby zapobiegać warunkom wyścigu
Warunki wyścigu mogą wystąpić, jeśli HAL usługi Composer zaktualizuje obsługiwane konfiguracje wyświetlania jednocześnie z wywoływaniem platformy 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 przedstawiono szczegóły implementacji interfejsu Composer HAL, który używa identyfikatorów sekwencyjnych, aby zapobiegać takim warunkom.
Rozważ tę sekwencję zdarzeń. Gdy nowe identyfikatory sekwencyjne NIE są przypisane do nowych konfiguracji wyświetlania, spowoduje to powstanie warunku wyścigu:
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 usługi komponowania 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 usługi Composer wysyła do platformy 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 usługi Composer 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 tworzenia kompozytowych reklam displayowych aktualizuje obsługiwane konfiguracje wyświetlania, przypisuje 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 tej 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
Struktura ta nazywa się
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 wartość
setActiveConfig(display, config=1)
(z kroku 2).HAL Composer ignoruje wywołanie, ponieważ identyfikator nie jest już prawidłowy.
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 określa nowy identyfikator (5) dla żądanej 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.