ViewCapture es una herramienta de software que captura las propiedades de las vistas (como la ubicación, el tamaño, la escala y la visibilidad) adjuntas a las ventanas a las que está conectada. ViewCapture captura información sobre las diferentes vistas dentro de una ventana y sus propiedades, lo que te permite conocer el estado de la experiencia del usuario en momentos específicos y hacer un seguimiento de los cambios a lo largo del tiempo.
Las grabaciones de pantalla pueden visualizar el estado de una vista en un momento específico y mostrar cómo cambia, pero demandan recursos significativos de la CPU y pueden afectar el rendimiento. La herramienta ViewCapture tiene menos impacto en los recursos y se puede habilitar con mayor frecuencia. Además, ViewCapture muestra visualizaciones fotograma por fotograma a nivel de la vista, lo que facilita la inspección del estado de la vista en momentos específicos en comparación con las grabaciones de pantalla.
En esta página, se describe cómo integrar ViewCapture en las apps del sistema.
Usar
ViewCapture.java
implementa una instancia de onDrawListener
y recopila un seguimiento de ViewCapture durante el proceso de dibujo. Cada vez que se vuelve a dibujar un fotograma, se activa un recorrido de la jerarquía del árbol de vistas que comienza en la vista raíz de la ventana.
ViewCapture usa métodos get públicos de View.java
para recuperar y copiar valores en un subproceso en segundo plano y mejorar el rendimiento. La implementación de ViewCapture
optimiza este proceso verificando si una vista está sucia o invalidada con captureViewTree
,
lo que evita recorrer toda la jerarquía de vistas. captureViewTree
solo está disponible para las apps del sistema y forma parte de la API de UnsupportedAppUsage.
El uso de esta API se limita a las apps según su versión del SDK de destino.
Limitaciones
En las siguientes secciones, se describen las limitaciones de rendimiento y memoria para ejecutar ViewCapture.
Rendimiento
La sobrecarga promedio del subproceso principal para el rendimiento de ViewCapture es de 195 μs. Sin embargo, en el peor de los casos, puede tardar aproximadamente 5 ms. Consulta la porción vc#onDraw
en el seguimiento de Perfetto.
Los costos indirectos se deben principalmente a las siguientes acciones:
- El recorrido de la jerarquía cuesta 50 μs, incluso cuando se poda.
- Extraer objetos de un asignador de listas libres para almacenar copias de propiedades de vista cuesta 20 μs.
- Recuperar cada valor de propiedad a través de una función de get genera muchas llamadas de función adicionales por vista, lo que cuesta 110 μs.
Por lo tanto, habilitar ViewCapture en el seguimiento siempre activo (AOT) afecta negativamente el rendimiento del sistema y genera fallas. Debido a estas limitaciones de rendimiento y memoria, este enfoque aún no está listo para la AOT. Recomendamos ViewCapture solo para la depuración local y en el lab.
Memoria
El método de Perfetto para los seguimientos de ViewCapture usa un solo búfer de anillo, que tiene una huella de memoria predefinida para evitar el uso excesivo de memoria. Este enfoque evita el consumo excesivo de memoria, ya que evita el uso de búferes de anillo separados para cada ventana, pero no resuelve el problema de almacenar toda la jerarquía de vistas para cada estado en Perfetto para cada fotograma. La grabación de una sola ventana, como NexusLauncher, puede producir más de 30 segundos de datos de ViewCapture en un búfer de 10 MB. Sin embargo, capturar más de 30 ventanas de la IU del sistema requiere un búfer más grande o una ventana de tiempo de grabación mucho más corta.
Instrucciones
Sigue estas instrucciones para integrar ViewCapture en las apps del sistema:
Agrega la dependencia a tu archivo
Android.bp
, como se muestra en el código del selector.android_library { name: "YourLib", static_libs: [ ... "//frameworks/libs/systemui:view_capture", ... ], platform_apis: true, privileged: true, }
Crea una instancia de ViewCapture cuando crees tu ventana, por ejemplo:
-
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"); } ... }
-
Cierra la instancia de ViewCapture cuando destruyas la ventana, como se muestra en los siguientes ejemplos: