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 для отладки сбоя теста на мерцание.
Изучите неудачный тест
Выполните следующие действия, чтобы определить тип проблемы и изучить сообщение об ошибке теста.
Определите тип проблемы, изучив название теста и класса.
Название теста и класса:
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
, что указывает на то, что пользователь переходит на экран недавних.Нажмите ссылку в столбце Dispatch Time (в данном случае
2024-04-18, 15:50:57.205
), чтобы перейти к этому моменту времени и проверить прямоугольники на вкладке Surface Flinger . Подтвердите правильность состояния устройства во время перехода, пройдя через переход с помощью клавиши со стрелкой вправо и наблюдая за прямоугольниками.Launcher появляется в 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. Свернуть отобранные свойства.
Выберите Show diff в представлении Proto Dump , чтобы выделить свойства, которые изменяются в этом кадре. Введите
transform
в поле текстового поиска, чтобы отфильтровать свойства:Рисунок 19. Показать разницу.
В этом кадре для
transition-leash
преобразование установлено изIDENTITY
вSCALE|TRANSLATE|ROT_270
.Эта информация показывает, что мерцание возникло, когда преобразование было применено к анимационному поводку приложения разделенного экрана номеронабирателя.
Рисунок 20. Идентификация мерцания.
Определите в коде, почему это преобразование установлено в качестве привязки перехода к разделенному экрану.