Cómo hacer un seguimiento de las transiciones de ventanas con Winscope

Winscope es una herramienta web que permite a los usuarios registrar, reproducir y analizar los estados de varios servicios del sistema durante las animaciones y transiciones, y después de ellas. Winscope registra todos los estados pertinentes del servicio del sistema en un archivo de registro. Con la IU de Winscope y el archivo de registro, puedes inspeccionar el estado de estos servicios para cada fotograma de animación, con o sin una grabación de pantalla, reproduciendo, avanzando y depurando las transiciones.

Registros admitidos

Winscope permite recopilar y representar visualmente varios registros o secuencias de estados de servicios del sistema. Puedes configurar estos registros para que se adapten a casos de uso específicos, desde una sobrecarga baja hasta una alta verbosidad. Winscope admite los siguientes registros:

  • EventLog: Recopila el registro de eventos de diagnóstico del sistema con EventLog. En Winscope, esta información solo se usa para identificar y mostrar las marcas de CUJ.
  • IME: Registra eventos del canal de procesamiento del editor de métodos de entrada (IME), incluidos IMS, IMMS y el cliente de IME.
  • Entrada: Registra eventos de entrada de varias partes de la canalización de eventos de entrada.
  • ProtoLog: Recopila mensajes de ProtoLog de los servicios del sistema y el código de los servicios del sistema que se ejecutan en procesos del cliente.
  • Grabación de pantalla: Recopila una grabación de pantalla junto con los registros.
  • Transiciones de shell: Registra los detalles del sistema de transición de ventanas y actividades.
  • SurfaceFlinger: Recopila registros de SurfaceFlinger que contienen información sobre superficies (capas), como la posición, el búfer y la composición.
  • Transacciones: Realiza un seguimiento del conjunto de cambios atómicos que recibe SurfaceFlinger con SurfaceControl para la composición.
  • ViewCapture: Captura un rango de propiedades de todas las vistas de las ventanas del sistema que admiten ViewCapture, como la IU del sistema y el Selector.
  • Administrador de ventanas: Registra los estados del administrador de ventanas que contienen detalles relacionados con las ventanas, incluidos los eventos de entrada y enfoque, la orientación de la pantalla, las transiciones, las animaciones, el posicionamiento y las transformaciones.

Volcados admitidos

Winscope puede recopilar y mostrar volcados de estado, que son instantáneas del estado del dispositivo tomadas en momentos específicos definidos por el usuario. A diferencia de los registros, que se recopilan de forma continua durante el uso del dispositivo y pueden afectar el rendimiento, los volcados solo se toman en estos momentos definidos por el usuario, lo que garantiza que no se vea comprometido el rendimiento ni la verbosidad. Esto permite un análisis más enfocado y eficiente del estado del dispositivo en momentos específicos. Winscope admite los siguientes volcados:

  • Administrador de ventanas: Volca un solo estado del administrador de ventanas.
  • SurfaceFlinger: Genera un volcado de una sola instantánea de SurfaceFlinger.
  • Captura de pantalla: Recopila una captura de pantalla junto con los volcados.

Recursos

Consulta Cómo ejecutar Winscope para obtener información sobre cómo compilar y ejecutar Winscope.

Consulta Cómo registrar capturas para obtener información sobre la recopilación de registros.

Consulta Cómo cargar registros para obtener información sobre cómo cargar registros con la IU web de Winscope.

Consulta Cómo analizar seguimientos para obtener información sobre el análisis de seguimientos.

Ejemplos

En el siguiente ejemplo, se describe cómo depurar una falla en una prueba de parpadeo y un error informado por el usuario.

Error en la prueba de parpadeo

En este ejemplo, se muestra cómo usar Winscope para depurar una falla en la prueba de parpadeo.

Examina la falla de la prueba

