Tracer les transitions de fenêtre à l'aide de Winscope

Winscope est un outil Web qui permet aux utilisateurs d'enregistrer, de lire et d'analyser les états de plusieurs services système pendant et après les animations et les transitions. Winscope enregistre tous les états de service système pertinents dans un fichier de suivi. En utilisant l'interface utilisateur Winscope avec le fichier de trace, vous pouvez inspecter l'état de ces services pour chaque frame d'animation, avec ou sans enregistrement d'écran, en rejouant, en parcourant et en déboguant les transitions.

Traces compatibles

Winscope permet de collecter et de représenter visuellement différentes traces ou séquences d'états de service système. Vous pouvez configurer ces traces en fonction de cas d'utilisation spécifiques, allant d'une faible surcharge à une grande lisibilité. Les traces suivantes sont compatibles avec Winscope:

  • EventLog:collecte l'enregistrement des événements de diagnostic système à l'aide de EventLog. Dans Winscope, ces informations ne sont utilisées que pour identifier et afficher les repères CUJ.
  • IME:tracez les événements du pipeline de l'éditeur de mode de saisie (IME), y compris IMS, IMMS et le client IME.
  • Entrée:permet de suivre les événements d'entrée à partir de différentes parties du pipeline d'événements d'entrée.
  • ProtoLog:collecte les messages ProtoLog des services système et le code des services système exécutés dans les processus client.
  • Enregistrement d'écran:collectez un enregistrement d'écran en plus des traces.
  • Transitions de shell:enregistre les détails du système de transition de fenêtre et d'activité.
  • SurfaceFlinger:collecte des traces SurfaceFlinger contenant des informations sur les surfaces (couches), telles que la position, le tampon et la composition.
  • Transactions:permet de suivre l'ensemble des modifications atomiques reçues par SurfaceFlinger à l'aide de SurfaceControl pour la composition.
  • ViewCapture:capture une plage de propriétés de toutes les vues à partir des fenêtres système compatibles avec ViewCapture, comme l'UI système et le lanceur.
  • Gestionnaire de fenêtres:tracez les états du gestionnaire de fenêtres contenant des informations sur les fenêtres, y compris les événements d'entrée et de mise au point, l'orientation de l'écran, les transitions, les animations, le positionnement et les transformations.

Dumps compatibles

Winscope peut collecter et afficher des vidages d'état, qui sont des instantanés de l'état de l'appareil pris à des moments spécifiques définis par l'utilisateur. Contrairement aux traces, qui sont collectées en continu pendant l'utilisation de l'appareil et peuvent affecter les performances, les vidages ne sont effectués qu'à ces moments définis par l'utilisateur, ce qui garantit que les performances et la verbosité ne sont pas compromises. Cela permet une analyse plus ciblée et efficace de l'état de l'appareil à des moments spécifiques. Les fichiers de dump suivants sont compatibles avec Winscope:

  • Gestionnaire de fenêtres:vidage d'un seul état de gestionnaire de fenêtres.
  • SurfaceFlinger:vidage d'un seul instantané SurfaceFlinger.
  • Capture d'écran:collectez une capture d'écran avec les vidages.

Ressources

Pour en savoir plus sur la création et l'exécution de Winscope, consultez Exécuter Winscope.

Pour en savoir plus sur la collecte de traces, consultez la section Capturer des traces.

Pour savoir comment charger des traces à l'aide de l'interface utilisateur Web Winscope, consultez Charger des traces.

Pour en savoir plus sur l'analyse des traces, consultez Analyser les traces.

Exemples

L'exemple suivant décrit comment déboguer un échec de test de clignotement et un bug signalé par un utilisateur.

Échec du test de clignotement

Cet exemple montre comment utiliser Winscope pour déboguer un échec de test de clignotement.

Examiner l'échec du test

