ViewCapture – это программный инструмент, который фиксирует свойства представлений (например, местоположение, размер, масштаб и видимость), прикрепленных к окнам, к которым он подключен. ViewCapture собирает информацию о различных представлениях в окне и их свойствах, позволяя вам узнать состояние пользовательского интерфейса в определенные моменты времени и отслеживать изменения с течением времени.
Записи экрана могут визуализировать состояние представления в определенное время и показать, как оно меняется, но они требуют значительных ресурсов ЦП и могут повлиять на производительность. Инструмент ViewCapture потребляет меньше ресурсов, поэтому его можно включать чаще. Кроме того, ViewCapture показывает визуализации покадрово на уровне представления, что упрощает проверку состояния представления в определенные моменты по сравнению с записью видео с экрана.
На этой странице описано, как интегрировать ViewCapture в системные приложения.
Использовать
ViewCapture.java реализует экземпляр onDrawListener и собирает трассировку ViewCapture во время отрисовки. Каждая перерисовка кадра запускает обход иерархии дерева представлений, начиная с корневого представления окна.
ViewCapture использует общедоступные методы получения View.java, чтобы извлекать и копировать значения в фоновый поток для повышения производительности. Реализация ViewCapture оптимизирует этот процесс, проверяя, является ли представление грязным или недействительным, с помощью captureViewTree, что позволяет избежать обхода всей иерархии View. captureViewTree доступен только для системных приложений и является частью API UnsupportedAppUsage.
Использовать этот API могут только приложения с определенной целевой версией SDK.
Ограничения
В этом разделе описаны ограничения ViewCapture по производительности и памяти.
Эффективность
Среднее время обработки основного потока для производительности ViewCapture составляет 195 мкс. Однако в худшем случае это может занять около 5 мс. См. фрагмент vc#onDraw в трассировке Perfetto.
Накладные расходы в основном связаны со следующими действиями:
- Переход по иерархии стоит 50 мкс, даже если она обрезана.
- Извлечение объектов из распределителя freelist для хранения копий свойств представления стоит 20 мкс.
- Получение каждого значения свойства с помощью функции получения приводит к множеству дополнительных вызовов функций на представление, что занимает 110 мкс.
Поэтому включение ViewCapture в режиме постоянной трассировки (AOT) негативно влияет на производительность системы и приводит к рывкам. Из-за этих ограничений производительности и памяти этот подход не подходит для AOT. Мы рекомендуем использовать ViewCapture только для лабораторной и локальной отладки.
Память
Чтобы избежать чрезмерного использования памяти, в Perfetto для трассировок ViewCapture используется один кольцевой буфер с заранее заданным объемом потребляемой памяти. Такой подход позволяет избежать чрезмерного потребления памяти, поскольку не требует отдельных кольцевых буферов для каждого окна. Однако это не решает проблему хранения всей иерархии представлений для каждого состояния в Perfetto для каждого кадра. Запись одного окна, например NexusLauncher, может создать более 30 секунд данных ViewCapture в буфере размером 10 МБ. Чтобы записать более 30 окон из интерфейса системы, потребуется либо больший буфер, либо значительно меньшее время записи.
Инструкции
Чтобы добавить ViewCapture в системные приложения, следуйте инструкциям ниже.
Добавьте зависимость в файл
Android.bp, как показано в коде панели запуска.android_library { name: "YourLib", static_libs: [ ... "//frameworks/libs/systemui:view_capture", ... ], platform_apis: true, privileged: true, }Создайте экземпляр ViewCapture при создании окна, например:
-
private SafeCloseable mViewCapture; @Override protected void onCreate(Bundle savedInstanceState) { ... mViewCapture = ViewCaptureFactory.getInstance(this).startCapture(getWindow()); } -
private SafeCloseable mViewCapture; @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (enableViewCaptureTracing()) { mViewCaptureCloseable = ViewCaptureFactory.getInstance(getContext()) .startCapture(getRootView(), ".NotificationShadeWindowView"); } ... }
-
Закрывайте экземпляр ViewCapture при уничтожении окна, как показано в следующих примерах: