Umgang mit Hotplugs

Anzeigefunktionen (z. B. Anzeigemodi und unterstützte HDR-Typen) können sich auf Geräten mit extern verbundenen Bildschirmen (mit HDMI oder DisplayPort), z. B. Android TV-Set-Top-Boxen (STBs) und Over-the-Top-Geräte (OTT), dynamisch ändern. Diese Änderung kann aufgrund eines HDMI-Hotplug-Signals erfolgen, z. B. wenn der Nutzer von einem Bildschirm zu einem anderen wechselt oder das Gerät ohne angeschlossenen Bildschirm startet. Unter Android 12 und höher wurden Änderungen am Framework vorgenommen, um Hotplugging- und dynamische Anzeigefunktionen zu ermöglichen.

Auf dieser Seite wird die Handhabung von Display-Hotplugs und Änderungen der Anzeigefunktionen in der Composer-HAL-Implementierung beschrieben. Außerdem wird erläutert, wie Sie den zugehörigen Framebuffer verwalten und Race-Bedingungen in diesen Situationen verhindern.

Anzeigefunktionen aktualisieren

In diesem Abschnitt wird beschrieben, wie das Android-Framework Änderungen an Anzeigefunktionen verarbeitet, die von Composer HAL initiiert werden.

Bevor Android Änderungen an den Anzeigefunktionen ordnungsgemäß verarbeiten kann, muss der OEM Composer HAL so implementieren, dass er onHotplug(display, connection=CONNECTED) verwendet, um das Framework über alle Änderungen an den Anzeigefunktionen zu informieren. Nach der Implementierung verarbeitet Android Änderungen an den Anzeigefunktionen so:

  1. Wird eine Änderung der Anzeigefunktionen erkannt, erhält das Framework eine onHotplug(display, connection=CONNECTED)-Benachrichtigung.
  2. Beim Empfang der Benachrichtigung löscht das Framework seinen Anzeigestatus und erstellt ihn mit den neuen Funktionen aus dem HAL mithilfe der Methoden getActiveConfig, getDisplayConfigs, getDisplayAttribute, getColorModes, getHdrCapabilities und getDisplayCapabilities neu.
  3. Nachdem das Framework einen neuen Anzeigezustand neu erstellt hat, wird der onDisplayChanged-Callback an die Apps gesendet, die solche Ereignisse beobachten.

Das Framework weist die Framepuffer bei nachfolgenden onHotplug(display, connection=CONNECTED)-Ereignissen neu zu. Weitere Informationen zum ordnungsgemäßen Verwalten des Framebuffer-Arbeitsspeichers, um Fehler bei der Zuweisung neuer Framebuffer zu vermeiden, finden Sie unter Client-Framebuffer-Verwaltung.

Häufige Verbindungsszenarien verarbeiten

In diesem Abschnitt wird beschrieben, wie Sie in Ihren Implementierungen verschiedene Verbindungsszenarien richtig handhaben, wenn der primäre Bildschirm angeschlossen und getrennt wird.

Das Android-Framework wurde für Mobilgeräte entwickelt, bietet aber keine integrierte Unterstützung für einen getrennten primären Bildschirm. Stattdessen muss der HAL den primären Bildschirm in seinen Interaktionen mit dem Framework durch einen Platzhalter ersetzen, wenn die primäre Anzeige physisch getrennt ist.

Die folgenden Szenarien können bei STBs und TV-Dongles auftreten, die extern angeschlossene Bildschirme haben, die getrennt werden können. Verwenden Sie die Informationen in der folgenden Tabelle, um die Unterstützung für diese Szenarien zu implementieren:

Szenario Umgang mit Ihrem Smartphone
Kein Display beim Starten verbunden
  • Senden Sie ein onHotplug(display, connection=CONNECTED)-Signal vom Composer-HAL an das Framework.
  • Ersetzen Sie den physischen Anzeigestatus im Composer-HAL durch einen Platzhalteranzeigestatus.
Primäres Display ist physisch verbunden
Primäres Display ist nicht verbunden
  • Senden Sie ein weiteres onHotplug(display, connection=CONNECTED)-Ereignis vom Composer-HAL an das Framework.
  • Ersetzen Sie den physischen Anzeigestatus im Composer-HAL durch einen Platzhalteranzeigestatus. Die Platzhalteranzeige muss einen einzelnen Anzeigemodus haben, damit das Framework den onDisplayChanged-Callback an Apps sendet, da sich die unterstützten Modi geändert haben. Dieser einzelne Anzeigemodus muss mit dem letzten aktiven Modus des physischen Displays übereinstimmen, bevor die Verbindung getrennt wird, damit Apps keine Konfigurationsänderungsereignisse empfangen.

Überlegungen zu Nicht-HDMI-Verbindungen

Android TV unterstützt nur die folgenden Auflösungen:

  • 720 × 1280
  • 1080 × 1920
  • 2160 × 3840
  • 4320 × 7680

Wenn ein STB oder ein TV-Dongle versucht, eine nicht unterstützte Auflösung anzuzeigen, z. B. 480i über eine CVBS-Verbindung, wird dem Nutzer eine Fehlermeldung angezeigt.

Wenn der STB- oder TV-Dongle sowohl HDMI- als auch Nicht-HDMI-Verbindungen hat, ist die HDMI-Verbindung der primäre Bildschirm und die Nicht-HDMI-Verbindung ist inaktiv. Wenn die HDMI-Verbindung getrennt wird, während die Nicht-HDMI-Verbindung weiterhin besteht, wird ein Ereignis an SurfaceFlinger gesendet und die Funktionen des Nicht-HDMI-Bildschirms müssen über die getDisplayAttribute und andere iComposerClient APIs (z. B. getHdrCapabilities) wiedergegeben werden.