Suivez ces étapes pour déterminer le type de problème et examiner le message d'échec du test.

  1. Déterminez le type de problème en examinant le nom du test et de la classe.

    Nom du test et de la classe:

    FlickerTestsNotification com.android.server.wm.flicker.notification.OpenAppFromLockscreenNotificationColdTest#appLayerBecomesVisible[ROTATION_0_GESTURAL_NAV]
    

    Type de problème :

    • Le CUJ fait référence au lancement d'une application à partir d'une notification de l'écran de verrouillage (OpenAppFromLockscreenNotificationColdTest).

    • Le test s'attend à ce que l'application devienne visible (#appLayerBecomesVisible).

  2. Examinez le message d'échec du test, qui fournit des informations complètes sur l'échec, y compris les éléments suivants:

    • Comparaison entre le résultat attendu et le résultat visible
    • Horodatages pour vous aider à identifier le moment où l'échec s'est produit
    • Nom de l'artefact ou du fichier associé à l'échec
    • Informations contextuelles supplémentaires utiles pour comprendre et déboguer l'échec
    android.tools.flicker.subject.exceptions.IncorrectVisibilityException: com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity# should be visible
    
    Where?
        Timestamp(UNIX=2024-05-10T11:04:14.227572545(1715339054227572545ns), UPTIME=37m21s184ms79178ns(2241184079178ns), ELAPSED=0ns)
    
    What?
        Expected: com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#
        Actual: [e636ecd com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#3457: Buffer is empty, Visible region calculated by Composition Engine is empty, com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#3458: Visible region calculated by Composition Engine is empty]
    
    Other information
        Artifact: FAIL__OpenAppFromLockscreenNotificationColdTest_ROTATION_0_GESTURAL_NAV.zip
    
    Check the test run artifacts for trace files
    
        at android.tools.flicker.subject.layers.LayerTraceEntrySubject.isVisible(LayerTraceEntrySubject.kt:187)
        at android.tools.flicker.subject.layers.LayersTraceSubject$isVisible$1$1.invoke(LayersTraceSubject.kt:151)
        at android.tools.flicker.subject.layers.LayersTraceSubject$isVisible$1$1.invoke(LayersTraceSubject.kt:150)
        at android.tools.flicker.assertions.NamedAssertion.invoke(NamedAssertion.kt:32)
        at android.tools.flicker.assertions.CompoundAssertion.invoke(CompoundAssertion.kt:42)
        at android.tools.flicker.assertions.AssertionsChecker.test(AssertionsChecker.kt:79)
        at android.tools.flicker.subject.FlickerTraceSubject.forAllEntries(FlickerTraceSubject.kt:59)
        at android.tools.flicker.assertions.AssertionDataFactory$createTraceAssertion$closedAssertion$1.invoke(AssertionDataFactory.kt:46)
        at android.tools.flicker.assertions.AssertionDataFactory$createTraceAssertion$closedAssertion$1.invoke(AssertionDataFactory.kt:43)
        at android.tools.flicker.assertions.AssertionDataImpl.checkAssertion(AssertionDataImpl.kt:33)
        at android.tools.flicker.assertions.ReaderAssertionRunner.doRunAssertion(ReaderAssertionRunner.kt:35)
        at android.tools.flicker.assertions.ReaderAssertionRunner.runAssertion(ReaderAssertionRunner.kt:29)
        at android.tools.flicker.assertions.BaseAssertionRunner.runAssertion(BaseAssertionRunner.kt:36)
        at android.tools.flicker.legacy.LegacyFlickerTest.doProcess(LegacyFlickerTest.kt:59)
        at android.tools.flicker.assertions.BaseFlickerTest.assertLayers(BaseFlickerTest.kt:89)
        at com.android.server.wm.flicker.notification.OpenAppTransition.appLayerBecomesVisible_coldStart(OpenAppTransition.kt:51)
        at com.android.server.wm.flicker.notification.OpenAppFromNotificationColdTest.appLayerBecomesVisible(OpenAppFromNotificationColdTest.kt:64)
    

    Cet exemple de sortie indique ce qui suit:

    • Le problème se produit à 2024-05-10T11:04:14.227572545.

    • NotificationActivity devrait être visible, mais il ne l'est pas.

    • Le nom du fichier d'artefact contenant les traces de débogage est FAIL__OpenAppFromLockscreenNotificationColdTest_ROTATION_0_GESTURAL_NAV.

Déboguer

Pour déterminer la cause du scintillement, procédez comme suit:

  1. Téléchargez les fichiers de trace et chargez-les dans Winscope. Winscope s'ouvre avec SurfaceFlinger sélectionné automatiquement:

    Page de destination Winscope avec vue SurfaceFlinger

    Figure 1 : Page de destination Winscope avec vue SurfaceFlinger.

  2. Accédez au code temporel à l'origine du problème en copiant et en collant le code temporel du message d'exception dans le champ de code temporel. Vous pouvez copier l'horodatage au format lisible (2024-05-10T11:04:14.227572545) et le coller dans le premier champ, ou copier l'horodatage en nanosecondes (1715339054227572545ns) et le coller dans le deuxième champ.

    Boîte de dialogue "Code temporel"

    Figure 2. Boîte de dialogue de code temporel.

  3. Appuyez sur la flèche vers la gauche pour accéder au frame précédent. Dans cet état, l'application NotificationActivity s'affiche correctement dans la vidéo. Les surfaces de l'application et de l'écran de démarrage sont visibles, comme indiqué par leurs rectangles verts dans la vue 3D et le chip V sur leurs éléments de hiérarchie.

    Les noms des surfaces de l'application et de l'écran de démarrage sont les suivants:

    com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#3458`
    
    Splash Screen com.android.server.wm.flicker.testapp#3453
    

    Cela indique que l'application était en cours de lancement lorsque l'écran est devenu noir et que cet événement se produit pendant le lancement de l'application, car l'écran de démarrage est toujours visible:

    Au démarrage de l'application

    Figure 3. Au démarrage de l'application.

  4. Appuyez sur la flèche vers la droite pour revenir au frame suivant, où le scintillement se produit. Dans la vue des rectangles, le NotificationShade s'affiche à l'écran au lieu de l'application. Les surfaces suivantes sont affichées dans ce frame:

    • Superpositions de décoration d'écran (en haut et en bas)
    • Barre de navigation
    • Emplacement du pointeur (à partir de l'enregistrement d'écran)

      Activité de clignotement

      Figure 4. Activité de scintillement.

  5. Sélectionnez l'activité de l'application dans la vue hiérarchique. Si vous ne la trouvez pas, désactivez l'option Afficher uniquement V, puis inspectez la vue des propriétés.

    Le nom de la surface de l'application est le suivant:

    com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#3458`
    

    Propriétés de l'application

    Figure 5. Propriétés de l'application.

    Bien que l'activité de l'application soit définie sur "visible" et "opaque", la surface n'est pas affichée en raison d'une erreur Invisible due to: null visible region. Cela se produit parce qu'une autre surface opaque a été placée devant elle lors de la composition. Cette hypothèse découle du fait que le rectangle NotificationShade se trouve devant le rectangle NotificationActivity dans la vue 3D, et que le NotificationShade visible (vert) est potentiellement la couche choisie.

  6. Pour valider cette hypothèse, sélectionnez la surface NotificationShade visible sur le frame actuel et vérifiez ses propriétés. Les indicateurs sont définis sur OPAQUE|ENABLE_BACKPRESSURE (0x102). Le nom de la surface NotificationShade est NotificationShade#3447. Appuyez ensuite sur la flèche de gauche pour revenir au frame précédent (avant le clignotement) et inspectez à nouveau les propriétés de la surface NotificationShade. Notez qu'au lieu d'être OPAQUE, la surface ne comporte que l'indicateur ENABLE_BACKPRESSURE (0x100). Cela confirme que NotificationShade devient opaque avant que le lancement de l'application ne soit complètement terminé. Étant donné que NotificationShade se trouve devant NotificationActivity, l'application ne s'affiche pas. NotificationShade est noir, donc l'écran passe brièvement au noir, ce qui provoque le scintillement.

  7. Identifiez dans le code pourquoi NotificationShade devient opaque trop tôt.

Bug signalé par l'utilisateur

Les bugs signalés par les utilisateurs peuvent être difficiles à déboguer, car ils manquent souvent d'informations détaillées. Contrairement aux échecs de test de clignotement, qui fournissent des codes temporels, des détails sur les éléments et des enregistrements d'écran spécifiques, les bugs signalés par les utilisateurs n'incluent généralement qu'une brève description du problème.

Dans notre étude de cas, la seule information fournie est le titre Écran clignotant lors de la réouverture de l'application depuis l'écran partagé et un code temporel approximatif de 18 avril 2024 15h51 GMT-04:00.

Pour déboguer un bug signalé par un utilisateur, procédez comme suit:

  1. Chargez le fichier de trace dans Winscope. Winscope s'ouvre avec SurfaceFlinger sélectionné automatiquement.

    Page de destination Winscope avec vue SurfaceFlinger

    Figure 6. Page de destination Winscope avec vue SurfaceFlinger.

  2. Accédez à l'horodatage approximatif signalé par l'utilisateur, ici 3:50 PM GMT-04:00, en saisissant 15:50:00 dans le champ d'horodatage lisible par l'homme.

    Boîte de dialogue "Code temporel"

    Figure 7. Boîte de dialogue de code temporel.

  3. Utilisez la vue rects pour identifier ce qui a été dessiné à l'écran. Pour une meilleure vue, utilisez le curseur Rotation pour modifier la perspective des rectangles. En cochant Afficher uniquement V et Plat dans la vue Hiérarchie, le fond d'écran, la superposition de décoration d'écran, le format letterbox, le lanceur, les surfaces de contacts et le clavier sont visibles.

    Les noms des packages sont les suivants:

    • Lanceur: com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#40602

    • Contacts : com.google.android.contacts/com.android.contacts.activities.PeopleActivity#40565

    • Numéroteur: com.google.android.dialer/com.google.android.dialer.extensions.GoogleDialtactsActivity#40564

    En plus des surfaces visibles (rectangles verts), un rectangle gris, qui représente la surface de la zone d'affichage, nommé Écran inconnu, s'affiche. Pour améliorer la visibilité, cliquez sur (icône de visibilité) à côté de la surface ScreenDecorHwcOverlay#64 pour masquer le rectangle correspondant et afficher les surfaces derrière. Nous supprimons la superposition pour l'analyse, car elle n'est pas visible par l'utilisateur et ne sera pas signalée comme une animation clignotante.

    Rapport "Utilisateur"

    Figure 8. Rapport "Utilisateur".

  4. Après avoir identifié les surfaces impliquées dans l'affichage en écran partagé, utilisez la trace des transitions pour passer en revue les différentes actions de l'utilisateur et trouver le scintillement. Cliquez sur l'onglet Transitions dans Winscope pour afficher la liste des transitions jouées:

    transitions

    Figure 9. Transitions.

    La transition lue pendant ce frame est mise en surbrillance en bleu. Dans ce cas, les indicateurs de transition incluent TRANSIT_FLAG_IS_RECENTS, ce qui indique que l'utilisateur accède à l'écran "Recents" (Éléments récents).

  5. Cliquez sur le lien dans la colonne Heure de distribution (2024-04-18, 15:50:57.205 dans ce cas) pour accéder à ce moment et vérifier les rectangles dans l'onglet Surface Flinger. Vérifiez que l'état de l'appareil est correct pendant la transition en parcourant la transition à l'aide de la touche fléchée vers la droite et en observant les rectangles.

    Le lanceur d'applications s'affiche à 15:50:57.278, mais l'animation ne démarre pas à ce moment-là. Le fond d'écran est déjà visible, car rien n'est dessiné entre les applications en mode écran partagé (séparateur). Une image plus tôt (15:50:57.212), le fond d'écran n'est pas visible et le séparateur est affiché, ce qui correspond à l'apparence de l'écran partagé lorsqu'il n'est pas animé.

    Écran avant le clignotement

    Figure 10. Écran avant l'événement de clignotement.

  6. Pour consulter la prochaine transition, cliquez directement sur la chronologie. Les états de SurfaceFlinger sont représentés par une ligne de blocs bleu clair. Les transitions sont représentées par une ligne de blocs roses.

    Fin de la première transition

    Figure 11 : Fin de la première transition.

    Cliquez sur la ligne SurfaceFlinger à la position de début de la prochaine transition. Dans la figure 11, la position verticale du curseur est indiquée par la fine ligne bleue. L'arrière-plan bleu clair de la ligne SurfaceFlinger indique sa position horizontale. Passez en revue la transition à l'aide de la touche fléchée vers la droite pour voir si un scintillement se produit. Vérifiez que l'appareil est adapté à cette transition.

  7. Ignorez la transition suivante, car sa durée est très courte et qu'elle est donc peu susceptible de contenir un clignotement. Cliquez plutôt sur la timeline dans la ligne SurfaceFlinger à la position de début de la prochaine transition plus longue, comme indiqué par le curseur dans l'image suivante.

    fin de la deuxième transition

    Figure 12. Fin de la deuxième transition.

    Au cours de cette transition, à 15:51:13.239, observez que les calques Splash Screen des deux applications, des contacts et du clavier se trouvent du même côté de l'écran:

    écrans de démarrage

    Figure 13. Écrans de démarrage

  8. Indiquez l'application qui se trouve du mauvais côté. Ajoutez un favori à votre position actuelle en cliquant sur l'icône en forme de drapeau à côté du champ de saisie ns pour revenir plus tard à ce cadre.

    ajouter un favori

    Figure 14. Ajoutez un favori.

  9. Accédez à un frame à la fin de la transition en cliquant directement sur la timeline, par exemple sur 15:51:13.859. Les deux applications sont maintenant dans leur position finale, avec le clavier à gauche et les contacts à droite:

    écran partagé final

    Figure 15. Écran partagé final.

  10. Cliquez sur l'icône du repère dans la chronologie pour revenir au frame avec le scintillement.

    chronologie des favoris

    Figure 16. Chronologie des favoris.

    Les deux applications se trouvent à droite, ce qui indique que le clavier est mal positionné.

  11. Cliquez sur l'écran de démarrage du clavier pour afficher ses propriétés. Examinez spécifiquement ses propriétés de transformation dans la vue Propriétés sélectionnée.

    Propriétés de transformation

    Figure 17. Propriétés de transformation.

    La transformation calculée est appliquée à cette surface, mais n'est pas définie comme ce niveau. Les colonnes calculées et demandées ont des valeurs différentes, ce qui indique que la transformation est héritée d'une surface parente.

  12. Désélectionnez Flat (Plat) dans la vue de hiérarchie pour afficher l'ensemble de l'arborescence de la hiérarchie, puis accédez aux nœuds parents de la surface de l'application jusqu'à ce que les transformations Calculated (Calculées) et Requested (Requêtées) soient identiques, ce qui indique que la transformation est requise sur la surface Surface(name=Task=7934)/@0x1941191_transition-leash#40670.

  13. Vérifiez quand la transformation a été définie pour la première fois et à quelle valeur. Réduisez les propriétés sélectionnées en cliquant sur l'icône à côté du titre:

    réduire les propriétés sélectionnées

    Figure 18. Réduire les propriétés sélectionnées

  14. Sélectionnez Afficher le différentiel dans la vue Proto Dump pour mettre en surbrillance les propriétés modifiées dans ce frame. Saisissez transform dans le champ de recherche textuelle pour filtrer les propriétés:

    show diff

    Figure 19. Afficher le différentiel.

    La transformation est définie de IDENTITY à SCALE|TRANSLATE|ROT_270 dans ce frame pour le transition-leash.

    Ces informations montrent que le scintillement s'est produit lorsque la transformation a été appliquée à la laisse d'animation de l'application du clavier en mode écran partagé.

    Identification du scintillement

    Figure 20. Identification du scintillement.

  15. Identifiez dans le code pourquoi cette transformation est définie sur la laisse de transition en écran partagé.