Отслеживание переходов окон с помощью Winscope

Winscope — это веб-инструмент, позволяющий записывать, воспроизводить и анализировать состояния различных системных служб во время и после анимации и переходов. Winscope записывает все соответствующие состояния системных служб в файл трассировки. Используя пользовательский интерфейс Winscope с файлом трассировки, вы можете проверять состояние этих служб для каждого кадра анимации, с записью экрана или без нее, воспроизводя, пошагово выполняя и отлаживая переходы.

Поддерживаемые трассировки

Winscope предоставляет возможность собирать и визуально отображать различные трассировки , то есть последовательности состояний системных служб. Вы можете настроить эти трассировки в соответствии с конкретными сценариями использования, от низкозатратных до высокодетализированных. Winscope поддерживает следующие типы трассировок:

  • Журнал событий: Соберите запись диагностических событий системы с помощью EventLog . В Winscope эта информация используется только для идентификации и отображения меток CUJ.
  • IME: Отслеживание событий из конвейера редактора методов ввода (IME), включая IMS, IMMS и IME Client.
  • Входные данные: Отслеживание входных событий из различных частей конвейера обработки входных событий.
  • ProtoLog: Сбор сообщений ProtoLog от системных служб и кода системных служб, работающих в клиентских процессах.
  • Запись экрана: Сделайте запись экрана вместе с трассировкой.
  • Переходы между оболочками: подробная информация о системе перехода между окнами и действиями.
  • SurfaceFlinger: Собирает трассировки SurfaceFlinger , содержащие информацию о поверхностях (слоях), такую ​​как положение, буфер и состав.
  • Транзакции: Отслеживание набора атомарных изменений, полученных SurfaceFlinger, с использованием SurfaceControl для композиции.
  • ViewCapture: Захватывает ряд свойств всех элементов интерфейса Windows, поддерживающих ViewCapture, таких как системный интерфейс и панель запуска.
  • Диспетчер окон: Трассировка диспетчера окон содержит подробную информацию об окнах, включая события ввода и фокусировки, ориентацию экрана, переходы, анимацию, позиционирование и преобразования.

Поддерживаемые дампы

Winscope может собирать и отображать дампы состояния, представляющие собой снимки состояния устройства, сделанные в определенные моменты времени, заданные пользователем. В отличие от трассировки, которая непрерывно собирается во время использования устройства и может влиять на производительность, дампы создаются только в эти заданные пользователем моменты, чтобы убедиться, что производительность и детализация не ухудшаются. Это позволяет проводить более целенаправленный и эффективный анализ состояния устройства в определенные моменты времени. Winscope поддерживает следующие типы дампов:

  • Менеджер окон: Вывести в память только одно состояние менеджера окон.
  • SurfaceFlinger: Создать дамп одного снимка SurfaceFlinger.
  • Скриншот: Сделайте скриншот вместе с дампами.

Ресурсы

См. раздел «Запуск Winscope» для получения информации о сборке и запуске Winscope.

См. раздел «Захват трассировок» для получения информации о сборе трассировок.

См. раздел «Загрузка трассировок» для получения информации о том, как загружать трассировки с помощью веб-интерфейса Winscope.

См. раздел «Анализ трассировок» для получения информации об анализе трассировок.

Примеры

В следующем примере описано, как отладить ошибку, возникшую при проверке мерцания, и ошибку, о которой сообщил пользователь.

Сбой теста на мерцание

В этом примере показано, как использовать Winscope для отладки ошибки теста на мерцание.

Изучите причину сбоя теста.

