Winscope to narzędzie internetowe, które umożliwia użytkownikom nagrywanie, odtwarzanie i analizowanie stanów kilku usług systemowych podczas animacji i przechodów oraz po ich zakończeniu. Winscope rejestruje wszystkie istotne stany usług systemowych w pliku śledzonym. Za pomocą interfejsu użytkownika Winscope i pliku śladu możesz sprawdzić stan tych usług w przypadku każdego klatki animacji (z opcją nagrywania ekranu lub bez niej), odtwarzając, przechodząc i debugując przejścia.
Obsługiwane ścieżki
Winscope umożliwia zbieranie i wizualne przedstawianie różnych ścieżek lub sekwencji stanów usług systemowych. Możesz konfigurować te ścieżki pod kątem konkretnych przypadków użycia, od ścieżek z minimalnym obciążeniem po ścieżki z wysoką szczegółowością. Winscope obsługuje te ścieżki:
- EventLog: zbieranie rekordu zdarzenia diagnostycznego systemu za pomocą
EventLog
. W Winscope informacje te są używane tylko do identyfikowania i wyświetlania znaków CUJ. - IME: śledzenie zdarzeń z kanału Edytora metody wprowadzania (IME), w tym IMS, IMMS i klienta IME.
- Wejście: śledzenie zdarzeń wejściowych z różnych części potoku zdarzeń wejściowych.
- ProtoLog: zbieranie ProtoLog wiadomości z usług systemowych i kodu usług systemowych działających w procesach klienta.
- Nagrywanie ekranu: obok śladów należy zebrać nagranie ekranu.
- Przejścia w powłoce: rejestrowanie szczegółów systemu dotyczących przejścia z okna na okno i z aktywności.
- SurfaceFlinger: zbiera SurfaceFlingerścieżki zawierające informacje o powierzchniach (warstwach), takie jak pozycja, bufor i kompozycja.
- Transakcje: śledzenie zestawu zmian atomowych otrzymanych przez SurfaceFlingera za pomocą
SurfaceControl
do kompozycji. - ViewCapture: umożliwia rejestrowanie różnych właściwości wszystkich widoków z systemowych okien, które obsługują funkcję ViewCapture, takich jak interfejs Systemu i wydatki.
- Window Manager: śledzone Window Managerstany zawierające szczegóły dotyczące okien, w tym zdarzenia związane z wprowadzaniem danych i uzyskiwaniem fokusa, orientację ekranu, przejścia, animacje, pozycjonowanie i transformacje.
Obsługiwane zrzuty ekranu
Winscope może zbierać i wyświetlać stany urządzenia, czyli migawki stanu urządzenia w określonych momentach zdefiniowanych przez użytkownika. W odróżnieniu od śladów, które są stale zbierane podczas korzystania z urządzenia i mogą wpływać na wydajność, zrzuty są wykonywane tylko w określonych momentach określonych przez użytkownika, co pozwala zachować wydajność i szczegółowość. Umożliwia to bardziej ukierunkowaną i skuteczną analizę stanu urządzenia w określonych momentach. Winscope obsługuje te rodzaje zrzutów:
- Window Manager: zrzut stanu pojedynczego menedżera okien.
- SurfaceFlinger: zrzut pojedynczego zrzutu ekranu SurfaceFlinger.
- Zrzut ekranu: zrzut ekranu wraz z dumpami.
Materiały
Informacje o tworzeniu i uruchamianiu Winscope znajdziesz w artykule Uruchamianie Winscope.
Informacje o zbieraniu śladów znajdziesz w artykule Zapisywanie śladów.
Informacje o wczytywaniu śladów znajdziesz w artykule Wczytywanie śladów.
Informacje o analizowaniu śladów znajdziesz w artykule Analiza śladów.
Przykłady
Ten przykład pokazuje, jak debugować niepowodzenie testu migotania i zgłaszany przez użytkownika błąd.
Niepowodzenie testu migotania
Ten przykład pokazuje, jak za pomocą Winscope debugować nieudany test migotania.
Sprawdzanie niepowodzenia testu
Aby określić typ problemu i zbadać komunikat o niepowodzeniach testu, wykonaj te czynności.
Określ typ problemu, badając nazwę testu i klasy.
Nazwa testu i zajęć:
FlickerTestsNotification com.android.server.wm.flicker.notification.OpenAppFromLockscreenNotificationColdTest#appLayerBecomesVisible[ROTATION_0_GESTURAL_NAV]
Typ problemu:
CUJ dotyczy uruchamiania aplikacji z powiadomienia na ekranie blokady (
OpenAppFromLockscreenNotificationColdTest
).Test zakłada, że aplikacja będzie widoczna (
#appLayerBecomesVisible
).
Sprawdź komunikat o nieudanym teście, który zawiera obszerne informacje o nieudanym teście, w tym:
- Porównanie oczekiwanego wyniku z rzeczywistym widocznym wynikiem
- sygnatury czasowe, które pomogą określić, kiedy wystąpił błąd;
- Nazwa artefaktu lub pliku powiązanego z błędem
- dodatkowe informacje kontekstowe przydatne do zrozumienia i debugowania błędu;
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)
Ten przykład danych wyjściowych wskazuje:
Problem występuje w miejscu
2024-05-10T11:04:14.227572545
.Parametr
NotificationActivity
powinien być widoczny, ale tak nie jest.Nazwa pliku artefaktu zawierającego ścieżki do debugowania to
FAIL__OpenAppFromLockscreenNotificationColdTest_ROTATION_0_GESTURAL_NAV
.
Debuguj
Aby określić przyczynę migotania:
Pobierz pliki śledzone i załaduj je w Winscope. Winscope otwiera się z automatycznie wybranym SurfaceFlinger:
Rysunek 1. Strona docelowa Winscope z widokiem w SurfaceFlinger.
Przejdź do sygnatury czasowej, w której występuje problem, kopiując i wklejając sygnaturę czasową z komunikatu o wyjątku do pola sygnatury czasowej. Możesz skopiować sygnaturę czasową w czytelnym formacie (
2024-05-10T11:04:14.227572545
) i wkleić ją w pierwszym polu lub skopiować sygnaturę czasową w nanosekundach (1715339054227572545ns
) i wkleić ją w drugim polu.Rysunek 2. Okno sygnatury czasowej
Aby przejść do poprzedniego kadru, naciśnij strzałkę w lewo. W tym stanie aplikacja NotificationActivity jest prawidłowo wyświetlana na filmie, a powierzchnie aplikacji i ekranu powitalnego są widoczne. Są one oznaczone zielonymi prostokątami w widoku 3D i elementem V w hierarchii.
Nazwa aplikacji i ekranu powitalnego:
com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#3458` Splash Screen com.android.server.wm.flicker.testapp#3453
Oznacza to, że aplikacja była uruchamiana, gdy ekran stał się czarny, oraz że to zdarzenie ma miejsce podczas uruchamiania aplikacji, ponieważ ekran powitalny jest nadal widoczny:
Rysunek 3. Podczas uruchamiania aplikacji.
Naciśnij klawisz strzałki w prawo, aby przejść do następnego klatki, w której występuje migotanie. W widoku prostokątów zamiast aplikacji na ekranie wyświetlany jest
NotificationShade
. W tym kadrze wyświetlane są te elementy:- Dekoracyjne nakładki ekranu (górna i dolna)
- Pasek nawigacyjny
Lokalizacja wskaźnika (z nagrania ekranu)
Rysunek 4. aktywność na Flickerze.
W widoku hierarchii wybierz aktywność aplikacji. Jeśli nie możesz jej znaleźć, odznacz opcję Pokaż tylko V, a potem sprawdź widok usług.
Nazwa interfejsu aplikacji:
com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#3458`
Rysunek 5. Właściwości aplikacji.
Chociaż aktywność w aplikacji jest ustawiona jako widoczna i nieprzejrzysta, nie jest wyświetlana z powodu błędu
Invisible due to: null visible region
. Dzieje się tak, ponieważ podczas komponowania na obrazie umieszczono inną nieprzezroczystą powierzchnię. Ta hipoteza wynika z tego, że prostokątNotificationShade
znajduje się z przodu prostokątaNotificationActivity
w widoku 3D, a widoczny (zielony) prostokątNotificationShade
może być wybraną warstwą.Aby zweryfikować tę hipotezę, wybierz widoczną
NotificationShade
powierzchnię na bieżącej klatce i sprawdź jej właściwości. Flagi są ustawione naOPAQUE|ENABLE_BACKPRESSURE (0x102)
. Nazwa powierzchniNotificationShade
toNotificationShade#3447
. Następnie naciśnij strzałkę w lewo, aby wrócić do poprzedniej ramki (przed migotaniem), i ponownie sprawdź właściwości powierzchniNotificationShade
. Zwróć uwagę, że zamiastOPAQUE
na powierzchni widnieje tylko flagaENABLE_BACKPRESSURE (0x100)
. Potwierdza to, żeNotificationShade
staje się nieprzezroczysty przed pełnym uruchomieniem aplikacji. PonieważNotificationShade
znajduje się przedNotificationActivity
, aplikacja nie jest wyświetlana.NotificationShade
jest czarny, więc ekran na chwilę staje się czarny, co powoduje migotanie.Określ w kodzie, dlaczego element
NotificationShade
staje się nieprzezroczysty zbyt wcześnie.
Błąd zgłoszony przez użytkownika
Błędy zgłaszane przez użytkowników mogą być trudne do zdebugowania, ponieważ często brakuje im szczegółowych informacji. W odróżnieniu od błędów zgłaszanych przez użytkowników, które zawierają konkretne sygnatury czasowe, szczegóły elementów i nagrania ekranu, błędy wykrywane przez testy migotania zawierają zazwyczaj tylko krótki opis problemu.
W przypadku analizy tylko jedna informacja jest podana w tytule: Ekran migotał po ponownym otwarciu aplikacji z podzielonego ekranu. Przybliżona sygnatura czasowa to 18.04.2024 3:51 GMT-04:00.
Aby debugować błąd zgłoszony przez użytkownika:
Załaduj plik śladu w Winscope. Winscope otwiera się z automatycznie wybranym SurfaceFlingerem.
Rysunek 6. Strona docelowa Winscope z widokiem w SurfaceFlinger.
Przejdź do przybliżonego sygnatury czasowej zgłoszonej przez użytkownika, w tym przypadku
3:50 PM GMT-04:00
, wpisując15:50:00
w polu sygnatury czasowej zrozumiałej dla człowieka.Rysunek 7. Okno sygnatury czasowej
Użyj widoku prostokątów, aby określić, co zostało narysowane na ekranie. Aby uzyskać lepszy widok, użyj suwaka Obrót, aby zmienić perspektywę prostokątów. Jeśli w widoku Hierarchia zaznaczysz Pokaż tylko V i Płaski, widoczne będą tapeta, nakładka na ekran, ramka, launcher, kontakty i powierzchnie wybierania.
Nazwa pakietu:
Menu:
com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#40602
Kontakty:
com.google.android.contacts/com.android.contacts.activities.PeopleActivity#40565
Dialer:
com.google.android.dialer/com.google.android.dialer.extensions.GoogleDialtactsActivity#40564
Oprócz widocznych powierzchni (zielone prostokąty) wyświetla się szary prostokąt, który reprezentuje obszar wyświetlacza o nazwie Nieznany wyświetlacz. Aby poprawić widoczność, kliknij ikonę (
) obok powierzchni
ScreenDecorHwcOverlay#64
, aby ukryć odpowiadający jej prostokąt i pokazać powierzchnie znajdujące się za nim. Usunęliśmy na potrzeby analizy nakładkę, ponieważ nie jest ona widoczna dla użytkownika i nie zostanie zgłoszona jako migająca animacja.Rysunek 8. Raport o użytkowniku.
Gdy już określisz, które powierzchnie są widoczne na podzielonym ekranie, użyj śledzenia przejść, aby sprawdzić różne działania użytkownika i znaleźć migotanie. Aby wyświetlić listę odtwarzanych przejść, kliknij kartę Przejścia w Winscope:
Rysunek 9. Przejścia.
Przejście odtwarzane w tej klatce jest wyróżnione na niebiesko. W tym przypadku flagi przejścia obejmują
TRANSIT_FLAG_IS_RECENTS
, co wskazuje, że użytkownik wchodzi na ekran Ostatnie.Kliknij link w kolumnie Czas wysyłki (w tym przypadku
2024-04-18, 15:50:57.205
), aby przejść do tego punktu w czasie i sprawdzać prostokąty na karcie Surface Flinger. Sprawdź, czy stan urządzenia jest prawidłowy podczas przejścia, przechodząc przez przejście za pomocą prawego klawisza strzałki i obserwując prostokąty.Launcher pojawia się o 15:50:57.278, ale animacja nie rozpoczyna się w tym momencie. Tapeta jest już widoczna, ponieważ nic nie jest wyświetlane między aplikacjami na podzielonym ekranie (podziałka). Na jednym ujęciu wcześniejszym (15:50:57.212) tapeta jest niewidoczna, a widoczny jest podział ekranu. Tak wygląda ekran podzielony, gdy nie jest animowany.
Rysunek 10. Ekran przed zdarzeniem migotania.
Aby sprawdzić następny przewrót, kliknij bezpośrednio osi czasu. Stany SurfaceFlinger są reprezentowane przez rząd jasnoniebieskich bloków. Przejścia są oznaczone rzędem różowych bloków.
Rysunek 11. Koniec pierwszego przejścia.
Kliknij wiersz SurfaceFlinger w pozycji początkowej następnego przejścia. Na rysunku 11 pionowa pozycja kursora jest oznaczona cienką niebieską linią. Jasnobłękitne tło wiersza SurfaceFlinger wskazuje jego pozycję poziomą. Przejdź przez przejście za pomocą klawisza strzałki w prawo, aby sprawdzić, czy występuje migotanie. Sprawdź, czy urządzenie jest odpowiednie do przeprowadzenia tej zmiany.
Pomiń następne przejście, ponieważ jego czas trwania jest bardzo krótki i nie zawiera prawdopodobnie migotania. Zamiast tego kliknij ścieżkę w wierszu SurfaceFlinger w miejscu rozpoczęcia następnego dłuższego przejścia, jak pokazano na poniższym obrazie.
Rysunek 12. Koniec drugiego przejścia.
Podczas tego przejścia na ekranie
15:51:13.239
obaSplash Screen
warstwy obu aplikacji, kontaktów i dialera, znajdują się po tej samej stronie ekranu:Rysunek 13. ekrany powitalne.
Określ, która aplikacja jest po niewłaściwej stronie. Aby dodać zakładkę do bieżącej pozycji, kliknij ikonę flagi obok pola wejściowego ns. Dzięki temu łatwiej będzie Ci później wrócić do tego kadru.
Rysunek 14. Dodaj zakładkę.
Przejdź do klatki na końcu przejścia, klikając na osi czasu bezpośrednio, na przykład
15:51:13.859
. Teraz obie aplikacje znajdują się w swoim docelowym miejscu: Dialer po lewej stronie, a Kontakty – po prawej:Rysunek 15. Ostatni podzielony ekran.
Aby wrócić do kadru z migotaniem, kliknij flagę zakładki na osi czasu.
Rysunek 16. Oś czasu z zakładkami.
Obie aplikacje są po prawej stronie, co oznacza, że aplikacja Telefon jest w niewłaściwym miejscu.
Kliknij ekran powitalny wybierarki, aby wyświetlić jej właściwości. Szczególnie przyjrzyj się właściwościom przekształcenia w wybranym widoku Właściwości.
Rysunek 17. Przekształcanie właściwości.
Obliczona transformacja jest stosowana na tej powierzchni, ale nie jest ustawiona jako ta poziom. Kolumny obliczenia i żądania mają różne wartości, co wskazuje, że transformacja jest dziedziczona z poziomu powierzchni nadrzędnej.
Odznacz opcję Płaski w widoku hierarchii, aby wyświetlić całe drzewo hierarchii, a potem przejdź do węzłów nadrzędnych interfejsu aplikacji, aż oba elementy Obliczone i Żądane będą takie same, co oznacza, że transformacja jest żądana na interfejsie
Surface(name=Task=7934)/@0x1941191_transition-leash#40670
.Sprawdź, kiedy i na jaką wartość została ustawiona transformacja. Zmniejsz widoczność właściwości z rekomendacjami, klikając ikonę obok tytułu:
Rysunek 18. Zwiń zweryfikowane właściwości.
W widoku Proto Dump wybierz Pokaż różnice, aby wyróżnić właściwości, które są zmieniane w danej ramie. Aby przefiltrować właściwości, wpisz
transform
w polu wyszukiwania tekstowego:Rysunek 19. Pokaż różnice.
W tym interwale dla
transition-leash
transformacja jest ustawiona zIDENTITY
naSCALE|TRANSLATE|ROT_270
.Te informacje wskazują, że migotanie wystąpiło, gdy transformacja została zastosowana do łańcucha animacji aplikacji Dialer na podzielonym ekranie.
Rysunek 20. Identyfikacja migotania.
W kodzie określ, dlaczego ta transformacja jest ustawiona na łańcuch przejścia na podzielony ekran.