Gestion des hotplugs

Les fonctionnalités d'affichage (telles que les modes d'affichage et les types de HDR compatibles) peuvent changer de manière dynamique sur les appareils dotés d'écrans connectés en externe (avec HDMI ou DisplayPort), tels que les décodeurs Android TV et les appareils OTT (Over The Top). Ce changement peut se produire en raison d'un signal de connexion/déconnexion HDMI, par exemple lorsque l'utilisateur passe d'un écran à un autre ou démarre l'appareil sans écran connecté. Android 12 et versions ultérieures incluent des modifications apportées au framework pour gérer le branchement à chaud et les fonctionnalités d'affichage dynamique.

Cette page décrit la gestion des hotplugs d'affichage et les modifications apportées aux fonctionnalités d'affichage dans l'implémentation du HAL Composer. Il explique également comment gérer le framebuffer associé et empêcher les conditions de concurrence dans ces situations.

Mettre à jour les fonctionnalités d'affichage

Cette section décrit comment le framework Android gère les modifications des fonctionnalités d'affichage initiées par le HAL Composer.

Pour qu'Android puisse gérer correctement les modifications des fonctionnalités d'affichage, l'OEM doit implémenter l'HAL Composer de sorte qu'il utilise onHotplug(display, connection=CONNECTED) pour signaler au framework toute modification des fonctionnalités d'affichage. Une fois cela implémenté, Android gère les modifications apportées aux fonctionnalités d'affichage comme suit:

  1. Lorsqu'il détecte une modification des fonctionnalités d'affichage, le framework reçoit une notification onHotplug(display, connection=CONNECTED).
  2. À la réception de la notification, le framework abandonne son état d'affichage et le recrée avec les nouvelles fonctionnalités de l'HAL à l'aide des méthodes getActiveConfig, getDisplayConfigs, getDisplayAttribute, getColorModes, getHdrCapabilities et getDisplayCapabilities.
  3. Une fois que le framework a recréé un état d'affichage, il envoie le rappel onDisplayChanged aux applications qui écoutent ces événements.

Le framework réalloue les framebuffers lors des événements onHotplug(display, connection=CONNECTED) suivants. Pour en savoir plus sur la gestion appropriée de la mémoire du framebuffer afin d'éviter les erreurs lors de l'allocation de nouveaux framebuffers, consultez la section Gestion du framebuffer client.

Gérer les scénarios de connexion courants

Cette section explique comment gérer correctement les différents scénarios de connexion dans vos implémentations lorsque l'écran principal est connecté et déconnecté.

Étant conçu pour les appareils mobiles, le framework Android n'est pas compatible avec un écran principal déconnecté. Au lieu de cela, le HAL doit remplacer l'écran principal par un écran d'espace réservé dans ses interactions avec le framework lorsqu'un écran principal est physiquement déconnecté.

Les scénarios suivants peuvent se produire dans les box TV et les dongles TV qui disposent d'écrans connectés en externe et qui peuvent être déconnectés. Pour implémenter la prise en charge de ces scénarios, utilisez les informations du tableau ci-dessous:

Scénario Manipulation
Aucun écran connecté au démarrage
  • Envoyer un signal onHotplug(display, connection=CONNECTED) à partir du HAL de Composer vers le framework.
  • Remplacez l'état d'affichage physique dans le HAL de Composer par un état d'affichage d'espace réservé.
L'écran principal est physiquement connecté
L'écran principal est déconnecté physiquement
  • Envoyez un autre événement onHotplug(display, connection=CONNECTED) depuis le HAL Composer au framework.
  • Remplacez l'état d'affichage physique dans le HAL de Composer par un état d'affichage d'espace réservé. L'affichage de l'espace réservé doit avoir un seul mode d'affichage, afin que le framework envoie le rappel onDisplayChanged aux applications (car l'ensemble des modes compatibles a changé). Ce mode d'affichage unique doit correspondre au dernier mode actif de l'écran physique avant la déconnexion, afin que les applications ne reçoivent pas d'événements de modification de configuration.

Considérations concernant les connexions autres que HDMI

Android TV n'est compatible qu'avec les résolutions suivantes:

  • 720 x 1 280
  • 1 080 x 1 920
  • 2 160 x 3 840
  • 4 320 x 7 680

Lorsqu'un décodeur ou un dongle TV tente d'afficher une résolution non prise en charge, telle que 480i via une connexion CVBS, un message d'erreur s'affiche à l'utilisateur.

Si le décodeur ou le dongle TV dispose à la fois de connexions HDMI et non HDMI, la connexion HDMI est l'écran principal et la connexion non HDMI est inactive. Par conséquent, si la connexion HDMI est déconnectée alors que la connexion non HDMI est toujours connectée, un événement est envoyé à SurfaceFlinger et les fonctionnalités de l'écran non HDMI doivent être reflétées via getDisplayAttribute et d'autres API iComposerClient (telles que getHdrCapabilities).

