ViewCapture в системных приложениях

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

Записи экрана могут визуализировать состояние представления в определенное время и показывать, как оно меняется, но они требуют значительных ресурсов ЦП и могут влиять на производительность. Инструмент ViewCapture оказывает меньшее влияние на ресурсы и может включаться чаще. Кроме того, ViewCapture отображает визуализации кадр за кадром на уровне представления, что упрощает проверку состояния представления в определенные моменты по сравнению с записями экрана.

На этой странице описывается, как интегрировать ViewCapture в системные приложения.

Использовать

ViewCapture.java реализует экземпляр onDrawListener и собирает трассировку ViewCapture во время процесса рисования. Каждая перерисовка кадра запускает обход иерархии дерева представлений, начиная с корневого представления окна. ViewCapture использует общедоступные методы получения View.java для извлечения и копирования значений в фоновый поток для повышения производительности. Реализация ViewCapture оптимизирует этот процесс, проверяя, является ли представление грязным или недействительным, с помощью captureViewTree , тем самым избегая обхода всей иерархии представлений. captureViewTree доступен только для системных приложений и является частью API UnsupportedAppUsage. Использование этого API ограничено приложениями в зависимости от их целевой версии SDK.

Ограничения

В следующих разделах описываются ограничения производительности и памяти при работе ViewCapture.

Производительность

Средний накладной расход основного потока для производительности ViewCapture составляет 195 мкс. Однако в худшем случае он может занять около 5 мс. См. срез vc#onDraw в трассировке Perfetto .

Накладные расходы в основном обусловлены следующими действиями:

  1. Обход иерархии занимает 50 мкс, даже при сокращении.
  2. Извлечение объектов из распределителя свободного списка для хранения копий свойств представления занимает 20 мкс.
  3. Извлечение каждого значения свойства с помощью функции-геттера приводит к множеству дополнительных вызовов функций на одно представление, что обходится в 110 мкс.

Следовательно, включение ViewCapture в режиме Always On Tracing (AOT) негативно влияет на производительность системы и приводит к зависаниям. Из-за этих ограничений производительности и памяти этот подход не готов для AOT. Мы рекомендуем ViewCapture только для лабораторной и локальной отладки.

Память

Метод Perfetto для трассировок ViewCapture использует один кольцевой буфер, который имеет предопределенный отпечаток памяти для предотвращения чрезмерного использования памяти. Этот подход предотвращает чрезмерное потребление памяти, избегая использования отдельных кольцевых буферов для каждого окна, но не решает проблему хранения всей иерархии представлений для каждого состояния в Perfetto для каждого кадра. Запись одного окна, например NexusLauncher, может создать более 30 секунд данных ViewCapture в буфере размером 10 МБ. Однако захват более 30 окон из пользовательского интерфейса системы требует либо большего буфера, либо значительно более короткого временного окна записи.

Инструкции

Чтобы интегрировать ViewCapture в системные приложения, следуйте этим инструкциям:

  1. Добавьте зависимость в файл Android.bp , как показано в коде Launcher .

    android_library {
        name: "YourLib",
        static_libs: [
              ...
            "//frameworks/libs/systemui:view_capture",
              ...
        ],
        platform_apis: true,
        privileged: true,
    }
    
  2. Создайте экземпляр ViewCapture при создании окна, например:

    • Пример 1 :

      private SafeCloseable mViewCapture;
      
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        ...
        mViewCapture = ViewCaptureFactory.getInstance(this).startCapture(getWindow());
      }
      
    • Пример 2 :

      private SafeCloseable mViewCapture;
      
      @Override
      protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (enableViewCaptureTracing()) {
            mViewCaptureCloseable = ViewCaptureFactory.getInstance(getContext())
              .startCapture(getRootView(), ".NotificationShadeWindowView");
        }
        ...
      }
      
  3. Закройте экземпляр ViewCapture при уничтожении окна, как показано в следующих примерах:

    • Пример 1 :

      @Override
      public void onDestroy() {
        ...
        if (mViewCapture != null) mViewCapture.close();
      }
      
    • Пример 2 :

      @Override
      protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mViewCaptureCloseable != null) {
            mViewCaptureCloseable.close();
       }
        ...
      }