Выполните следующие шаги, чтобы определить тип проблемы и изучить сообщение об ошибке тестирования.

  1. Определите тип проблемы, изучив название теста и класса.

    Название теста и класса:

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

    Тип проблемы:

    • CUJ обозначает запуск приложения из уведомления на экране блокировки ( OpenAppFromLockscreenNotificationColdTest ).
    • В ходе теста предполагается, что приложение станет видимым ( #appLayerBecomesVisible ).
  2. Изучите сообщение об ошибке тестирования, которое содержит исчерпывающую информацию о сбое, в том числе:

    • Сравнение ожидаемого результата с фактическим видимым результатом.
    • Временные метки помогут точно определить, когда произошла ошибка.
    • Название артефакта или файла, связанного с ошибкой.
    • Дополнительная контекстная информация, имеющая значение для понимания и устранения ошибки.
    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)
    

    Данный пример выходных данных показывает следующее:

    • Проблема возникла 2024-05-10T11:04:14.227572545 .
    • Ожидается, что NotificationActivity будет видимым, но это не так.
    • Имя файла артефакта, содержащего трассировки для отладки, — FAIL__OpenAppFromLockscreenNotificationColdTest_ROTATION_0_GESTURAL_NAV .

Отлаживать

Выполните следующие шаги, чтобы определить причину мерцания:

  1. Загрузите файлы трассировки и загрузите их в Winscope. Winscope откроется с автоматически выбранным SurfaceFlinger:

    Winscope landing page with SurfaceFlinger view

    Рисунок 1. Главная страница Winscope с представлением SurfaceFlinger.

  2. Перейдите к временной метке, где возникла проблема, скопировав и вставив метку времени из сообщения об исключении в соответствующее поле. Вы можете либо скопировать метку времени в удобочитаемом формате ( 2024-05-10T11:04:14.227572545 ) и вставить ее в первое поле, либо скопировать метку времени в наносекундах ( 1715339054227572545ns ) и вставить ее во второе поле.

    Timestamp dialog

    Рисунок 2. Диалоговое окно «Отметка времени».

  3. Нажмите клавишу со стрелкой влево, чтобы перейти к предыдущему кадру. В этом состоянии приложение NotificationActivity корректно отображается в видео, и видны как поверхность приложения, так и поверхность заставки, что обозначено их зелеными прямоугольниками в 3D-виде и V- образным чипом на элементах их иерархии.

    Названия элементов интерфейса приложения и заставки:

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

    Это указывает на то, что приложение запускалось в момент, когда экран стал чёрным, и что это событие происходит во время запуска приложения, поскольку заставка всё ещё видна:

    At app launch

    Рисунок 3. При запуске приложения.

  4. Нажмите клавишу со стрелкой вправо, чтобы вернуться к следующему кадру, где происходит мерцание. В представлении прямоугольников на экране отображается NotificationShade вместо приложения. В этом кадре отображаются следующие поверхности:

    • Декоративные накладки для экрана (сверху и снизу)
    • Панель навигации
    • Местоположение указателя (по данным записи экрана)

    Flicker activity

    Рисунок 4. Мерцание.

  5. Выберите активность приложения в иерархическом представлении. Если вы не можете ее найти, снимите флажок « Показывать только V» . Затем изучите свойства приложения.

    Название приложения на поверхности:

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

    App properties

    Рисунок 5. Свойства приложения.

    Несмотря на то, что активность приложения установлена ​​как видимая и непрозрачная, поверхность не отображается из-за ошибки Invisible due to: null visible region . Это происходит потому, что во время композиции перед ней была размещена другая непрозрачная поверхность. Эта гипотеза основана на том, что прямоугольник NotificationShade находится перед прямоугольником NotificationActivity в 3D-виде, и видимый (зеленый) NotificationShade возможно, является выбранным слоем.

  6. Чтобы проверить эту гипотезу, выберите видимую поверхность NotificationShade на текущем кадре и проверьте её свойства. Флаги установлены в значение OPAQUE|ENABLE_BACKPRESSURE (0x102) . Имя поверхности NotificationShadeNotificationShade#3447 . Затем нажмите стрелку влево, чтобы вернуться к предыдущему кадру (до мерцания) и снова проверьте свойства поверхности NotificationShade . Обратите внимание, что вместо значения OPAQUE поверхность имеет только флаг ENABLE_BACKPRESSURE (0x100) . Это подтверждает, что NotificationShade становится непрозрачным до полного завершения запуска приложения. Поскольку NotificationShade находится перед NotificationActivity , приложение не отображается. NotificationShade становится чёрным, поэтому экран на короткое время гаснет, что и вызывает мерцание.

  7. Укажите в коде причину, по которой NotificationShade становится непрозрачным слишком рано.

