Gestion du branchement à chaud

Les capacités d'affichage (telles que les modes d'affichage et les types 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 à la suite d'un signal HDMI hotplug, 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 dans le framework pour gérer le branchement à chaud et les capacités d'affichage dynamique.

Cette page décrit la gestion des branchements à chaud d'écran et des modifications des capacités d'affichage dans l'implémentation Composer HAL. Il explique également comment gérer le framebuffer associé et éviter les conditions de concurrence dans ces situations.

Mettre à jour les capacités d'affichage

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

Avant qu'Android puisse gérer correctement les modifications des capacités d'affichage, l'OEM doit implémenter Composer HAL de manière à ce qu'il utilise onHotplug(display, connection=CONNECTED) pour informer le framework de toute modification des capacités d'affichage. Une fois cette implémentation effectuée, Android gère les modifications apportées aux capacités d'affichage comme suit :

  1. Lorsqu'un changement de capacités d'affichage est détecté, le framework reçoit une notification onHotplug(display, connection=CONNECTED).
  2. À la réception de la notification, le framework supprime son état d'affichage et le recrée avec les nouvelles fonctionnalités du HAL en utilisant les méthodes getActiveConfig, getDisplayConfigs, getDisplayAttribute, getColorModes, getHdrCapabilities et getDisplayCapabilities.
  3. Une fois que le framework a recréé un nouvel état d'affichage, il envoie le rappel onDisplayChanged aux applications qui écoutent de tels événements.

Le framework réaffecte les framebuffers lors des événements onHotplug(display, connection=CONNECTED) suivants. Pour savoir comment gérer correctement la mémoire du framebuffer afin d'éviter les échecs lors de l'allocation de nouveaux framebuffers, consultez Gestion du framebuffer client.

Gérer les scénarios de connexion courants

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

Étant donné qu'il a été 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 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 décodeurs et les clés TV connectés à des écrans externes qui peuvent être déconnectés. Pour implémenter la compatibilité avec ces scénarios, utilisez les informations du tableau ci-dessous :

Scénario Manipulation
Aucun écran connecté au moment du démarrage
  • Envoyez un signal onHotplug(display, connection=CONNECTED) du HAL Composer au framework.
  • Remplacez l'état d'affichage physique dans le HAL Composer par un état d'affichage d'espace réservé.
L'écran principal est physiquement connecté
L'écran principal est physiquement déconnecté
  • Envoyez un autre événement onHotplug(display, connection=CONNECTED) du HAL Composer au framework.
  • Remplacez l'état d'affichage physique dans le HAL Composer par un état d'affichage d'espace réservé. 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 la configuration.

Considérations relatives aux connexions non 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
  • 4320 x 7680

Lorsqu'un boîtier décodeur ou un dongle TV tente d'afficher une résolution non compatible, telle que 480i sur une connexion CVBS, un message d'erreur s'affiche.

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 active, un événement est envoyé à SurfaceFlinger et les capacités de l'écran non HDMI doivent être reflétées par le biais de 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 appelle setActiveConfig ou setActiveConfigWithConstraints. La solution consiste à implémenter Composer HAL pour utiliser des ID séquentiels et éviter ce problème.

Cette section décrit comment les conditions de course peuvent se produire, puis explique comment implémenter Composer HAL afin qu'il utilise des ID séquentiels pour éviter de telles conditions.

Prenons l'exemple de la séquence d'événements suivante, dans laquelle de nouveaux ID séquentiels ne sont PAS attribués aux nouvelles configurations d'affichage, ce qui provoque une condition de concurrence :

  1. Voici les ID de configuration d'affichage acceptés :

    • id=1, 1080x1920 60 Hz
    • id=2, 1080x1920 50 Hz
  2. Le framework appelle setActiveConfig(display, config=1).

  3. Parallèlement, le HAL du compositeur traite un changement de 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, 1080x1920 50 Hz
  4. Le HAL du compositeur envoie un événement onHotplug au framework pour indiquer que l'ensemble des modes compatibles a changé.

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

  6. Le HAL interprète que le framework a demandé un changement de configuration vers 2160x3840 60 Hz, alors qu'en réalité, 1080x1920 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 Composer HAL pour utiliser des ID séquentiels

Pour éviter de telles conditions de concurrence, l'OEM doit implémenter le HAL du compositeur 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 Composer ignore l'appel.

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

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

  1. Voici les ID de configuration d'affichage acceptés :

    • id=1, 1080x1920 60 Hz
    • id=2, 1080x1920 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 suit :

    • 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, 1080x1920 50 Hz

  4. Le HAL Composer envoie un événement onHotplug au framework pour indiquer que l'ensemble des modes compatibles a changé.

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

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

  7. Le framework reçoit et traite l'événement onHotplug 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 (5).

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

  10. La HAL interprète correctement le fait que le framework a demandé un changement de configuration à 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 concurrence est évitée et que la modification de la configuration de l'affichage est correctement mise à jour.