Rastrear transições de janela usando o Winscope

O Winscope é uma ferramenta da Web que permite aos usuários gravar, reproduzir e analisar os estados de vários serviços do sistema durante e após animações e transições. O Winscope registra todos os estados de serviço do sistema pertinentes em um arquivo de rastreamento. Usando a interface do Winscope com o arquivo de rastreamento, é possível inspecionar o estado desses serviços para cada frame de animação, com ou sem uma gravação de tela, reproduzindo, passando por cada etapa e destravando as transições.

Traces compatíveis

O Winscope permite coletar e representar visualmente vários rastros ou sequências de estados de serviços do sistema. É possível configurar esses rastros para atender a casos de uso específicos, variando de baixa sobrecarga a alta verbosidade. Os seguintes rastros são compatíveis com o Winscope:

  • EventLog:colete o registro de eventos de diagnóstico do sistema usando EventLog. No Winscope, essas informações são usadas apenas para identificar e mostrar as marcações do CUJ.
  • IME:rastreie eventos do pipeline do editor de método de entrada (IME), incluindo IMS, IMMS e cliente IME.
  • Entrada:rastreie eventos de entrada de várias partes do pipeline de eventos de entrada.
  • ProtoLog:colete mensagens de ProtoLog de serviços do sistema e o código de serviços do sistema em execução em processos do cliente.
  • Gravação de tela:colete uma gravação de tela com os rastros.
  • Transições de shell:registre detalhes do sistema de transição de janela e atividade.
  • SurfaceFlinger:colete traços de SurfaceFlinger que contêm informações sobre superfícies (camadas), como posição, buffer e composição.
  • Transações:rastreie o conjunto de mudanças atômicas recebidas pelo SurfaceFlinger usando SurfaceControl para composição.
  • ViewCapture:capture uma variedade de propriedades de todas as visualizações do Windows do sistema que oferecem suporte a ViewCapture, como a interface do sistema e o inicializador.
  • Gerenciador de janelas:rastreie os estados do Gerenciador de janelas que contêm detalhes relacionados a janelas, incluindo eventos de entrada e foco, orientação da tela, transições, animações, posicionamento e transformações.

Dumps compatíveis

O Winscope pode coletar e mostrar despejos de estado, que são snapshots do estado do dispositivo feitos em momentos específicos definidos pelo usuário. Ao contrário dos rastros, que são coletados continuamente durante o uso do dispositivo e podem afetar o desempenho, os despejos são feitos apenas nos momentos definidos pelo usuário, garantindo que o desempenho e a verbosidade não sejam comprometidos. Isso permite uma análise mais focada e eficiente do estado do dispositivo em momentos específicos. Os seguintes despejos são compatíveis com o Winscope:

  • Gerenciador de janelas:salva um único estado do gerenciador de janelas.
  • SurfaceFlinger:despeje um único snapshot do SurfaceFlinger.
  • Captura de tela:colete uma captura de tela com os despejos.

Recursos

Consulte Executar o Winscope para informações sobre como criar e executar o Winscope.

Consulte Capturar rastros para informações sobre como coletar rastros.

Consulte Traces de carga para informações sobre como carregar traces usando a interface da Web do Winscope.

Consulte Analisar traces para informações sobre como analisar traces.

Exemplos

O exemplo a seguir descreve como depurar uma falha no teste de cintilação e um bug informado pelo usuário.

Falha no teste de cintilação

Este exemplo demonstra como usar o Winscope para depurar uma falha no teste de cintilação.

Analisar a falha do teste

Siga estas etapas para determinar o tipo de problema e examinar a mensagem de falha do teste.

  1. Determine o tipo de problema examinando o nome do teste e da classe.

    Nome do teste e da turma:

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

    Tipo de problema:

    • O CUJ se refere à inicialização de um app de uma notificação na tela de bloqueio (OpenAppFromLockscreenNotificationColdTest).

    • O teste espera que o app fique visível (#appLayerBecomesVisible).

  2. Examine a mensagem de falha do teste, que fornece informações abrangentes sobre a falha, incluindo:

    • Uma comparação entre o resultado esperado e o resultado real visível
    • Carimbos de data/hora para ajudar a identificar quando a falha ocorreu
    • O nome do artefato ou arquivo associado à falha
    • Outras informações contextuais relevantes para entender e depurar a falha
    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)
    

    Este exemplo de saída indica o seguinte:

    • O problema acontece em 2024-05-10T11:04:14.227572545.

    • O elemento NotificationActivity deveria estar visível, mas não está.

    • O nome do arquivo de artefato que contém os rastros para depuração é FAIL__OpenAppFromLockscreenNotificationColdTest_ROTATION_0_GESTURAL_NAV.

Depuração

