Śledzenie przejść między oknami za pomocą narzędzia Winscope

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.

  1. 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).

  2. 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:

  1. Pobierz pliki śledzone i załaduj je w Winscope. Winscope otwiera się z automatycznie wybranym SurfaceFlinger:

    Strona docelowa Winscope z widokiem SurfaceFlinger

    Rysunek 1. Strona docelowa Winscope z widokiem w SurfaceFlinger.

  2. 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.

    Okno sygnatury czasowej

    Rysunek 2. Okno sygnatury czasowej

  3. 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:

    Podczas uruchamiania aplikacji

    Rysunek 3. Podczas uruchamiania aplikacji.

  4. 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)

      Aktywność związana z miganiem

      Rysunek 4. aktywność na Flickerze.

  5. 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`
    

    Właściwości aplikacji

    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ąt NotificationShade znajduje się z przodu prostokąta NotificationActivity w widoku 3D, a widoczny (zielony) prostokąt NotificationShade może być wybraną warstwą.

  6. Aby zweryfikować tę hipotezę, wybierz widoczną NotificationShadepowierzchnię na bieżącej klatce i sprawdź jej właściwości. Flagi są ustawione na OPAQUE|ENABLE_BACKPRESSURE (0x102). Nazwa powierzchni NotificationShade to NotificationShade#3447. Następnie naciśnij strzałkę w lewo, aby wrócić do poprzedniej ramki (przed migotaniem), i ponownie sprawdź właściwości powierzchni NotificationShade. Zwróć uwagę, że zamiast OPAQUE na powierzchni widnieje tylko flaga ENABLE_BACKPRESSURE (0x100). Potwierdza to, że NotificationShade staje się nieprzezroczysty przed pełnym uruchomieniem aplikacji. Ponieważ NotificationShade znajduje się przed NotificationActivity, aplikacja nie jest wyświetlana. NotificationShade jest czarny, więc ekran na chwilę staje się czarny, co powoduje migotanie.

  7. 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:

  1. Załaduj plik śladu w Winscope. Winscope otwiera się z automatycznie wybranym SurfaceFlingerem.

    Strona docelowa Winscope z widokiem SurfaceFlinger

    Rysunek 6. Strona docelowa Winscope z widokiem w SurfaceFlinger.

  2. Przejdź do przybliżonego sygnatury czasowej zgłoszonej przez użytkownika, w tym przypadku 3:50 PM GMT-04:00, wpisując 15:50:00 w polu sygnatury czasowej zrozumiałej dla człowieka.

    Okno sygnatury czasowej

    Rysunek 7. Okno sygnatury czasowej

  3. 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 VPł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ę (ikona widoczności) 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.

    Raport o użytkowniku

    Rysunek 8. Raport o użytkowniku.

  4. 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:

    przejścia,

    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.

  5. 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.

    Ekran przed migotaniem

    Rysunek 10. Ekran przed zdarzeniem migotania.

  6. 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.

    Koniec pierwszego przejścia

    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.

  7. 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.

    koniec drugiego przejścia

    Rysunek 12. Koniec drugiego przejścia.

    Podczas tego przejścia na ekranie 15:51:13.239oba Splash Screenwarstwy obu aplikacji, kontaktów i dialera, znajdują się po tej samej stronie ekranu:

    ekrany powitalne

    Rysunek 13. ekrany powitalne.

  8. 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.

    dodawanie zakładek,

    Rysunek 14. Dodaj zakładkę.

  9. 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:

    Ostatni podzielony ekran

    Rysunek 15. Ostatni podzielony ekran.

  10. Aby wrócić do kadru z migotaniem, kliknij flagę zakładki na osi czasu.

    oś czasu zakładek

    Rysunek 16. Oś czasu z zakładkami.

    Obie aplikacje są po prawej stronie, co oznacza, że aplikacja Telefon jest w niewłaściwym miejscu.

  11. 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.

    Właściwości transformacji

    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.

  12. 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Żądane będą takie same, co oznacza, że transformacja jest żądana na interfejsie Surface(name=Task=7934)/@0x1941191_transition-leash#40670.

  13. Sprawdź, kiedy i na jaką wartość została ustawiona transformacja. Zmniejsz widoczność właściwości z rekomendacjami, klikając ikonę obok tytułu:

    zwinąć wybrane właściwości

    Rysunek 18. Zwiń zweryfikowane właściwości.

  14. 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:

    show diff

    Rysunek 19. Pokaż różnice.

    W tym interwale dla transition-leash transformacja jest ustawiona z IDENTITY na SCALE|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.

    Identyfikacja migotania

    Rysunek 20. Identyfikacja migotania.

  15. W kodzie określ, dlaczego ta transformacja jest ustawiona na łańcuch przejścia na podzielony ekran.