Sigue estos pasos para determinar el tipo de problema y examinar el mensaje de error de la prueba.

  1. Para determinar el tipo de problema, examina el nombre de la prueba y de la clase.

    Nombre de la prueba y la clase:

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

    Tipo de problema:

    • El CUJ se refiere al inicio de una app desde una notificación de la pantalla de bloqueo (OpenAppFromLockscreenNotificationColdTest).

    • La prueba espera que la app se haga visible (#appLayerBecomesVisible).

  2. Examina el mensaje de falla de la prueba, que proporciona información integral sobre la falla, incluido lo siguiente:

    • Comparación entre el resultado esperado y el resultado visible real
    • Marcas de tiempo para ayudar a identificar el momento en que ocurrió la falla
    • Nombre del artefacto o archivo asociado con la falla
    • Información contextual adicional pertinente para comprender y depurar la falla
    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)
    

    En este ejemplo de resultado, se indica lo siguiente:

    • El problema ocurre en 2024-05-10T11:04:14.227572545.

    • Se espera que NotificationActivity sea visible, pero no lo es.

    • El nombre del archivo de artefacto que contiene los registros para la depuración es FAIL__OpenAppFromLockscreenNotificationColdTest_ROTATION_0_GESTURAL_NAV.

Depuración

Sigue estos pasos para determinar la causa del parpadeo:

  1. Descarga los archivos de registro y cárgalos en Winscope. Winscope se abre con SurfaceFlinger seleccionado automáticamente:

    Página de destino de Winscope con la vista de SurfaceFlinger

    Figura 1: Página de destino de Winscope con la vista de SurfaceFlinger.

  2. Para navegar a la marca de tiempo en la que ocurre el problema, copia y pega la marca de tiempo del mensaje de excepción en el campo de marca de tiempo. Puedes copiar la marca de tiempo en formato legible (2024-05-10T11:04:14.227572545) y pegarla en el primer campo, o bien copiar la marca de tiempo en nanosegundos (1715339054227572545ns) y pegarla en el segundo campo.

    Diálogo de marca de tiempo

    Figura 2: Es el diálogo de marca de tiempo.

  3. Presiona la tecla de flecha hacia la izquierda para navegar al fotograma anterior. En este estado, la app de NotificationActivity se muestra correctamente en el video, y se ven tanto la app como las superficies de la pantalla de presentación, indicadas por sus rectángulos verdes en la vista 3D y el chip V en sus elementos de jerarquía.

    Los nombres de la app y de la pantalla de presentación son los siguientes:

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

    Esto indica que la app se estaba iniciando cuando la pantalla se puso negra y que este evento ocurre durante el inicio de la app, ya que la pantalla de presentación aún está visible:

    Al iniciar la app

    Figura 3: Al iniciar la app

  4. Presiona la tecla de flecha hacia la derecha para volver al siguiente fotograma, en el que se produce el parpadeo. En la vista de rectángulos, se muestra NotificationShade en la pantalla, en lugar de la app. En este fotograma, se muestran las siguientes superficies:

    • Superposiciones de decoración de pantalla (parte superior e inferior)
    • Barra de navegación
    • Ubicación del puntero (de la grabación de pantalla)

      Actividad de parpadeo

      Figura 4: Actividad de parpadeo

  5. Selecciona la actividad de la app en la vista de jerarquía. Si no lo encuentras, desactiva Mostrar solo V y, luego, inspecciona la vista de propiedades.

    El nombre de la superficie de la app es el siguiente:

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

    Propiedades de la app

    Figura 5: Son las propiedades de la app.

    Aunque la actividad de la app está configurada como visible y opaca, no se muestra la superficie debido a un error de Invisible due to: null visible region. Esto ocurre porque se colocó otra superficie opaca delante de ella durante la composición. Esta hipótesis se basa en que el rectángulo NotificationShade está delante del rectángulo NotificationActivity en la vista 3D, y el NotificationShade visible (verde) podría ser la capa elegida.

  6. Para validar esta hipótesis, selecciona la superficie NotificationShade visible en el fotograma actual y verifica sus propiedades. Las marcas se establecen en OPAQUE|ENABLE_BACKPRESSURE (0x102). El nombre de la superficie NotificationShade es NotificationShade#3447. A continuación, presiona la flecha hacia la izquierda para volver al fotograma anterior (antes del parpadeo) y, luego, inspecciona las propiedades de la superficie NotificationShade nuevamente. Observa que, en lugar de ser OPAQUE, la superficie solo tiene la marca ENABLE_BACKPRESSURE (0x100). Esto confirma que NotificationShade se vuelve opaco antes de que se complete el inicio de la app. Como NotificationShade está delante de NotificationActivity, no se muestra la app. El NotificationShade es negro, por lo que la pantalla se oscurece brevemente, lo que provoca el parpadeo.

  7. Identifica en el código por qué NotificationShade se vuelve opaco demasiado pronto.

