ViewCapture to narzędzie, które rejestruje właściwości widoków (takie jak lokalizacja, rozmiar, skala i widoczność) dołączonych do okien, z którymi jest powiązane. ViewCapture rejestruje informacje o różnych widokach w oknie i ich właściwościach, dzięki czemu możesz poznać stan wrażeń użytkownika w określonych momentach i śledzić zmiany w czasie.
Nagrania ekranu mogą wizualizować stan widoku w określonym czasie i pokazywać, jak się on zmienia, ale wymagają znacznych zasobów procesora i mogą wpływać na wydajność. Narzędzie ViewCapture ma mniejszy wpływ na zasoby i można je włączać częściej. Dodatkowo ViewCapture wyświetla wizualizacje klatka po klatce na poziomie widoku, co ułatwia sprawdzanie stanu widoku w określonych momentach w porównaniu z nagraniami ekranu.
Na tej stronie opisujemy, jak wdrożyć ViewCapture w aplikacjach systemowych.
Użyj
ViewCapture.java implementuje instancję onDrawListener i zbiera ślad ViewCapture podczas procesu rysowania. Każde ponowne narysowanie klatki powoduje przejście przez hierarchię drzewa widoków, zaczynając od widoku głównego okna.
ViewCapture używa publicznych metod pobierania View.java, aby pobierać i kopiować wartości do wątku w tle, co zwiększa wydajność. Implementacja ViewCapture optymalizuje ten proces, sprawdzając, czy widok jest nieaktualny lub unieważniony, za pomocą captureViewTree, dzięki czemu nie trzeba przechodzić przez całą hierarchię widoków. captureViewTree jest dostępna tylko w przypadku aplikacji systemowych i jest częścią interfejsu UnsupportedAppUsage API.
Korzystanie z tego interfejsu API jest ograniczone do aplikacji w zależności od docelowej wersji pakietu SDK.
Ograniczenia
W tej sekcji opisano ograniczenia wydajności i pamięci funkcji ViewCapture.
Wydajność
Średni narzut głównego wątku w przypadku wydajności ViewCapture wynosi 195 μs. W najgorszych przypadkach może to zająć około 5 ms. Sprawdź wycinek vc#onDraw w śladzie Perfetto.
Koszty ogólne wynikają głównie z tych działań:
- Przejście przez hierarchię kosztuje 50 μs, nawet w przypadku przycinania.
- Pobieranie obiektów z alokatora listy swobodnej w celu przechowywania kopii właściwości widoku kosztuje 20 μs.
- Pobieranie wartości każdej właściwości za pomocą funkcji pobierającej powoduje wiele dodatkowych wywołań funkcji na widok, co kosztuje 110 μs.
Włączenie funkcji ViewCapture w trybie śledzenia na wygaszonym ekranie (AOT) negatywnie wpływa na wydajność systemu i powoduje zacinanie się obrazu. Ze względu na te ograniczenia wydajności i pamięci to podejście nie jest gotowe do kompilacji AOT. Zalecamy używanie funkcji ViewCapture tylko do debugowania w laboratorium i lokalnie.
Pamięć
Metoda Perfetto do śledzenia ViewCapture używa pojedynczego bufora pierścieniowego o zdefiniowanym rozmiarze pamięci, aby zapobiec nadmiernemu wykorzystaniu pamięci. Takie podejście zapobiega nadmiernemu zużyciu pamięci, ponieważ nie wymaga oddzielnych buforów pierścieniowych dla każdego okna. Nie rozwiązuje to jednak problemu z przechowywaniem całej hierarchii widoków dla każdego stanu w Perfetto w przypadku każdej klatki. Nagrywanie pojedynczego okna, np. NexusLauncher, może wygenerować ponad 30 sekund danych ViewCapture w buforze o rozmiarze 10 MB. Przechwytywanie ponad 30 okien interfejsu systemu wymaga większego bufora lub znacznie krótszego czasu nagrywania.
Instrukcje
Aby wdrożyć ViewCapture w aplikacjach systemowych, wykonaj te czynności:
Dodaj zależność do pliku
Android.bp, jak pokazano w kodzie Launchera.android_library { name: "YourLib", static_libs: [ ... "//frameworks/libs/systemui:view_capture", ... ], platform_apis: true, privileged: true, }Podczas tworzenia okna utwórz instancję ViewCapture, na przykład:
-
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"); } ... }
-
Zamknij instancję ViewCapture podczas niszczenia okna, jak pokazano w tych przykładach:
-
@Override public void onDestroy() { ... if (mViewCapture != null) mViewCapture.close(); } -
@Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mViewCaptureCloseable != null) { mViewCaptureCloseable.close(); } ... }
-