Umgang mit Hotplugs

Displayfunktionen wie Displaymodi und unterstützte HDR-Typen können sich auf Geräten mit extern angeschlossenen Displays (über HDMI oder DisplayPort) dynamisch ändern, z. B. auf Android TV-Set-Top-Boxen (STBs) und Over-the-Top-Geräten (OTT). 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. Android 12 und höher enthalten Änderungen am Framework, um Hotplugging und dynamische Displayfunktionen zu verarbeiten.

Auf dieser Seite wird die Verarbeitung von Hotplugs für Displays und Änderungen an den Displayfunktionen 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.

Displayfunktionen aktualisieren

In diesem Abschnitt wird beschrieben, wie das Android-Framework Änderungen an den Displayfunktionen verarbeitet, die von der Composer HAL initiiert wurden.

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 Änderungen an den Anzeigefunktionen zu informieren. Nach der Implementierung werden Änderungen an den Displayfunktionen von Android so verarbeitet:

  1. Wenn eine Änderung der Anzeigefunktionen erkannt wird, erhält das Framework eine onHotplug(display, connection=CONNECTED)-Benachrichtigung.
  2. Wenn das Framework die Benachrichtigung erhält, setzt es den Displaystatus zurück und erstellt ihn mit den neuen Funktionen der HAL neu. Dazu werden die Methoden getActiveConfig, getDisplayConfigs, getDisplayAttribute, getColorModes, getHdrCapabilities und getDisplayCapabilities verwendet.
  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 Framebuffer bei nachfolgenden onHotplug(display, connection=CONNECTED)-Ereignissen neu zu. Weitere Informationen zum ordnungsgemäßen Verwalten des Framebuffer-Speichers, um Fehler bei der Zuweisung neuer Framebuffer zu vermeiden, finden Sie unter Client-Framebuffer-Verwaltung.

Häufige Verbindungsszenarien verarbeiten

In diesem Abschnitt erfahren Sie, wie Sie verschiedene Verbindungsszenarien in Ihren Implementierungen richtig handhaben, wenn das primäre Display verbunden und getrennt ist.

Da das Android-Framework für Mobilgeräte entwickelt wurde, unterstützt es kein getrenntes primäres Display. 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 Set-Top-Boxen und TV-Dongles auftreten, die extern angeschlossene Displays haben, die getrennt werden können. Verwenden Sie die Informationen in der folgenden Tabelle, um Unterstützung für diese Szenarien zu implementieren:

Szenario Handhabung
Kein angeschlossener Bildschirm beim Starten
  • Senden Sie ein onHotplug(display, connection=CONNECTED)-Signal von der Composer HAL an das Framework.
  • Ersetzen Sie den physischen Displaystatus in der Composer HAL durch einen Platzhalter-Displaystatus.
Primäres Display ist physisch verbunden
Das primäre Display ist physisch getrennt
  • Senden Sie ein weiteres onHotplug(display, connection=CONNECTED)-Ereignis von der Composer HAL an das Framework.
  • Ersetzen Sie den physischen Displaystatus in der Composer HAL durch einen Platzhalter-Displaystatus. Die Platzhalteranzeige muss einen einzelnen Anzeigemodus haben, damit das Framework den onDisplayChanged-Callback an die Apps sendet, weil sich die unterstützten Modi geändert haben. Dieser Modus für ein einzelnes Display muss mit dem zuletzt aktiven Modus des physischen Displays vor der Trennung übereinstimmen, damit Apps keine Ereignisse zur Konfigurationsänderung erhalten.

Nicht HDMI-Verbindungen

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

  • 720 x 1280
  • 1.080 × 1.920
  • 2160 x 3840
  • 4320 × 7680

Wenn ein STB oder TV-Dongle versucht, eine nicht unterstützte Auflösung wie 480i über eine CVBS-Verbindung anzuzeigen, 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 zu implementieren, um sequenzielle IDs zu verwenden und dieses Problem zu vermeiden.

In diesem Abschnitt wird beschrieben, wie es zu Race-Bedingungen kommen kann. Anschließend folgen Details dazu, wie Sie Composer HAL so implementieren, dass solche Bedingungen mithilfe von sequenziellen IDs verhindert werden.

Betrachten Sie die folgende Abfolge von Ereignissen, wenn den neuen Anzeigenkonfigurationen KEINE neuen, fortlaufenden IDs zugewiesen werden, was zu einer Race-Condition führt:

  1. Folgende Displaykonfigurations-IDs werden unterstützt:

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

  3. Gleichzeitig verarbeitet die Composer HAL eine Änderung der Displaykonfigurationen und aktualisiert ihren internen Status auf eine neue Gruppe von Displaykonfigurationen, wie hier dargestellt:

    • id=1, 2160 x 3840, 60 Hz
    • id=2, 2160 × 3840, 50 Hz
    • id=3, 1080 x 1920, 60 Hz
    • id=4, 1080 × 1920, 50 Hz
  4. 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 HAL geht davon aus, dass das Framework eine Konfigurationsänderung auf 2160 × 3840 60 Hz angefordert hat, obwohl in Wirklichkeit 1080 × 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 von sequenziellen IDs konfigurieren

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

  • Wenn die Composer HAL die unterstützten Displaykonfigurationen aktualisiert, werden den neuen Displaykonfigurationen neue, fortlaufende IDs zugewiesen.
  • Wenn das Framework setActiveConfig oder setActiveConfigWithConstraints mit einer ungültigen Konfigurations-ID aufruft, wird der Aufruf von der Composer HAL ignoriert.

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

Angenommen, den neuen Anzeigenkonfigurationen werden neue, fortlaufende IDs zugewiesen. Hier ist die Abfolge der Ereignisse:

  1. Folgende Displaykonfigurations-IDs werden unterstützt:

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

  3. Wenn eine Änderung der Anzeigekonfigurationen verarbeitet wird, werden die nächsten Konfigurations-IDs ab der nächsten nicht verwendeten Ganzzahl zugewiesen. Das sieht so aus:

    • id=3, 2.160 × 3.840, 60 Hz

    • id=4, 2160 × 3840, 50 Hz

    • id=5, 1.080 × 1.920, 60 Hz

    • id=6, 1080 × 1920, 50 Hz

  4. Die Composer HAL sendet ein onHotplug-Ereignis an das Framework, um zu informieren, dass sich die unterstützten Modi geändert haben.

  5. Die 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 onHotplug-Ereignis aus Schritt 4. Er ruft die Composer HAL mit den Funktionen getDisplayConfigs und getDisplayAttribute auf. Mit diesen Funktionen identifiziert das Framework die neue ID (5) für die gewünschte Auflösung und Bildwiederholrate von 1080 × 1920 und 60 Hz.

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

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

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

Wie im Beispiel oben gezeigt, wird durch den Prozess mit sequenziellen ID-Zuweisungen verhindert, dass es zu einer Race-Bedingung kommt, und die richtige Änderung der Anzeigekonfiguration wird aktualisiert.