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

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

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

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

  • EventLog: Соберите запись диагностического события системы с помощью EventLog . В Winscope эта информация используется только для идентификации и отображения маркировок CUJ.
  • IME: отслеживание событий из конвейера редактора методов ввода (IME), включая IMS, IMMS и IME Client.
  • Вход: отслеживание событий входа из различных частей конвейера событий входа.
  • 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) . Имя поверхности 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 и 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. Нажмите ссылку в столбце Dispatch Time (в данном случае 2024-04-18, 15:50:57.205 ), чтобы перейти к этому моменту времени и проверить прямоугольники на вкладке Surface Flinger . Подтвердите правильность состояния устройства во время перехода, пройдя через переход с помощью клавиши со стрелкой вправо и наблюдая за прямоугольниками.

    Launcher появляется в 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. Выберите Show diff в представлении Proto Dump , чтобы выделить свойства, которые изменяются в этом кадре. Введите transform в поле текстового поиска, чтобы отфильтровать свойства:

    show diff

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

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

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

    Identification of the flicker

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

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