Sequenzielle Konfigurations-IDs verwenden, um Race-Bedingungen zu verhindern

Race-Bedingungen können auftreten, wenn der Composer-HAL die unterstützten Anzeigekonfigurationen gleichzeitig mit dem Framework aktualisiert, das setActiveConfig oder setActiveConfigWithConstraints aufruft. Die Lösung besteht darin, Composer HAL so zu implementieren, dass sequenzielle IDs verwendet werden und dieses Problem vermieden wird.

In diesem Abschnitt wird beschrieben, wie die Race-Bedingungen auftreten können, gefolgt von Details zur Implementierung von Composer HAL, damit er sequenzielle IDs verwendet, um solche Bedingungen zu verhindern.

Sehen Sie sich die folgende Ereignissequenz an, wenn den neuen Anzeigekonfigurationen NICHT neue, sequenzielle IDs zugewiesen werden. Dies führt zu einer Race-Bedingung:

  1. Folgende Konfigurations-IDs für Displayanzeigen werden unterstützt:

    • id=1, 1.080 × 1.920, 60 Hz
    • id=2, 1.080 × 1.920, 50 Hz
  2. Das Framework ruft setActiveConfig(display, config=1) auf.

  3. Gleichzeitig verarbeitet der Composer-HAL eine Änderung der Anzeigekonfigurationen und aktualisiert seinen internen Status auf einen neuen Satz von Anzeigekonfigurationen:

    • id=1, 2.160 × 3.840, 60 Hz
    • id=2, 2.160 × 3.840, 50 Hz
    • id=3, 1.080 × 1.920, 60 Hz
    • id=4, 1.080 × 1.920, 50 Hz
  4. Composer HAL sendet ein onHotplug-Ereignis an das Framework, um zu benachrichtigen, dass sich der Satz der unterstützten Modi geändert hat.

  5. Der Composer-HAL empfängt setActiveConfig(display, config=1) (aus Schritt 2).

  6. Der HAL geht davon aus, dass das Framework eine Konfigurationsänderung auf 2160 x 3840 60 Hz angefordert hat, obwohl in Wirklichkeit 1080 x 1920 60 Hz gewünscht ist.

Der Prozess mit nicht sequenziellen ID-Zuweisungen endet hier mit einer Fehlinterpretation der gewünschten Konfigurationsänderung.

Composer-HAL für die Verwendung sequenzieller IDs konfigurieren

Um solche Race-Bedingungen zu vermeiden, muss der OEM den Composer-HAL so implementieren:

  • Wenn der Composer-HAL die unterstützten Anzeigekonfigurationen aktualisiert, weist er den neuen Anzeigekonfigurationen neue sequenzielle IDs zu.
  • Wenn das Framework setActiveConfig oder setActiveConfigWithConstraints mit einer ungültigen Konfigurations-ID aufruft, ignoriert der Composer-HAL den Aufruf.

Diese Schritte dienen dazu, Race-Bedingungen zu verhindern, wie in der folgenden Diskussion gezeigt.

Sehen Sie sich die folgende Ereignissequenz an, wenn den neuen Anzeigekonfigurationen neue sequenzielle IDs zugewiesen werden:

  1. Folgende Konfigurations-IDs für Displayanzeigen werden unterstützt:

    • id=1, 1.080 × 1.920, 60 Hz
    • id=2, 1.080 × 1.920, 50 Hz
  2. Das Framework ruft setActiveConfig(display, config=1) auf.

  3. Wenn eine Änderung von Displaykonfigurationen verarbeitet wird, wird der nächste Satz Konfigurations-IDs ab der nächsten nicht verwendeten Ganzzahl zugewiesen:

    • id=3, 2.160 × 3.840, 60 Hz

    • id=4, 2.160 × 3.840, 50 Hz

    • id=5, 1.080 × 1.920, 60 Hz

    • id=6, 1.080 × 1.920, 50 Hz

  4. Der Composer-HAL sendet ein onHotplug-Ereignis an das Framework, um zu informieren, dass sich der Satz der unterstützten Modi geändert hat.

  5. Der Composer-HAL empfängt setActiveConfig(display, config=1) (aus Schritt 2).

  6. Der Composer-HAL ignoriert den Aufruf, da die ID nicht mehr gültig ist.

  7. Das Framework empfängt und verarbeitet das Ereignis onHotplug aus Schritt 4. Er ruft den Composer-HAL mit den Funktionen getDisplayConfigs und getDisplayAttribute auf. Mit diesen Funktionen ermittelt das Framework die neue ID (5) für die gewünschte Auflösung und Aktualisierungsrate von 1.080 × 1.920 und 60 Hz.

  8. Das Framework sendet ein weiteres setActiveConfig-Ereignis mit der aktualisierten ID 5.

  9. Der Composer-HAL empfängt setActiveConfig(display, config=5) aus Schritt 5.

  10. Der HAL interpretiert richtig, dass das Framework eine Konfigurationsänderung auf 1080 × 1920 60 Hz angefordert hat.

Wie im obigen Beispiel gezeigt, sorgt der Prozess mit sequenziellen ID-Zuweisungen dafür, dass die Race-Bedingung verhindert und die korrekte Änderung der Anzeigekonfiguration aktualisiert wird.