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]Тип проблемы:
- Алгоритм достижения цели – это запуск приложения из уведомления на заблокированном экране (
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 и Плоский, будут видны обои, наложение декора экрана, каше, панель запуска, контакты и номеронабиратель.
Названия пакетов:
- Панель запуска:
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. Чтобы убедиться, что состояние устройства во время перехода правильное, выполните переход с помощью клавиши со стрелкой вправо и проверьте прямоугольники.Панель запуска появляется в 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. Свойства преобразования.
Рассчитанное преобразование применяется к этой поверхности, но не задано на этом уровне. Значения в вычисляемых и запрошенных столбцах различаются, что указывает на наследование преобразования от родительской платформы.
Снимите флажок Плоская в иерархическом представлении, чтобы показать все дерево иерархии, и перейдите к родительским узлам поверхности приложения, пока преобразования Рассчитанное и Запрошенное не станут одинаковыми. Это будет означать, что преобразование запрошено на поверхности
Surface(name=Task=7934)/@0x1941191_transition-leash#40670.Узнайте, когда и какое значение было задано для преобразования. Сверните список рекомендованных свойств, нажав на значок рядом с заголовком:
Рисунок 18. Сверните список рекомендованных свойств.
Выберите Показать различия в представлении Дамп протокола, чтобы выделить свойства, которые изменяются в этом кадре. Введите
transformв поле текстового поиска, чтобы отфильтровать свойства:
Рисунок 19. Показать различия.
В этом кадре для
transition-leashпреобразование задано сIDENTITYнаSCALE|TRANSLATE|ROT_270.Эта информация показывает, что мерцание произошло, когда преобразование было применено к поводку анимации приложения для разделения экрана номеронабирателя.
Рисунок 20. Идентификация мерцания.
Определите в коде, почему это преобразование задано для поводка перехода в режим разделения экрана.