ViewCapture dans les applications système

ViewCapture est un outil logiciel qui capture les propriétés des vues (telles que l'emplacement, la taille, l'échelle et la visibilité) associées aux fenêtres auxquelles il est associé. ViewCapture capture des informations sur les différentes vues d'une fenêtre et leurs propriétés, ce qui vous permet de connaître l'état de l'expérience utilisateur à des moments spécifiques et de suivre les changements au fil du temps.

Les enregistrements d'écran peuvent visualiser l'état d'une vue à un moment donné et montrer comment il évolue, mais ils exigent des ressources de processeur importantes et peuvent avoir un impact sur les performances. L'outil ViewCapture a un impact moindre sur les ressources et peut être activé plus fréquemment. De plus, ViewCapture affiche les visualisations image par image au niveau de la vue, ce qui facilite l'inspection de l'état de la vue à des moments spécifiques par rapport aux enregistrements d'écran.

Cette page explique comment intégrer ViewCapture dans les applications système.

Utiliser

ViewCapture.java implémente une instance de onDrawListener et collecte une trace ViewCapture pendant le processus de dessin. Chaque redessin de frame déclenche une traversée de la hiérarchie de l'arborescence des vues à partir de la vue racine de la fenêtre. ViewCapture utilise des méthodes getter publiques View.java pour récupérer et copier des valeurs dans un thread en arrière-plan afin d'améliorer les performances. L'implémentation de ViewCapture optimise ce processus en vérifiant si une vue est sale ou invalidée à l'aide de captureViewTree, ce qui évite d'explorer l'ensemble de la hiérarchie des vues. captureViewTree n'est disponible que pour les applications système et fait partie de l'API UnsupportedAppUsage. L'utilisation de cette API est limitée aux applications basées sur leur version de SDK cible.

Limites

Les sections suivantes décrivent les limites de performances et de mémoire lors de l'exécution de ViewCapture.

Performances

Le coût moyen du thread principal pour les performances de ViewCapture est de 195 μs. Toutefois, dans le pire des cas, cela peut prendre environ cinq millisecondes. Reportez-vous à la tranche vc#onDraw dans la trace Perfetto.

Les frais généraux sont principalement dus aux actions suivantes:

  1. L'exploration de la hiérarchie coûte 50 μs, même après avoir été élaguée.
  2. Extraire des objets d'un alloueur de liste libre pour stocker des copies de propriétés de vue coûte 20 μs.
  3. La récupération de chaque valeur de propriété via une fonction getter entraîne de nombreux appels de fonction supplémentaires par vue, ce qui coûte 110 μs.

Par conséquent, l'activation de ViewCapture dans le traçage permanent (AOT) a un impact négatif sur les performances du système et entraîne des à-coups. En raison de ces limites de performances et de mémoire, cette approche n'est pas prête pour l'AOT. Nous vous recommandons d'utiliser ViewCapture uniquement pour le débogage en laboratoire et local.

Mémoire

La méthode de Perfetto pour les traces ViewCapture utilise une seule mémoire tampon circulaire, qui a une empreinte mémoire prédéfinie pour éviter une utilisation excessive de la mémoire. Cette approche évite une consommation excessive de mémoire en évitant d'utiliser des tampons de anneau distincts pour chaque fenêtre, mais ne résout pas le problème de stockage de l'ensemble de la hiérarchie des vues pour chaque état dans Perfetto pour chaque frame. L'enregistrement d'une seule fenêtre, telle que NexusLauncher, peut générer plus de 30 secondes de données ViewCapture dans un tampon de 10 Mo. Toutefois, la capture de plus de 30 fenêtres à partir de l'UI du système nécessite soit une mémoire tampon plus importante, soit une période d'enregistrement considérablement plus courte.

Instructions

Suivez ces instructions pour intégrer ViewCapture dans les applications système:

  1. Ajoutez la dépendance à votre fichier Android.bp, comme indiqué dans le code du lanceur.

    android_library {
        name: "YourLib",
        static_libs: [
              ...
            "//frameworks/libs/systemui:view_capture",
              ...
        ],
        platform_apis: true,
        privileged: true,
    }
    
  2. Créez une instance ViewCapture lorsque vous créez votre fenêtre, par exemple:

    • Exemple 1:

      private SafeCloseable mViewCapture;
      
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        ...
        mViewCapture = ViewCaptureFactory.getInstance(this).startCapture(getWindow());
      }
      
    • Exemple 2:

      private SafeCloseable mViewCapture;
      
      @Override
      protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (enableViewCaptureTracing()) {
            mViewCaptureCloseable = ViewCaptureFactory.getInstance(getContext())
              .startCapture(getRootView(), ".NotificationShadeWindowView");
        }
        ...
      }
      
  3. Fermez l'instance ViewCapture lorsque vous supprimez votre fenêtre, comme indiqué dans les exemples suivants:

    • Exemple 1:

      @Override
      public void onDestroy() {
        ...
        if (mViewCapture != null) mViewCapture.close();
      }
      
    • Exemple 2:

      @Override
      protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mViewCaptureCloseable != null) {
            mViewCaptureCloseable.close();
       }
        ...
      }