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 grava todos os estados pertinentes do serviço do sistema 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, percorrendo e depurando as transições.
Traces compatíveis
O Winscope permite coletar e representar visualmente vários rastreamentos ou sequências de estados de serviços do sistema. É possível configurar esses rastreamentos para atender a casos de uso específicos, que variam de baixa sobrecarga a alta verbosidade. O Winscope é compatível com os seguintes rastreamentos:
- 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 marcações de CUJ. - IME:rastreia 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:coleta mensagens ProtoLog de serviços do sistema e do código de serviços do sistema em execução em processos do cliente.
- Gravação de tela:colete uma gravação de tela junto com os rastreamentos.
- Transições de shell:registram detalhes do sistema de transição de atividade e janela de gravação.
- SurfaceFlinger:coleta rastreamentos do 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:captura uma variedade de propriedades de todas as visualizações de janelas do sistema que oferecem suporte a ViewCapture, como a interface do sistema e o iniciador.
- Gerenciador de janelas:rastreamento de 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 tirados em momentos específicos definidos pelo usuário. Ao contrário dos rastreamentos, que são coletados continuamente durante o uso do dispositivo e podem afetar o desempenho, os despejos são feitos apenas nesses 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. Estes dumps são compatíveis com o Winscope:
- Gerenciador de janelas:despeja um único estado do gerenciador de janelas.
- SurfaceFlinger:despeja um único snapshot do SurfaceFlinger.
- Captura de tela:faça uma captura de tela junto com os despejos.
Recursos
Consulte Executar o Winscope para saber como criar e executar o Winscope.
Consulte Capturar traces para informações sobre como coletar traces.
Consulte Carregar rastreamentos para saber como fazer isso 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 oscilação e um bug informado pelo usuário.
Falha no teste de oscilação
Este exemplo demonstra como usar o Winscope para depurar uma falha no teste de oscilação.
Examinar a falha no teste
Siga estas etapas para determinar o tipo de problema e examinar a mensagem de falha no teste.
Determine o tipo de problema examinando o teste e o nome 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 ao lançamento de um app por uma notificação na tela de bloqueio (
OpenAppFromLockscreenNotificationColdTest
).O teste espera que o app fique visível (
#appLayerBecomesVisible
).
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 visível real
- 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
.NotificationActivity
deveria estar visível, mas não está.O nome do arquivo de artefato que contém os rastreamentos para depuração é
FAIL__OpenAppFromLockscreenNotificationColdTest_ROTATION_0_GESTURAL_NAV
.
Depuração
Siga estas etapas para determinar a causa da oscilação:
Faça o download dos arquivos de rastreamento e carregue-os no Winscope. O Winscope é aberto com o SurfaceFlinger selecionado automaticamente:
Figura 1. Página de destino do Winscope com a visualização do SurfaceFlinger.
Copie e cole o carimbo de data/hora da mensagem de exceção no campo correspondente para navegar até o momento em que o problema ocorre. Você pode copiar o carimbo de data/hora em 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.Figura 2. Caixa de diálogo de carimbo de data/hora.
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 ficam visíveis, indicadas pelos retângulos verdes na visualização 3D e pelo ícone V nos elementos da hierarquia.
Os nomes de 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 de apresentação ainda está visível:
Figura 3. Ao iniciar o app.
Pressione a tecla de seta para a direita para voltar ao próximo frame, onde o tremor ocorre. Na visualização de rects, 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
Localização do cursor (da gravação de tela)
Figura 4. Atividade de oscilação.
Selecione a atividade do app na visualização de hierarquia. Se não encontrar, desmarque Mostrar apenas V e 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`
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 acontece porque outra superfície opaca foi colocada na frente dela durante a composição. Essa hipótese decorre do fato de o retânguloNotificationShade
estar na frente do retânguloNotificationActivity
na visualização 3D, e oNotificationShade
visível (verde) ser potencialmente a camada escolhida.Para validar essa hipótese, selecione a superfície
NotificationShade
visível no frame atual e verifique as propriedades dela. As flags estão definidas comoOPAQUE|ENABLE_BACKPRESSURE (0x102)
. O nome da superfícieNotificationShade
éNotificationShade#3447
. Em seguida, pressione a seta para a esquerda para voltar ao frame anterior (antes da oscilação) e inspecione as propriedades da superfícieNotificationShade
novamente. Em vez de serOPAQUE
, a superfície tem apenas a flagENABLE_BACKPRESSURE (0x100)
. Isso confirma queNotificationShade
fica opaco antes que o lançamento do app seja totalmente concluído. Como oNotificationShade
está na frente doNotificationActivity
, o app não é mostrado. ONotificationShade
é preto, então a tela fica preta brevemente, o que causa a oscilação.Identifique no código por que o
NotificationShade
fica opaco muito cedo.
Bug relatado pelo usuário
É difícil depurar bugs informados pelos usuários porque eles 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 do elemento e gravações de tela, os bugs informados pelos usuários 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 na tela dividida e um carimbo de data/hora aproximado de 18 de abril de 2024, 15h51 GMT-04:00.
Siga estas etapas para depurar um bug informado pelo usuário:
Carregue o arquivo de rastreamento no Winscope. O Winscope é aberto com o SurfaceFlinger selecionado automaticamente.
Figura 6. Página de destino do Winscope com a visualização do SurfaceFlinger.
Navegue até o carimbo de data/hora aproximado informado pelo usuário, neste caso
3:50 PM GMT-04:00
, inserindo15:50:00
no campo de carimbo de data/hora legível.Figura 7. Caixa de diálogo de carimbo de data/hora.
Use a visualização de retângulos para identificar o que foi desenhado na tela. Para uma visualização melhor, use o controle deslizante Rotação 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 correio, o iniciador, os contatos e as superfícies do discador 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 em (
) ao lado da superfície
ScreenDecorHwcOverlay#64
para ocultar o rect correspondente e revelar as superfícies atrás. Removemos a sobreposição da análise porque ela não fica visível para o usuário e não seria informada como uma animação tremeluzente.Figura 8. Denúncia de usuário.
Depois de identificar quais superfícies estão envolvidas na visualização em tela dividida, use o rastreamento de transições para passar por várias ações do usuário e encontrar o flicker. Clique na guia Transições no Winscope para visualizar a lista de transições reproduzidas:
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 de apps recentes.Clique no link na coluna Tempo de envio (neste caso,
2024-04-18, 15:50:57.205
) para navegar até esse ponto no tempo e verificar os retângulos na guia Surface Flinger. Confirme a correção do estado do dispositivo durante a transição percorrendo-a com a tecla de seta direita e observando os retângulos.O iniciador aparece às 15:50:57.278, mas a animação não começa nesse momento. O plano de fundo já está visível porque nada é desenhado entre os apps de tela dividida (divisor). Um frame antes (15:50:57.212), o papel de parede não está visível, e o divisor é mostrado, que é como a tela dividida aparece quando não está animada.
Figura 10. Tela antes do evento de oscilação.
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 azuis claros. As transições são representadas por uma linha de blocos rosa.
Figura 11. Fim 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. Percorra a transição com a tecla de seta para a direita e verifique se há um tremular. Confirme se o dispositivo está correto para essa transição.
Pule a próxima transição, já que a duração dela é muito pequena e é improvável que contenha um flicker. 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.
Figura 12. Fim da segunda transição.
Durante essa transição, em
15:51:13.239
, observe que as camadasSplash Screen
dos dois apps, dos contatos e do discador estão no mesmo lado da tela:Figura 13. Telas de apresentação.
Esclareça qual app está do lado errado. Adicione um marcador à sua posição atual clicando no ícone de flag ao lado do campo de entrada ns para ajudar a voltar a esse frame mais tarde.
Figura 14. Adicionar favorito.
Clique diretamente na linha do tempo para navegar até um frame no final da transição, por exemplo,
15:51:13.859
. Aqui, os dois apps estão na posição final, com o discador à esquerda e os contatos à direita:Figura 15. Tela dividida final.
Clique na flag do marcador na linha do tempo para voltar ao frame com o efeito de tremulação.
Figura 16. Adicionar aos favoritos.
Os dois apps estão à direita, indicando que o discador está na posição errada.
Clique na tela inicial do discador para conferir as propriedades. Observe especificamente as propriedades de transformação na visualização Propriedades selecionada.
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, indicando que a transformação está sendo herdada de uma superfície principal.
Desmarque Flat na visualização de hierarquia para mostrar toda a árvore hierárquica e navegue até os nós principais da superfície do app até que as transformações Calculated e Requested sejam iguais, mostrando a transformação requested na superfície
Surface(name=Task=7934)/@0x1941191_transition-leash#40670
.Confirme quando a transformação foi definida pela primeira vez e qual era o valor. Clique no ícone ao lado do título para recolher as propriedades selecionadas:
Figura 18. Feche as propriedades selecionadas.
Selecione Mostrar diferença 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:Figura 19. Mostrar diferença.
A transformação é definida de
IDENTITY
paraSCALE|TRANSLATE|ROT_270
neste frame para otransition-leash
.Essas informações mostram que o tremular ocorreu quando a transformação foi aplicada à guia de animação do app de tela dividida do discador.
Figura 20. Identificação da oscilação.
Identifique no código por que essa transformação está definida como a transição de tela dividida.