Utiliser des ID de configuration séquentiels pour éviter les conditions de concurrence

Des conditions de course peuvent survenir si le HAL Composer met à jour les configurations d'affichage compatibles en même temps que le framework qui appelle setActiveConfig ou setActiveConfigWithConstraints. La solution consiste à implémenter HAL Composer pour utiliser des ID séquentiels et éviter ce problème.

Cette section décrit comment les conditions de course peuvent se produire, suivie d'informations sur l'implémentation de HAL Composer afin qu'il utilise des ID séquentiels pour éviter de telles conditions.

Considérez la séquence d'événements suivante, lorsque de nouveaux ID séquentiels ne sont PAS attribués aux nouvelles configurations d'affichage, ce qui entraîne une condition de concurrence:

  1. Les ID de configuration d'affichage compatibles sont les suivants:

    • id=1, 1 080 x 1 920 60 Hz
    • id=2, 1 080 x 1 920 50 Hz
  2. Le framework appelle setActiveConfig(display, config=1).

  3. Simultanément, le HAL de Composer traite une modification des configurations d'affichage et met à jour son état interne vers un nouvel ensemble de configurations d'affichage, comme suit:

    • id=1, 2 160 x 3 840 60 Hz
    • id=2, 2 160 x 3 840 50 Hz
    • id=3, 1 080 x 1 920, 60 Hz
    • id=4, 1 080 x 1 920, 50 Hz
  4. Le HAL de Composer envoie un événement onHotplug au framework pour l'informer que l'ensemble des modes compatibles a changé.

  5. Le HAL de Composer reçoit setActiveConfig(display, config=1) (à partir de l'étape 2).

  6. Le HAL interprète que le framework a demandé une modification de configuration vers 2 160 x 3 840 pixels à 60 Hz, alors qu'en réalité, 1 080 x 1 920 pixels à 60 Hz était souhaité.

Le processus utilisant des attributions d'ID non séquentielles se termine ici par une mauvaise interprétation de la modification de configuration souhaitée.

Configurer l'HAL de Composer pour utiliser des ID séquentiels

Pour éviter de telles conditions de course, l'OEM doit implémenter le HAL Composer comme suit:

  • Lorsque le HAL Composer met à jour les configurations d'affichage compatibles, il attribue de nouveaux ID séquentiels aux nouvelles configurations d'affichage.
  • Lorsque le framework appelle setActiveConfig ou setActiveConfigWithConstraints avec un ID de configuration non valide, le HAL de Composer ignore l'appel.

Ces étapes permettent d'éviter les conditions de concurrence, comme indiqué dans la discussion suivante.

Prenons la séquence d'événements suivante, lorsque de nouveaux ID séquentiels sont attribués aux nouvelles configurations d'affichage:

  1. Les ID de configuration d'affichage compatibles sont les suivants:

    • id=1, 1 080 x 1 920 60 Hz
    • id=2, 1 080 x 1 920 50 Hz
  2. Le framework appelle setActiveConfig(display, config=1).

  3. Lorsqu'une modification des configurations d'affichage est traitée, l'ensemble suivant d'ID de configuration est attribué à partir du prochain entier inutilisé, comme indiqué ci-dessous:

    • id=3, 2 160 x 3 840 60 Hz

    • id=4, 2 160 x 3 840 50 Hz

    • id=5, 1 080 x 1 920, 60 Hz

    • id=6, 1 080 x 1 920 50 Hz

  4. Le HAL de Composer envoie un événement onHotplug au framework pour avertir que l'ensemble des modes compatibles a été modifié.

  5. Le HAL de Composer reçoit setActiveConfig(display, config=1) (à partir de l'étape 2).

  6. Le HAL de Composer ignore l'appel, car l'ID n'est plus valide.

  7. Le framework reçoit et traite l'événement onHotplug à partir de l'étape 4. Il appelle le HAL Composer à l'aide des fonctions getDisplayConfigs et getDisplayAttribute. Avec ces fonctions, le framework identifie le nouvel ID (5) pour la résolution et la fréquence d'actualisation souhaitées de 1 080 x 1 920 et 60 Hz.

  8. Le framework envoie un autre événement setActiveConfig avec un ID mis à jour de 5.

  9. Le HAL de Composer reçoit setActiveConfig(display, config=5) à partir de l'étape 5.

  10. Le HAL interprète correctement que le framework a demandé une modification de configuration vers 1 080 x 1 920 60 Hz.

Comme indiqué dans l'exemple ci-dessus, le processus utilisant des attributions d'ID séquentielles garantit que la condition de course est évitée et que la modification de configuration d'affichage appropriée est mise à jour.