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

Winscope est un outil Web qui permet aux utilisateurs d'enregistrer, de relire 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 trace. 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 verbosité élevée. Les traces suivantes sont acceptées par Winscope :

  • EventLog : collectez 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 marquages CUJ.
  • IME : événements de trace du pipeline de l'éditeur de méthode d'entrée (IME), y compris IMS, IMMS et le client IME.
  • Entrée : tracez les événements d'entrée provenant de différentes parties du pipeline d'événements d'entrée.
  • ProtoLog : collecte les messages ProtoLog des services système et du 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 du shell : enregistrez les détails du système de transition des fenêtres et des activités.
  • SurfaceFlinger : collecte les traces SurfaceFlinger contenant des informations sur les surfaces (calques), telles que la position, la mémoire tampon et la composition.
  • Transactions : tracez l'ensemble des modifications atomiques reçues par SurfaceFlinger à l'aide de SurfaceControl pour la composition.
  • ViewCapture : capture une série de propriétés de toutes les vues des fenêtres système compatibles avec ViewCapture, comme l'UI système et le lanceur d'applications.
  • Gestionnaire de fenêtres : états 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 dumps 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 avoir un impact sur les performances, les dumps 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 plus efficace de l'état de l'appareil à des moments précis. Les dumps suivants sont acceptés par Winscope :

  • Gestionnaire de fenêtres : vider l'état d'un seul gestionnaire de fenêtres.
  • SurfaceFlinger : vider un seul instantané SurfaceFlinger.
  • Capture d'écran : collectez une capture d'écran en plus des dumps.

Ressources

Pour savoir comment compiler et exécuter Winscope, consultez Exécuter Winscope.

Pour en savoir plus sur la collecte des traces, consultez 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 scintillement et un bug signalé par un utilisateur.

Échec du test de scintillement

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

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 du cours :

    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 sur 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 :

    • Comparaison entre le résultat attendu et le résultat visible réel
    • Codes temporels pour identifier le moment où l'échec s'est produit
    • Nom de l'artefact ou du fichier associé à l'échec
    • Informations contextuelles supplémentaires permettant de comprendre et de 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 résultat indique les éléments suivants :

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

    • NotificationActivity doit être visible, mais 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 où se produit le 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 "Code temporel".

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

    Voici les noms des surfaces de l'application et de l'écran de démarrage :

    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 lancement de l'application

    Figure 3. Au lancement de l'application.

  4. Appuyez sur la flèche vers la droite pour revenir à la prochaine image où le scintillement se produit. Dans la vue des rectangles, 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 de l'é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 le 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 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 rectangle NotificationShade visible (en vert) est potentiellement le calque choisi.

  6. Pour valider cette hypothèse, sélectionnez la surface NotificationShade visible dans 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 vers la gauche pour revenir à l'image précédente (avant le scintillement) et inspecter à 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é. Comme NotificationShade se trouve devant NotificationActivity, l'application n'est pas affichée. Le NotificationShade est noir, donc l'écran devient brièvement noir, ce qui provoque le scintillement.

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

Bug signalé par un utilisateur