Siga estas etapas para determinar a causa do problema:

  1. Faça o download dos arquivos de rastreamento e carregue-os no Winscope. O Winscope é aberto com o SurfaceFlinger selecionado automaticamente:

    Página de destino do Winscope com visualização do SurfaceFlinger

    Figura 1. Página de destino do Winscope com visualização do SurfaceFlinger.

  2. Navegue até o carimbo de data/hora em que o problema ocorre copiando e colando o carimbo da mensagem de exceção no campo de carimbo de data/hora. Você pode copiar o carimbo de data/hora em um formato legível (2024-05-10T11:04:14.227572545) e colar no primeiro campo ou copiar o carimbo de data/hora em nanossegundos (1715339054227572545ns) e colar no segundo campo.

    Caixa de diálogo de carimbo de data/hora

    Figura 2. Caixa de diálogo de carimbo de data/hora.

  3. Pressione a tecla de seta para a esquerda para navegar até o frame anterior. Nesse estado, o app NotificationActivity aparece corretamente no vídeo, e as superfícies do app e da tela de apresentação estão visíveis, indicadas pelos retângulos verdes na visualização 3D e pelo ícone V nos elementos da hierarquia.

    Os nomes da superfície do app e da tela de apresentação são:

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

    Isso indica que o app estava sendo iniciado quando a tela ficou preta e que esse evento está acontecendo durante a inicialização do app, já que a tela inicial ainda está visível:

    Ao iniciar o app

    Figura 3. Ao iniciar o app.

  4. Pressione a tecla de seta para a direita para voltar ao próximo frame, onde o flicker ocorre. Na visualização de retângulos, o NotificationShade é mostrado na tela, em vez do app. As seguintes superfícies são mostradas neste frame:

    • Sobreposições de decoração de tela (parte de cima e de baixo)
    • Barra de navegação
    • Local do cursor (da gravação de tela)

      Atividade de cintilação

      Figura 4. Atividade de cintilação.

  5. Selecione a atividade do app na visualização de hierarquia. Se não encontrar, desative a opção Mostrar apenas V. Em seguida, inspecione a visualização de propriedades.

    O nome da plataforma do app é:

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

    Propriedades do app

    Figura 5. Propriedades do app.

    Embora a atividade do app esteja definida como visível e opaca, a superfície não é mostrada devido a um erro Invisible due to: null visible region. Isso ocorre porque outra superfície opaca foi colocada na frente dela durante a composição. Essa hipótese decorre do retângulo NotificationShade estar na frente do NotificationActivity na visualização 3D, e do NotificationShade visível (verde) ser potencialmente a camada escolhida.

  6. Para validar essa hipótese, selecione a superfície NotificationShade visível no frame atual e verifique as propriedades dela. As flags são definidas como OPAQUE|ENABLE_BACKPRESSURE (0x102). O nome da superfície NotificationShade é NotificationShade#3447. Em seguida, pressione a seta para a esquerda para voltar ao frame anterior (antes do tremor) e inspecionar as propriedades da superfície NotificationShade novamente. Em vez de ser OPAQUE, a superfície tem apenas a flag ENABLE_BACKPRESSURE (0x100). Isso confirma que NotificationShade fica opaco antes do lançamento do app ser totalmente concluído. Como a NotificationShade está na frente da NotificationActivity, o app não é mostrado. O NotificationShade está preto, então a tela fica preta por um breve momento, o que causa o piscar.

  7. Identifique no código por que o NotificationShade fica opaco muito cedo.

Bug relatado pelo usuário

Os bugs informados pelo usuário podem ser difíceis de depurar porque geralmente não têm informações detalhadas. Ao contrário das falhas no teste de oscilação, que fornecem carimbos de data/hora específicos, detalhes de elementos e gravações de tela, os bugs informados pelo usuário geralmente incluem apenas uma breve descrição do problema.

No nosso estudo de caso, as únicas informações fornecidas são o título A tela piscou ao reabrir o app da tela dividida e um carimbo de data/hora aproximado de 18 de abril de 2024, 15h 51 GMT-04:00.

