Отслеживание переходов окон с помощью 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]
    

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

    • 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) . Имя поверхности 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 landing page with SurfaceFlinger view

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

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

    Timestamp dialog

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

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

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

    • Лаунчер: 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. Снимите флажок Flat в представлении иерархии, чтобы отобразить все дерево иерархии, и переходите к родительским узлам поверхности приложения, пока вычисляемые и запрошенные преобразования не станут одинаковыми, отображая запрошенное преобразование на Surface(name=Task=7934)/@0x1941191_transition-leash#40670 .

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

    collapse the curated properties

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

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

    show diff

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

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

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

    Identification of the flicker

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

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