Il peut être difficile de déboguer les bugs signalés par les utilisateurs, car ils manquent souvent d'informations détaillées. Contrairement aux échecs des tests de scintillement, qui fournissent des codes temporels spécifiques, des détails sur les éléments et des enregistrements d'écran, 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, les seules informations fournies sont le titre L'écran a clignoté lors de la réouverture de l'application en mode écran partagé et un code temporel approximatif 18 avr. 2024 à 15:51 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 automatiquement sélectionné.

    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 de l'horodatage au format lisible.

    Boîte de dialogue "Code temporel"

    Figure 7. Boîte de dialogue "Code temporel".

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

    Voici les noms des packages :

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

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

    • Application Téléphone : com.google.android.dialer/com.google.android.dialer.extensions.GoogleDialtactsActivity#40564

    En plus des surfaces visibles (rectangles verts), un rectangle gris représentant la surface de la zone d'affichage, nommé Unknown display (Affichage 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 situées derrière. Nous supprimons le calque de l'analyse, car il n'est pas visible par l'utilisateur et ne serait pas signalé comme une animation clignotante.

    Rapport utilisateur

    Figure 8. Rapport utilisateur

  4. Une fois que vous avez identifié les surfaces impliquées dans la vue en écran partagé, utilisez la trace des transitions pour parcourir les différentes actions de l'utilisateur et trouver le scintillement. Cliquez sur l'onglet Transitions dans Winscope pour visualiser la liste des transitions lues :

    transitions

    Figure 9. Transitions.

    La transition lue pendant cette image est mise en évidence en bleu. Dans ce cas, les indicateurs de transition incluent TRANSIT_FLAG_IS_RECENTS, qui indique que l'utilisateur accède à l'écran "Récents".

  5. Cliquez sur le lien dans la colonne Heure d'envoi (2024-04-18, 15:50:57.205 dans le cas présent) pour accéder à ce point temporel et vérifier les rects dans l'onglet Surface Flinger. Vérifiez que l'état de l'appareil est correct pendant la transition en parcourant la transition avec la touche flèche vers la droite et en observant les rectangles.

    Le lanceur d'applications apparaît à 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 écran partagé (séparateur). Une frame plus tôt (15:50:57.212), le fond d'écran n'est pas visible et le séparateur s'affiche, ce qui correspond à l'apparence de l'écran partagé lorsqu'il n'est pas animé.

    Écran avant le scintillement

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

  6. Pour consulter la transition suivante, cliquez directement sur la timeline. Les états SurfaceFlinger sont représentés par une rangée de blocs bleu clair. Les transitions sont représentées par une rangée de blocs roses.

    Fin de la première transition

    Figure 11 : Fin de la première transition.

    Cliquez sur la ligne SurfaceFlinger au début de la transition suivante. 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. Parcourez 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 semble correct pour cette transition.

  7. Ignorez la transition suivante, car sa durée est très courte et il est donc peu probable qu'elle contienne un scintillement. Cliquez plutôt sur la timeline dans la ligne SurfaceFlinger, au début de la transition plus longue suivante, comme indiqué par le curseur dans l'image ci-dessous.

    fin de la deuxième transition

    Figure 12. Fin de la deuxième transition.

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

    écrans de démarrage

    Figure 13. Écrans de démarrage

  8. Précisez quelle application se trouve du mauvais côté. Ajoutez un repère à votre position actuelle en cliquant sur l'icône en forme de drapeau à côté du champ de saisie ns pour vous aider à revenir à ce frame plus tard.

    ajouter un favori

    Figure 14. Ajouter 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. Ici, les deux applications sont maintenant dans leur position finale, avec le clavier de numérotation à gauche et les contacts à droite :

    écran partagé final

    Figure 15. Écran partagé final.

  10. Cliquez sur le repère dans la timeline pour revenir à la frame où le scintillement se produit.

    chronologie des favoris

    Figure 16. Ajouter un repère à la timeline.

    Les deux applications se trouvent à droite, ce qui indique que le sélecteur est dans la mauvaise position.

  11. Cliquez sur l'écran de démarrage du sélecteur pour afficher ses propriétés. Examinez plus précisément ses propriétés de transformation dans la vue Propriétés.

    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 à ce niveau. Les colonnes "Calculé" et "Demandé" ont des valeurs différentes, ce qui indique que la transformation est héritée d'une surface parente.

  12. Désélectionnez Plat dans la vue hiérarchique pour afficher l'intégralité de l'arborescence hiérarchique, puis accédez aux nœuds parents de la surface de l'application jusqu'à ce que les transformations Calculé et Demandé soient identiques, ce qui indique que la transformation est demandée sur la surface Surface(name=Task=7934)/@0x1941191_transition-leash#40670.

  13. Vérifiez la date à laquelle la transformation a été définie pour la première fois et la valeur qui lui a été attribuée. 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éduisez les propriétés sélectionnées.

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

    Afficher les différences

    Figure 19. Afficher les différences

    La transformation est définie de IDENTITY à SCALE|TRANSLATE|ROT_270 dans ce frame pour 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 d'écran partagé du clavier de numérotation.

    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é.