Error informado por el usuario

Los errores que informan los usuarios pueden ser difíciles de depurar porque a menudo carecen de información detallada. A diferencia de los errores de la prueba de parpadeo, que proporcionan marcas de tiempo específicas, detalles de los elementos y grabaciones de pantalla, los errores que informan los usuarios suelen incluir solo una breve descripción del problema.

En nuestro caso de estudio, la única información proporcionada es el título La pantalla parpadeó al volver a abrir la app desde la pantalla dividida y una marca de tiempo aproximada de 18 de abril de 2024, 3:51 p.m. (GMT-4).

Sigue estos pasos para depurar un error que informó un usuario:

  1. Carga el archivo de registro en Winscope. Winscope se abre con SurfaceFlinger seleccionado automáticamente.

    Página de destino de Winscope con la vista de SurfaceFlinger

    Figura 6: Página de destino de Winscope con la vista de SurfaceFlinger.

  2. Para navegar a la marca de tiempo aproximada que informó el usuario, en este caso 3:50 PM GMT-04:00, ingresa 15:50:00 en el campo de marca de tiempo legible.

    Diálogo de marca de tiempo

    Figura 7: Es el diálogo de marca de tiempo.

  3. Usa la vista de rectángulos para identificar qué se dibujó en la pantalla. Para obtener una mejor vista, usa el control deslizante Rotación para cambiar la perspectiva de los rectángulos. Si marcas Mostrar solo V y Plano en la vista Hierarchy, se verán el fondo de pantalla, la superposición de decoración de la pantalla, el formato letterbox, el selector, los contactos y el marcador.

    Los nombres de los paquetes son los siguientes:

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

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

    • Marcador: com.google.android.dialer/com.google.android.dialer.extensions.GoogleDialtactsActivity#40564

    Además de las superficies visibles (rectángulos verdes), se muestra un rectángulo gris, que representa la superficie del área de visualización, llamado Unknown display. Para mejorar la visibilidad, haz clic en el ícono (Ícono de visibilidad) junto a la superficie ScreenDecorHwcOverlay#64 para ocultar su rectángulo correspondiente y revelar las superficies que se encuentran detrás. Quitamos la capa superpuesta para el análisis porque no es visible para el usuario y no se informaría como una animación parpadeante.

    Informe de usuario

    Figura 8: Informe de usuario

  4. Después de identificar qué superficies están involucradas en la vista de pantalla dividida, usa el registro de Transitions para revisar varias acciones del usuario y encontrar el parpadeo. Haz clic en la pestaña Transitions en Winscope para visualizar la lista de transiciones reproducidas:

    transiciones

    Figura 9: Transitions.

    La transición que se reproduce durante este fotograma se destaca en azul. En este caso, las marcas de transición incluyen TRANSIT_FLAG_IS_RECENTS, que indica que el usuario está ingresando a la pantalla de Recientes.

  5. Haz clic en el vínculo de la columna Dispatch Time (en este caso, 2024-04-18, 15:50:57.205) para navegar a ese punto en el tiempo y verificar los rectángulos en la pestaña Surface Flinger. Confirma la corrección del estado del dispositivo durante la transición. Para ello, avanza por la transición con la tecla de flecha hacia la derecha y observa los rectángulos.

    El selector aparece a las 15:50:57.278, pero la animación no comienza en ese momento. El fondo de pantalla ya es visible porque no se dibuja nada entre las apps de pantalla dividida (divisor). Un fotograma antes (15:50:57.212), no se ve el fondo de pantalla y se muestra el divisor, que es el aspecto de la pantalla dividida cuando no se anima.

    Pantalla antes del parpadeo

    Figura 10: Es la pantalla antes del evento de parpadeo.

  6. Para ver la siguiente transición, haz clic directamente en la línea de tiempo. Los estados de SurfaceFlinger se representan con una fila de bloques celestes. Las transiciones se representan con una fila de bloques rosas.

    Final de la primera transición

    Figura 11: Es el final de la primera transición.

    Haz clic en la fila SurfaceFlinger en la posición inicial de la siguiente transición. En la figura 11, la posición vertical del cursor se indica con la línea azul delgada. El fondo celeste claro de la fila SurfaceFlinger muestra su posición horizontal. Recorre la transición con la tecla de flecha hacia la derecha para ver si se produce un parpadeo. Confirma que el dispositivo se vea correctamente para esta transición.

  7. Omite la siguiente transición, ya que su duración es muy corta, por lo que es poco probable que contenga un parpadeo. En su lugar, haz clic en la línea de tiempo en la fila de SurfaceFlinger en la posición inicial de la siguiente transición más larga, como lo indica el cursor en la siguiente imagen.

    Final de la segunda transición

    Figura 12: Es el final de la segunda transición.

    Durante esta transición, en 15:51:13.239, observa que las capas de Splash Screen para ambas apps, los contactos y el marcador, se encuentran en el mismo lado de la pantalla:

    pantallas de presentación

    Figura 13: Pantallas de presentación

  8. Aclara qué app está en el lado incorrecto. Para agregar un marcador a tu posición actual, haz clic en el ícono de la marca junto al campo de entrada ns para volver a este fotograma más adelante.

    Agregar a favoritos

    Figura 14: Agregar a favoritos

  9. Para navegar a un fotograma al final de la transición, haz clic directamente en la línea de tiempo, por ejemplo, en 15:51:13.859. Aquí, las dos apps están en su posición final, con el marcador a la izquierda y los contactos a la derecha:

    pantalla dividida final

    Figura 15: Pantalla dividida final.

  10. Haz clic en la marca del marcador en la línea de tiempo para volver al fotograma con el parpadeo.

    línea de tiempo de favoritos

    Figura 16: Marcar la línea de tiempo

    Ambas apps se encuentran a la derecha, lo que indica que el dial está en la posición incorrecta.

  11. Haz clic en la pantalla de presentación del marcador para ver sus propiedades. Observa específicamente sus propiedades de transformación en la vista Propiedades seleccionada.

    Propiedades de transformación

    Figura 17: Propiedades de transformación

    La transformación calculada se aplica a esta superficie, pero no se establece en este nivel. Las columnas calculadas y solicitadas tienen valores diferentes, lo que indica que la transformación se hereda de una plataforma principal.

  12. Anula la selección de Plano en la vista de jerarquía para mostrar todo el árbol de jerarquía y navega a los nodos principales de la superficie de la app hasta que las transformaciones Calculado y Solicitado sean iguales, lo que muestra que la transformación se solicitó en la superficie Surface(name=Task=7934)/@0x1941191_transition-leash#40670.

  13. Confirma cuándo se estableció la transformación por primera vez y con qué valor. Para contraer las propiedades seleccionadas, haz clic en el ícono junto al título:

    contraer las propiedades seleccionadas

    Figura 18: Contrae las propiedades seleccionadas.

  14. Selecciona Show diff en la vista Proto Dump para destacar las propiedades que se modifican en este fotograma. Escribe transform en el campo de búsqueda de texto para filtrar las propiedades:

    Mostrar diferencia

    Figura 19: Mostrar diferencia

    La transformación se establece de IDENTITY a SCALE|TRANSLATE|ROT_270 en este fotograma para el transition-leash.

    Esta información muestra que el parpadeo ocurrió cuando se aplicó la transformación a la correa de animación de la app de pantalla dividida del marcador.

    Identificación del parpadeo

    Figura 20: Es la identificación del parpadeo.

  15. Identifica en el código por qué esta transformación se establece en la correa de transición de pantalla dividida.