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

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

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

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

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

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

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

  • Менеджер окон. Дамп одного состояния менеджера окон.
  • SurfaceFlinger: создать дамп одного снимка SurfaceFlinger.
  • Скриншот. Скриншот будет собран вместе с дампами.

Ресурсы

Информацию о том, как создать и запустить Winscope, можно найти в разделе Запуск Winscope.

Информацию о том, как собирать трассировки, можно найти в разделе Запись трассировок.

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

Подробнее об анализе трассировок…

Примеры

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

Сбой при проверке мерцания

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

Как устранить сбой при тестировании

Чтобы определить тип проблемы и изучить сообщение о сбое при тестировании, выполните следующие действия:

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

    Название теста и курса.

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

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

    • Алгоритм достижения цели – это запуск приложения из уведомления на заблокированном экране (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 с представлением SurfaceFlinger

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

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

    Диалоговое окно "Временная метка"

    Рисунок 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
    

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

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

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

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

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

    Мерцание

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

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

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

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

    Свойства приложений

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

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

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

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

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

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

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

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

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

    Целевая страница Winscope с представлением SurfaceFlinger

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

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

    Диалоговое окно временной метки

    Рисунок 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

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

    Отчет о пользователях

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

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

    переходы;

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

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

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

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

    Экран до мерцания

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

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

    Конец первого перехода

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

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

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

    конец второго перехода;

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

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

    заставки;

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

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

    добавить закладку;

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

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

    финальный разделенный экран;

    Рисунок 15. Последний разделенный экран.

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

    хронология закладок

    Рисунок 16. Добавлять закладки на временной шкале.

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

  11. Нажмите на заставку номеронабирателя, чтобы посмотреть его свойства. Посмотрите на свойства преобразования в представлении Свойства.

    Свойства преобразования

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

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

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

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

    свернуть подобранные свойства;

    Рисунок 18. Сверните список рекомендованных свойств.

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

    Показать различия

    Рисунок 19. Показать различия.

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

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

    Идентификация мерцания

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

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