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 для отладки сбоя теста мерцания.
Изучите провал теста
Выполните следующие действия, чтобы определить тип проблемы и изучить сообщение об ошибке теста.
Определите тип проблемы, изучив имя теста и класса.
Имя теста и класса:
FlickerTestsNotification com.android.server.wm.flicker.notification.OpenAppFromLockscreenNotificationColdTest#appLayerBecomesVisible[ROTATION_0_GESTURAL_NAV]
Тип проблемы:
CUJ относится к запуску приложения из уведомления на экране блокировки (
OpenAppFromLockscreenNotificationColdTest
).Тест ожидает, что приложение станет видимым (
#appLayerBecomesVisible
).
Изучите сообщение об ошибке теста, в котором содержится подробная информация о сбое, включая:
- Сравнение ожидаемого результата с фактическим видимым результатом
- Временные метки, помогающие точно определить, когда произошел сбой
- Имя артефакта или файла, связанного с ошибкой
- Дополнительная контекстная информация, имеющая значение для понимания и устранения неполадки
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
.
Отлаживать
Чтобы определить причину мерцания, выполните следующие действия:
Загрузите файлы трассировки и загрузите их в Winscope. Winscope открывается с автоматически выбранным SurfaceFlinger:
Рисунок 1. Целевая страница Winscope с представлением SurfaceFlinger.
Перейдите к временной метке, где возникла проблема, скопировав её из сообщения об исключении и вставив в поле временной метки. Вы можете скопировать временную метку в удобном для восприятия формате (
2024-05-10T11:04:14.227572545
) и вставить в первое поле, либо скопировать временную метку в наносекундах (1715339054227572545ns
) и вставить во второе поле.Рисунок 2. Диалоговое окно временной метки.
Нажмите клавишу со стрелкой влево, чтобы перейти к предыдущему кадру. В этом состоянии приложение 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. При запуске приложения.
Нажмите клавишу со стрелкой вправо, чтобы вернуться к следующему кадру, где наблюдается мерцание. В прямоугольном представлении вместо приложения на экране отображается
NotificationShade
. В этом кадре показаны следующие поверхности:- Накладки на экранный декор (верхняя и нижняя)
- Панель навигации
Местоположение указателя (из записи экрана)
Рисунок 4. Мерцательная активность.
Выберите действие приложения в иерархическом представлении. Если вы его не нашли, снимите флажок « Показывать только 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
потенциально является выбранным слоем.Чтобы проверить эту гипотезу, выберите видимую поверхность
NotificationShade
на текущем кадре и проверьте ее свойства. Флаги установлены наOPAQUE|ENABLE_BACKPRESSURE (0x102)
. Имя поверхностиNotificationShade
-NotificationShade#3447
. Затем нажмите стрелку влево, чтобы вернуться к предыдущему кадру (до мерцания), и снова проверьте свойства поверхностиNotificationShade
. Обратите внимание, что вместоOPAQUE
поверхность имеет только флагENABLE_BACKPRESSURE (0x100)
. Это подтверждает, чтоNotificationShade
становится непрозрачным до полного завершения запуска приложения. ПосколькуNotificationShade
находится передNotificationActivity
, приложение не отображается.NotificationShade
черный, поэтому экран на короткое время становится черным, что и вызывает мерцание.Определите в коде, почему
NotificationShade
становится непрозрачным слишком рано.
Ошибка, о которой сообщил пользователь
Отладка ошибок, о которых сообщают пользователи, может быть сложной, поскольку часто отсутствует подробная информация. В отличие от ошибок, выявленных в ходе тестирования мерцания, которые сопровождаются конкретными временными метками, подробной информацией об элементах и записями экрана, ошибки, о которых сообщают пользователи, обычно содержат лишь краткое описание проблемы.
В нашем исследовании была предоставлена только информация о заголовке « Экран мерцал при повторном открытии приложения из режима разделенного экрана» и примерная временная метка 18 апреля 2024 г. 15:51 GMT-04:00 .
Чтобы устранить ошибку, о которой сообщил пользователь, выполните следующие действия:
Загрузите файл трассировки в Winscope. Winscope открывается с автоматически выбранным SurfaceFlinger.
Рисунок 6. Целевая страница Winscope с представлением SurfaceFlinger.
Перейдите к приблизительной временной метке, указанной пользователем, в данном случае
3:50 PM GMT-04:00
, введя15:50:00
в удобное для чтения поле временной метки.Рисунок 7. Диалоговое окно временной метки.
Используйте представление «Прямоугольники», чтобы определить, что было нарисовано на экране. Для лучшего обзора используйте ползунок «Поворот» , чтобы изменить перспективу прямоугольников. Если в представлении «Иерархия» выбрать «Показывать только 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
Помимо видимых поверхностей (зелёных прямоугольников), отображается серый прямоугольник, представляющий поверхность области отображения, называемый «Неизвестный дисплей ». Для улучшения видимости нажмите кнопку (
) рядом с поверхностью
ScreenDecorHwcOverlay#64
, чтобы скрыть соответствующий прямоугольник и показать поверхности за ним. Мы удаляем наложение для анализа, поскольку оно не видно пользователю и не будет считаться мерцающей анимацией.Рисунок 8. Отчет пользователя.
Определив, какие поверхности задействованы в режиме разделенного экрана, используйте трассировку переходов, чтобы пошагово просмотреть различные действия пользователя и найти мерцание. Перейдите на вкладку «Переходы» в Winscope, чтобы отобразить список воспроизведенных переходов:
Рисунок 9. Переходы.
Переход, воспроизводимый в этом кадре, выделен синим цветом. В данном случае флаги перехода включают
TRANSIT_FLAG_IS_RECENTS
, что указывает на то, что пользователь переходит на экран недавних действий.Щёлкните по ссылке в столбце «Время отправки» (в данном случае
2024-04-18, 15:50:57.205
), чтобы перейти к этому моменту времени и проверить прямоугольники на вкладке «Surface Flinger» . Убедитесь в правильности состояния устройства во время перехода, пройдя по нему с помощью клавиши со стрелкой вправо и наблюдая за прямоугольниками.Заставка появляется в 15:50:57.278, но анимация не запускается. Обои уже видны, поскольку между приложениями на разделённом экране (разделителем) ничего не отображается. На один кадр ранее (15:50:57.212) обои не видны, а разделитель отображается — так выглядит разделённый экран без анимации.
Рисунок 10. Экран до события мерцания.
Чтобы увидеть следующий переход, нажмите на временную шкалу. Состояния SurfaceFlinger представлены рядом светло-голубых блоков. Переходы представлены рядом розовых блоков.
Рисунок 11. Конец первого перехода.
Щёлкните строку SurfaceFlinger в начальной точке следующего перехода. На рисунке 11 вертикальное положение курсора обозначено тонкой синей линией. Светло-голубой фон строки SurfaceFlinger показывает её горизонтальное положение. Пройдите переход, нажимая клавишу со стрелкой вправо, чтобы проверить, появляется ли мерцание. Убедитесь, что устройство корректно отображает этот переход.
Пропустите следующий переход, так как его длительность очень мала, поэтому он вряд ли будет содержать мерцание. Вместо этого щелкните на временной шкале в строке SurfaceFlinger в начальной точке следующего более длительного перехода, как указано курсором на следующем изображении.
Рисунок 12. Конец второго перехода.
Во время этого перехода в
15:51:13.239
обратите внимание, что слоиSplash Screen
для обоих приложений, контактов и номеронабирателя находятся на одной стороне дисплея:Рисунок 13. Заставки.
Уточните, какое приложение находится не на той стороне. Добавьте закладку на текущую позицию, нажав на значок флага рядом с полем ввода ns , чтобы позже вернуться к этому фрейму.
Рисунок 14. Добавить закладку.
Перейдите к кадру в конце перехода, щелкнув непосредственно по временной шкале, например, к
15:51:13.859
. Здесь оба приложения находятся в конечном положении: номеронабиратель слева, а контакты справа:Рисунок 15. Окончательный вариант разделенного экрана.
Щелкните флажок закладки на временной шкале, чтобы вернуться к кадру с мерцанием.
Рисунок 16. Временная шкала закладок.
Оба приложения находятся справа, что указывает на то, что номеронабиратель находится в неправильном положении.
Нажмите на заставку дозвонщика, чтобы просмотреть его свойства. Обратите особое внимание на свойства преобразования в специальном представлении «Свойства» .
Рисунок 17. Свойства преобразования.
Вычисленное преобразование применяется к этой поверхности, но не устанавливается в качестве этого уровня. Вычисленный и запрошенный столбцы имеют разные значения, что указывает на то, что преобразование наследуется от родительской поверхности.
Снимите флажок Flat в представлении иерархии, чтобы отобразить все дерево иерархии, и переходите к родительским узлам поверхности приложения, пока вычисляемые и запрошенные преобразования не станут одинаковыми, отображая запрошенное преобразование на
Surface(name=Task=7934)/@0x1941191_transition-leash#40670
.Проверьте, когда и какое значение было задано преобразованием. Сверните отобранные свойства, нажав на значок рядом с заголовком:
Рисунок 18. Свернуть отобранные свойства.
Выберите «Показать различия» в представлении Proto Dump , чтобы выделить изменяемые свойства в этом кадре. Введите
transform
в поле поиска, чтобы отфильтровать свойства:Рисунок 19. Показать разницу.
В этом кадре для
transition-leash
преобразование задается изIDENTITY
вSCALE|TRANSLATE|ROT_270
.Эта информация показывает, что мерцание возникло, когда преобразование было применено к анимационному поводку приложения разделенного экрана номеронабирателя.
Рисунок 20. Идентификация мерцания.
Определите в коде, почему это преобразование установлено в качестве привязки перехода к разделенному экрану.