Siga estas etapas para depurar um bug informado pelo usuário:

  1. Carregar o arquivo de rastreamento no Winscope. O Winscope é aberto com o SurfaceFlinger selecionado automaticamente.

    Página de destino do Winscope com visualização do SurfaceFlinger

    Figura 6. Página de destino do Winscope com visualização do SurfaceFlinger.

  2. Navegue até o carimbo de data/hora aproximado informado pelo usuário, neste caso 3:50 PM GMT-04:00, digitando 15:50:00 no campo de carimbo de data/hora legível por humanos.

    Caixa de diálogo de carimbo de data/hora

    Figura 7. Caixa de diálogo de carimbo de data/hora.

  3. Use a visualização de retângulos para identificar o que foi desenhado na tela. Para uma melhor visualização, use o controle deslizante Rotation para mudar a perspectiva dos retângulos. Ao marcar Mostrar apenas V e Plano na visualização Hierarquia, o plano de fundo, a sobreposição de decoração da tela, a caixa de carta, o iniciador, os contatos e as plataformas de discagem ficam visíveis.

    Os nomes dos pacotes são:

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

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

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

    Além das superfícies visíveis (retângulos verdes), um retângulo cinza, que representa a superfície da área de exibição, chamado Tela desconhecida, é mostrado. Para melhorar a visibilidade, clique no (ícone de visibilidade) ao lado da superfície ScreenDecorHwcOverlay#64 para ocultar o retângulo correspondente e revelar as superfícies por trás. Removemos a sobreposição para a análise porque ela não é visível para o usuário e não é informada como uma animação intermitente.

    Relatório de usuário

    Figura 8. Relatório de usuário.

  4. Depois de identificar quais superfícies estão envolvidas na visualização de tela dividida, use o rastreamento de transições para passar por várias ações do usuário e encontrar o tremor. Clique na guia Transitions no Winscope para visualizar a lista de transições tocadas:

    transições

    Figura 9. Transitions.

    A transição reproduzida durante esse frame é destacada em azul. Nesse caso, as flags de transição incluem TRANSIT_FLAG_IS_RECENTS, que indica que o usuário está entrando na tela Recentes.

  5. Clique no link na coluna Tempo de envio (neste caso, 2024-04-18, 15:50:57.205) para navegar até esse ponto e verificar os retângulos na guia Surface Flinger. Confirme a correção do estado do dispositivo durante a transição, avançando pela transição com a tecla de seta para a direita e observando os retângulos.

    O inicializador aparece às 15:50:57.278, mas a animação não começa. O plano de fundo já está visível porque nada é desenhado entre os apps da tela dividida (divisor). Um frame antes (15:50:57.212), o plano de fundo não está visível, e o divisor é mostrado, que é como a tela dividida aparece quando não está animada.

    Tela antes do tremor

    Figura 10. Tela antes do evento de oscilação.

  6. Para conferir a próxima transição, clique diretamente na linha do tempo. Os estados do SurfaceFlinger são representados por uma linha de blocos azul-claro. As transições são representadas por uma linha de blocos cor-de-rosa.

    Fim da primeira transição

    Figura 11. Término da primeira transição.

    Clique na linha SurfaceFlinger na posição inicial da próxima transição. Na Figura 11, a posição vertical do cursor é indicada pela linha azul fina. O plano de fundo azul claro da linha SurfaceFlinger mostra a posição horizontal dela. Siga a transição com a tecla de seta para a direita para ver se ocorre um tremido. Confirme se o dispositivo está correto para essa transição.

  7. Pule a próxima transição porque a duração dela é muito pequena. Portanto, é improvável que ela contenha um tremido. Em vez disso, clique na linha do tempo na linha SurfaceFlinger na posição inicial da próxima transição mais longa, conforme indicado pelo cursor na imagem a seguir.

    fim da segunda transição

    Figura 12. Fim da segunda transição.

    Durante essa transição, em 15:51:13.239, observe que as camadas Splash Screen dos dois apps, os contatos e o discador, estão no mesmo lado da tela:

    telas de apresentação

    Figura 13. Telas de apresentação.

  8. Esclareça qual app está no lado errado. Adicione um marcador de página à sua posição atual clicando no ícone de bandeira ao lado do campo de entrada ns, para navegar de volta a esse frame mais tarde.

    adicionar favorito

    Figura 14. Adicionar favorito.

  9. Navegue até um frame no final da transição clicando diretamente na linha do tempo, por exemplo, para 15:51:13.859. Aqui, os dois apps estão na posição final, com o discador à esquerda e os contatos à direita:

    tela dividida final

    Figura 15. Tela dividida final.

  10. Clique na bandeira da marcação na linha do tempo para voltar ao frame com a cintilação.

    Linha do tempo de favoritos

    Figura 16. Linha do tempo de favoritos.

    Os dois apps estão à direita, indicando que o discador está na posição errada.

  11. Clique na tela de apresentação do discador para conferir as propriedades. Analise específicamente as propriedades de transformação na visualização Properties.

    Transformar propriedades

    Figura 17. Transformar propriedades.

    A transformação calculada é aplicada a essa superfície, mas não é definida como esse nível. As colunas calculadas e solicitadas têm valores diferentes, o que indica que a transformação está sendo herdada de uma superfície mãe.

  12. Desmarque Flat na visualização de hierarquia para mostrar toda a árvore de hierarquia e navegue até os nós pai da plataforma do app até que as transformações Calculated e Requested sejam iguais, mostrando a transformação sendo solicitada na plataforma Surface(name=Task=7934)/@0x1941191_transition-leash#40670.

  13. Confirme quando a transformação foi definida pela primeira vez e qual valor. Para recolher as propriedades selecionadas, clique no ícone ao lado do título:

    fechar as propriedades selecionadas

    Figura 18. Feche as propriedades selecionadas.

  14. Selecione Show diff na visualização Proto Dump para destacar as propriedades que estão sendo alteradas neste frame. Digite transform no campo de pesquisa de texto para filtrar as propriedades:

    show diff

    Figura 19. Mostrar diferença.

    A transformação é definida de IDENTITY para SCALE|TRANSLATE|ROT_270 neste frame para o transition-leash.

    Essas informações mostram que o tremor ocorreu quando a transformação foi aplicada à guia de animação do app de discagem em tela dividida.

    Identificação do tremor

    Figura 20. Identificação do tremor.

  15. Identifique no código por que essa transformação é definida para a guia de transição de tela dividida.