Ошибка, о которой сообщил пользователь.

Сообщения пользователей об ошибках могут быть сложными для отладки, поскольку им часто не хватает подробной информации. В отличие от ошибок при тестировании мерцания, которые предоставляют конкретные временные метки, сведения об элементах и ​​записи экрана, сообщения пользователей об ошибках обычно содержат лишь краткое описание проблемы.

В нашем исследовании представлена ​​только следующая информация: заголовок « Экран мерцает при повторном открытии приложения в режиме разделенного экрана» и приблизительное время 18 апреля 2024 г., 15:51 GMT-04:00 .

Для отладки ошибки, о которой сообщил пользователь, выполните следующие действия:

  1. Загрузите файл трассировки в Winscope. Winscope откроется с автоматически выбранным SurfaceFlinger.

    Winscope landing page with SurfaceFlinger view

    Рисунок 6. Главная страница Winscope с представлением SurfaceFlinger.

  2. Чтобы перейти к приблизительному времени, указанному пользователем (в данном случае 3:50 PM GMT-04:00 , введите 15:50:00 в поле для ввода времени, понятное человеку.

    Timestamp dialog

    Рисунок 7. Диалоговое окно «Отметка времени».

  3. Используйте режим просмотра прямоугольников, чтобы определить, что было нарисовано на экране. Для лучшего обзора используйте ползунок «Поворот» , чтобы изменить перспективу прямоугольников. Отметив в режиме просмотра иерархии пункты «Показывать только V» и «Плоский» , вы увидите обои, наложение декора экрана, черные полосы по бокам, панель запуска, контакты и панель набора номера.

    Названия пакетов:

    • Лаунчер: com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#40602
    • Контакты: com.google.android.contacts/com.android.contacts.activities.PeopleActivity#40565
    • Номеронабиратель: com.google.android.dialer/com.google.android.dialer.extensions.GoogleDialtactsActivity#40564

    В дополнение к видимым поверхностям (зеленые прямоугольники) отображается серый прямоугольник, представляющий собой поверхность области отображения, с именем «Неизвестный дисплей ». Для улучшения видимости щелкните ( visibility icon ) рядом с поверхностью ScreenDecorHwcOverlay#64 чтобы скрыть соответствующий прямоугольник и показать поверхности за ним. Мы удаляем наложение для анализа, поскольку оно не видно пользователю и не будет отображаться как мерцающая анимация.

    User report

    Рисунок 8. Отчет пользователя.

  4. После определения поверхностей, задействованных в режиме разделенного экрана, используйте трассировку переходов, чтобы пошагово просмотреть различные действия пользователя и найти мерцание. Щелкните вкладку «Переходы» в Winscope, чтобы визуализировать список воспроизведенных переходов:

    transitions

    Рисунок 9. Переходы.

    Переход, воспроизводимый в этом кадре, выделен синим цветом. В данном случае флаги перехода включают TRANSIT_FLAG_IS_RECENTS , что указывает на то, что пользователь переходит на экран последних просмотренных элементов.

  5. Щелкните ссылку в столбце «Время отправки» (в данном случае 2024-04-18, 15:50:57.205 ), чтобы перейти к этому моменту времени и проверить прямоугольники на вкладке Surface Flinger . Подтвердите правильность состояния устройства во время перехода, пошагово выполняя переход с помощью клавиши со стрелкой вправо и наблюдая за прямоугольниками.

    Панель запуска появляется в 15:50:57.278, но анимация тогда не начинается. Обои уже видны, потому что между приложениями в режиме разделенного экрана ничего не отображается (разделитель). Кадром раньше (15:50:57.212) обои не видны, и отображается разделитель, именно так выглядит разделенный экран, когда анимация не запущена.

    Screen before flicker

    Рисунок 10. Экран до появления мерцания.

  6. Чтобы посмотреть следующий переход, щелкните непосредственно по временной шкале. Состояния SurfaceFlinger отображаются рядом светло-голубых блоков. Переходы отображаются рядом розовых блоков.

    End of first transition

    Рисунок 11. Конец первого перехода.

    Щелкните по строке SurfaceFlinger в начальной позиции следующего перехода. На рисунке 11 вертикальное положение курсора обозначено тонкой синей линией. Светло-голубой фон строки SurfaceFlinger показывает ее горизонтальное положение. Пройдите по переходу с помощью клавиши со стрелкой вправо, чтобы проверить, не возникает ли мерцание. Убедитесь, что устройство отображает изображение корректно для этого перехода.

  7. Пропустите следующий переход, так как его продолжительность очень мала, поэтому вряд ли он будет сопровождаться мерцанием. Вместо этого щелкните по временной шкале в строке SurfaceFlinger в начальной позиции следующего более длительного перехода, как указано курсором на следующем изображении.

    end of second transition

    Рисунок 12. Конец второго перехода.

    В этот момент перехода, в 15:51:13.239 , обратите внимание, что Splash Screen для обоих приложений, контактов и номеронабирателя, находятся на одной стороне экрана:

    splash screens

    Рисунок 13. Заставки.

  8. Уточните, какое приложение находится не с той стороны. Добавьте закладку к текущему положению, щелкнув значок флажка рядом с полем ввода ns , чтобы позже вернуться к этому фрейму.

    add bookmark

    Рисунок 14. Добавить закладку.

  9. Перейдите к кадру в конце перехода, щелкнув непосредственно по временной шкале, например, к 15:51:13.859 . Здесь оба приложения находятся в своем конечном положении: номеронабиратель слева, а контакты справа.

    final split screen

    Рисунок 15. Финальное разделение экрана.

  10. Нажмите на флажок закладки на временной шкале, чтобы вернуться к кадру с мерцанием.

    bookmark timeline

    Рисунок 16. Хронологическая шкала закладок.

    Оба приложения находятся справа, что указывает на неправильное расположение приложения для набора номера.

  11. Чтобы просмотреть свойства программы для набора номера, щелкните по заставке. Обратите особое внимание на свойства преобразования в режиме просмотра свойств .

    Transform properties

    Рисунок 17. Свойства преобразования.

    Вычисленное преобразование применяется к этой поверхности, но не задается на этом уровне. Столбцы «Вычисленное» и «Запрошенное» имеют разные значения, что указывает на то, что преобразование наследуется от родительской поверхности.

  12. Снимите флажок «Плоский» в представлении иерархии, чтобы отобразить все дерево иерархии, и переходите к родительским узлам поверхности приложения, пока значения вычисляемых и запрашиваемых преобразований не совпадут, отображая запрашиваемое преобразование на Surface(name=Task=7934)/@0x1941191_transition-leash#40670 .

  13. Укажите, когда и на какое значение было впервые установлено преобразование. Сверните отобранные свойства, щелкнув значок рядом с заголовком:

    collapse the curated properties

    Рисунок 18. Свернуть отобранные свойства.

  14. Выберите «Показать различия» в окне «Прототип дампа» , чтобы выделить свойства, изменяющиеся в этом окне. Введите transform в поле поиска, чтобы отфильтровать свойства:

    show diff

    Рисунок 19. Показана разница.

    В этом кадре для transition-leash преобразование устанавливается с IDENTITY на SCALE|TRANSLATE|ROT_270 .

    Эта информация показывает, что мерцание произошло, когда преобразование было применено к анимационному ремню приложения для разделенного экрана в приложении для набора номера.

    Identification of the flicker

    Рисунок 20. Идентификация мерцания.

  15. Укажите в коде, почему для этого преобразования установлен параметр "поводок перехода к разделенному экрану".