מעקב אחר מעברים בחלונות באמצעות Winscope

‫Winscope הוא כלי אינטרנטי שמאפשר למשתמשים להקליט, להפעיל מחדש ולנתח את המצבים של כמה שירותי מערכת במהלך אנימציות ומעברים ואחריהם. ‫Winscope מתעד את כל מצבי שירות המערכת הרלוונטיים בקובץ מעקב. אפשר להשתמש בממשק המשתמש של Winscope עם קובץ המעקב כדי לבדוק את מצב השירותים האלה לכל פריים של אנימציה, עם או בלי הקלטת מסך, על ידי הפעלה חוזרת, מעבר בין פריים לפריים וניפוי באגים במעברים.

עקבות נתמכים

‫Winscope מאפשר לאסוף עקבות שונות או רצפים של מצבי שירותי מערכת, ולהציג אותם באופן חזותי. אפשר להגדיר את העקבות האלה כך שיתאימו לתרחישי שימוש ספציפיים, החל מתקורה נמוכה ועד למידע מפורט. ‫Winscope תומך בסוגי העקבות הבאים:

  • EventLog: איסוף של רשומת אירוע האבחון של המערכת באמצעות ‫EventLog. ב-Winscope, המידע הזה משמש רק לזיהוי ולהצגה של סימוני CUJ.
  • IME: מעקב אחרי אירועים מצינור הנתונים של עורך שיטות הקלט (IME), כולל IMS,‏ IMMS ולקוח IME.
  • קלט: מעקב אחר אירועי קלט מחלקים שונים בצינור של אירועי הקלט.
  • ProtoLog: איסוף הודעות ProtoLog משירותי מערכת ומהקוד של שירותי מערכת שפועלים בתהליכי לקוח.
  • הקלטת מסך: איסוף הקלטת מסך לצד העקבות.
  • מעברים בין מעטפות: פרטים על מערכת המעברים בין חלונות ופעילויות.
  • SurfaceFlinger: איסוף עקבות של SurfaceFlinger שמכילים מידע על משטחים (שכבות) כמו מיקום, מאגר והרכב.
  • עסקאות: מעקב אחר קבוצת השינויים האטומית שמתקבלת על ידי SurfaceFlinger באמצעות SurfaceControl לצורך קומפוזיציה.
  • ViewCapture: צילום טווח של מאפיינים של כל התצוגות ממערכת Windows שתומכות ב-ViewCapture, כמו ממשק המשתמש של המערכת ומרכז האפליקציות.
  • Window Manager: Trace Window Manager states containing details pertaining to windows, including input and focus events, screen orientation, transitions, animations, positioning, and transformations.

קובצי dump נתמכים

‫Winscope יכול לאסוף ולהציג קובצי dump של מצב המכשיר, שהם תמונות מצב של המכשיר שצולמו ברגעים ספציפיים שהוגדרו על ידי המשתמש. בניגוד לנתוני מעקב, שנאספים באופן רציף במהלך השימוש במכשיר ועשויים להשפיע על הביצועים, נתוני ה-dump נאספים רק ברגעים שהמשתמש מגדיר, וכך מובטח שהביצועים והפירוט לא ייפגעו. כך אפשר לבצע ניתוח ממוקד ויעיל יותר של מצב המכשיר בנקודות זמן ספציפיות. ‫Winscope תומך בדאמפים הבאים:

  • Window Manager: יצירת dump של מצב יחיד של Window Manager.
  • SurfaceFlinger: יצירת dump של snapshot יחיד של SurfaceFlinger.
  • צילום מסך: צילום מסך יצורף לקובצי ה-dump.

משאבים

מידע על בנייה והרצה של Winscope זמין במאמר בנושא הרצת Winscope.

מידע על איסוף עקבות זמין במאמר בנושא לכידת עקבות.

במאמר טעינת נתוני מעקב מוסבר איך לטעון נתוני מעקב באמצעות ממשק המשתמש של Winscope באינטרנט.

מידע על ניתוח עקבות זמין במאמר ניתוח עקבות.

דוגמאות

בדוגמה הבאה מתואר איך לנפות באגים בבדיקה של הבהובים ובבאג שדווח על ידי משתמש.

כשל בבדיקת הריצוד

בדוגמה הזו מוסבר איך להשתמש ב-Winscope כדי לנפות באגים בבדיקה של הבהובים.

בדיקת הכשל בבדיקה

כדי לזהות את סוג הבעיה ולבדוק את הודעת הכשל של הבדיקה, פועלים לפי השלבים הבאים.

  1. בודקים את שם הבדיקה ואת שם הכיתה כדי לקבוע את סוג הבעיה.

    שם הבדיקה ושם הכיתה:

    FlickerTestsNotification com.android.server.wm.flicker.notification.OpenAppFromLockscreenNotificationColdTest#appLayerBecomesVisible[ROTATION_0_GESTURAL_NAV]
    

    סוג הבעיה:

    • ה-CUJ מתייחס להפעלת אפליקציה מהתראה במסך הנעילה (OpenAppFromLockscreenNotificationColdTest).

    • הבדיקה מצפה שהאפליקציה תהיה גלויה (#appLayerBecomesVisible).

  2. בודקים את הודעת הכישלון של הבדיקה, שכוללת מידע מקיף על הכישלון, כולל:

    • השוואה בין התוצאה הצפויה לבין התוצאה הגלויה בפועל
    • חותמות זמן שיעזרו לזהות מתי הכשל התרחש
    • השם של הארטיפקט או הקובץ שמשויכים לכשל
    • מידע הקשרי נוסף שרלוונטי להבנה ולניפוי באגים של הכשל
    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)
    

    דוגמת הפלט הזו מציינת את הדברים הבאים:

    • הבעיה מתרחשת בשעה 2024-05-10T11:04:14.227572545.

    • הפרמטר NotificationActivity אמור להיות גלוי, אבל הוא לא.

    • שם קובץ הארטיפקט שמכיל את העקבות לניפוי הבאגים הוא FAIL__OpenAppFromLockscreenNotificationColdTest_ROTATION_0_GESTURAL_NAV.

ניפוי באגים

כדי לגלות מה גורם להבהוב, פועלים לפי השלבים הבאים:

  1. מורידים את קובצי המעקב וטוענים אותם ב-Winscope. ‫Winscope נפתח עם SurfaceFlinger שנבחר באופן אוטומטי:

    דף הנחיתה של Winscope עם תצוגה של SurfaceFlinger

    איור 1. דף הנחיתה של Winscope עם תצוגה של SurfaceFlinger.

  2. כדי לעבור לחותמת הזמן שבה הבעיה מתרחשת, מעתיקים את חותמת הזמן מהודעת החריגה ומדביקים אותה בשדה חותמת הזמן. אפשר להעתיק את חותמת הזמן בפורמט קריא (2024-05-10T11:04:14.227572545) ולהדביק אותה בשדה הראשון, או להעתיק את חותמת הזמן בננו-שניות (1715339054227572545ns) ולהדביק אותה בשדה השני.

    תיבת דו-שיח של חותמת זמן

    איור 2. תיבת דו-שיח של חותמת זמן.

  3. כדי לעבור למסגרת הקודמת, לוחצים על מקש החץ שמאלה. במצב הזה, האפליקציה NotificationActivity מוצגת בצורה תקינה בסרטון, ושני משטחי האפליקציה ומסך הפתיחה גלויים. אפשר לראות את זה לפי המלבנים הירוקים בתצוגה התלת-ממדית, ולפי הצ'יפ V באלמנטים ההיררכיים שלהם.

    שמות האפליקציה ומסך הפתיחה הם:

    com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#3458`
    
    Splash Screen com.android.server.wm.flicker.testapp#3453
    

    האינדיקציה הזו מציינת שהאפליקציה הופעלה כשהמסך הפך לשחור, ושהאירוע הזה קורה במהלך הפעלת האפליקציה, כי מסך הפתיחה עדיין מוצג:

    בהפעלת האפליקציה

    איור 3. בהפעלת האפליקציה.

  4. לוחצים על מקש החץ ימינה כדי לחזור למסגרת הבאה, שבה ההבהוב מתרחש. בתצוגת ה-rects, במקום האפליקציה מוצג NotificationShade במסך. המסכים הבאים מוצגים בפריים הזה:

    • שכבות-על של קישוטים במסך (למעלה ולמטה)
    • סרגל הניווט
    • מיקום הסמן (מתוך הקלטת המסך)

      פעילות הבהוב

      איור 4. פעילות ב-Flickr.

  5. בוחרים את פעילות האפליקציה בתצוגת ההיררכיה. אם לא מוצאים אותו, משביתים את האפשרות הצגת V בלבד. לאחר מכן, בודקים את תצוגת הנכסים.

    השם של משטח האפליקציה הוא:

    com.android.server.wm.flicker.testapp/com.android.server.wm.flicker.testapp.NotificationActivity#3458`
    

    נכסי אפליקציות

    איור 5. נכסי אפליקציות.

    למרות שהפעילות באפליקציה מוגדרת כגלויות ושקופות, השטח לא מוצג בגלל שגיאה Invisible due to: null visible region. הבעיה הזו מתרחשת כי משטח אטום אחר הוצב לפניו במהלך ההרכבה. ההשערה הזו נובעת מכך שהמלבן NotificationShade נמצא לפני המלבן NotificationActivity בתצוגה התלת-ממדית, והמלבן NotificationShade הירוק והגלוי הוא כנראה השכבה שנבחרה.

  6. כדי לאמת את ההשערה הזו, בוחרים את האזור הגלוי NotificationShade במסגרת הנוכחית ובודקים את המאפיינים שלו. הדגלים מוגדרים לערך OPAQUE|ENABLE_BACKPRESSURE (0x102). שם הפלטפורמה הוא NotificationShade.NotificationShade#3447 לאחר מכן, לוחצים על החץ שמאלה כדי לחזור למסגרת הקודמת (לפני ההבהוב) ובודקים שוב את המאפיינים של האובייקט NotificationShade. שימו לב שבמקום OPAQUE, יש רק את הדגל ENABLE_BACKPRESSURE (0x100). הפעולה הזו מאשרת ש-NotificationShade הופך לאטום לפני שהאפליקציה מסיימת את ההשקה. מכיוון שהסמל NotificationShade מופיע לפני הסמל NotificationActivity, האפליקציה לא מוצגת. הסמל NotificationShade שחור, ולכן המסך משחיר לרגע, מה שגורם להבהוב.

  7. בודקים בקוד למה NotificationShade הופך לאטום מוקדם מדי.

באג שדווח על ידי משתמש

קשה לנפות באגים שדווחו על ידי משתמשים כי לרוב חסר בהם מידע מפורט. בניגוד לדיווחים על כשלים בבדיקת הבהוב, שכוללים חותמות זמן ספציפיות, פרטי רכיבים והקלטות מסך, דיווחים על באגים שמתקבלים ממשתמשים כוללים בדרך כלל רק תיאור קצר של הבעיה.

במקרה לדוגמה שלנו, המידע היחיד שסופק הוא הכותרת המסך הבהב כשפותחים מחדש את האפליקציה מהמסך המפוצל וחותמת זמן משוערת של 18 באפריל 2024, ‏ 15:51 GMT-04:00.

כדי לנפות באג שדווח על ידי משתמש:

  1. טוענים את קובץ הפרטים ב-Winscope. ‫Winscope נפתח עם SurfaceFlinger שנבחר אוטומטית.

    דף הנחיתה של Winscope עם תצוגה של SurfaceFlinger

    איור 6. דף הנחיתה של Winscope עם תצוגה של SurfaceFlinger.

  2. כדי לנווט לחותמת הזמן המשוערת שדווחה על ידי המשתמש, במקרה הזה 3:50 PM GMT-04:00, מזינים 15:50:00 בשדה של חותמת הזמן שניתנת לקריאה על ידי בני אדם.

    תיבת דו-שיח של חותמת זמן

    איור 7. תיבת דו-שיח של חותמת זמן.

  3. אפשר להשתמש בתצוגת הריבועים כדי לזהות מה צויר על המסך. כדי לשנות את הפרספקטיבה של המלבנים, משתמשים בפס ההזזה סיבוב. אם מסמנים את האפשרויות הצגת V בלבד ושטוח בתצוגה היררכיה, אפשר לראות את הטפטים, את שכבת העיצוב של המסך, את הפסים השחורים בצדדים, את מרכז האפליקציות, את אנשי הקשר ואת חלונית החיוג.

    שמות החבילות הם:

    • מרכז האפליקציות: com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#40602

    • אנשי קשר: com.google.android.contacts/com.android.contacts.activities.PeopleActivity#40565

    • חייגן: com.google.android.dialer/com.google.android.dialer.extensions.GoogleDialtactsActivity#40564

    בנוסף למשטחים הגלויים (מלבנים ירוקים), מוצג מלבן אפור שמייצג את משטח אזור התצוגה, שנקרא תצוגה לא ידועה. כדי לשפר את הנראות, לוחצים על (סמל החשיפה) לצד הפלטפורמה ScreenDecorHwcOverlay#64 כדי להסתיר את המלבן המתאים ולחשוף את הפלטפורמות שמאחור. אנחנו מסירים את שכבת העל של הניתוח כי היא לא גלויה למשתמש ולא תדווח כאנימציה מהבהבת.

    דוח משתמשים

    איור 8. דוח משתמשים.

  4. אחרי שמזהים את הממשקים שמוצגים במסך המפוצל, משתמשים במעקב אחר המעברים כדי לעבור בין פעולות שונות של משתמשים ולמצוא את ההבהוב. לוחצים על הכרטיסייה Transitions ב-Winscope כדי לראות את רשימת המעברים שהופעלו:

    מעברים

    איור 9. מעברים.

    המעבר שמוצג במהלך המסגרת הזו מודגש בכחול. במקרה הזה, דגלי המעבר כוללים את TRANSIT_FLAG_IS_RECENTS, שמציין שהמשתמש נכנס למסך הפעולות האחרונות.

  5. לוחצים על הקישור בעמודה Dispatch Time (במקרה הזה 2024-04-18, 15:50:57.205) כדי לעבור לנקודת הזמן הזו ולאמת את המלבנים בכרטיסייה Surface Flinger. כדי לוודא שהמצב של המכשיר נכון במהלך המעבר, עוברים בין המצבים באמצעות מקש החץ שמאלה ומתבוננים במלבנים.

    ההפעלה מופיעה בשעה 15:50:57.278, אבל האנימציה לא מתחילה אז. הטפט כבר מוצג כי לא מצויר כלום בין האפליקציות במסך המפוצל (הקו המפריד). פריים אחד קודם (15:50:57.212), הטפט לא נראה, ומוצג הקו המפריד, כך נראה המסך המפוצל כשאין אנימציה.

    מסך לפני הבהוב

    איור 10. מסך לפני אירוע הבהוב.

  6. כדי לראות את המעבר הבא, לוחצים ישירות על ציר הזמן. מצבי SurfaceFlinger מיוצגים על ידי שורה של בלוקים כחולים בהירים. מעברים מיוצגים על ידי שורה של בלוקים ורודים.

    סוף המעבר הראשון

    איור 11. סוף המעבר הראשון.

    לוחצים על השורה SurfaceFlinger במיקום ההתחלה של המעבר הבא. באיור 11, המיקום האנכי של הסמן מסומן על ידי הקו הכחול הדק. הרקע התכלת של השורה SurfaceFlinger מראה את המיקום האופקי שלה. מקישים על מקש החץ שמאלה כדי לעבור בין המצבים ולבדוק אם יש הבהוב. מוודאים שהמכשיר נראה תקין למעבר הזה.

  7. מדלגים על המעבר הבא כי משך הזמן שלו קצר מאוד, ולכן לא סביר שהוא יכלול הבהוב. במקום זאת, לוחצים על ציר הזמן בשורה SurfaceFlinger במיקום ההתחלה של המעבר הארוך הבא, כמו שמצוין על ידי הסמן בתמונה הבאה.

    סוף המעבר השני

    איור 12. סוף המעבר השני.

    במהלך המעבר הזה, בנקודה 15:51:13.239, אפשר לראות שהשכבות של שתי האפליקציות, אנשי הקשר וחייגן הטלפון, נמצאות באותו צד של המסך:Splash Screen

    מסכי פתיחה

    איור 13. מסכי פתיחה.

  8. מציינים איזו אפליקציה נמצאת בצד הלא נכון. כדי להוסיף סימנייה למיקום הנוכחי, לוחצים על סמל הדגל לצד שדה הקלט ns. כך תוכלו לחזור למסגרת הזו בקלות בהמשך.

    הוספת סימנייה

    איור 14. הוספת סימנייה.

  9. כדי לנווט לפריים בסוף המעבר, לוחצים ישירות על ציר הזמן, למשל על 15:51:13.859. כאן שתי האפליקציות נמצאות במיקום הסופי שלהן, עם אפליקציית החייגן בצד שמאל ואפליקציית אנשי הקשר בצד ימין:

    מסך מפוצל סופי

    איור 15. מסך מפוצל סופי.

  10. לוחצים על דגל הסימניה בציר הזמן כדי לחזור למסגרת עם ההבהוב.

    ציר זמן של סימניות

    איור 16. סימון ציר הזמן.

    שתי האפליקציות נמצאות בצד ימין, מה שמצביע על כך שהחייגן נמצא במיקום שגוי.

  11. לוחצים על מסך הפתיחה של החייגן כדי לראות את המאפיינים שלו. כדאי לבדוק את מאפייני הטרנספורמציה שלו בתצוגה מאפיינים שנבחרה בקפידה.

    מאפייני הטרנספורמציה

    איור 17. מאפייני הטרנספורמציה.

    הטרנספורמציה המחושבת מוחלת על האזור הזה, אבל לא מוגדרת ברמה הזו. הערכים בעמודות המחושבות והעמודות המבוקשות שונים, מה שמצביע על כך שהטרנספורמציה עוברת בירושה מפלטפורמת אב.

  12. מבטלים את הסימון של שטוח בתצוגה ההיררכית כדי להציג את עץ ההיררכיה המלא, ומנווטים לצמתי האב של משטח האפליקציה עד ששני הערכים של טרנספורמציות מחושבות ונדרשות זהים, ורואים שהטרנספורמציה נדרשת במשטח Surface(name=Task=7934)/@0x1941191_transition-leash#40670.

  13. אפשר לבדוק מתי הוגדר השינוי לראשונה ומה היה הערך שלו. כדי לכווץ את המאפיינים שנבחרו, לוחצים על הסמל לצד הכותרת:

    כיווץ המאפיינים שנבחרו

    איור 18. מכווצים את הנכסים שנבחרו.

  14. בוחרים באפשרות Show diff (הצגת ההבדלים) בתצוגה Proto Dump כדי להדגיש את המאפיינים שמשתנים בפריים הזה. מקלידים transform בשדה החיפוש כדי לסנן את המאפיינים:

    הצגת ההבדלים

    איור 19. הצגת ההבדלים.

    הטרנספורמציה מוגדרת מ-IDENTITY ל-SCALE|TRANSLATE|ROT_270 בפריים הזה עבור transition-leash.

    המידע הזה מראה שההבהוב התרחש כשבוצע שינוי (transform) ב-animation leash של אפליקציית המסך המפוצל של חייגן.

    זיהוי ההבהוב

    איור 20. זיהוי ההבהוב.

  15. מזהים בקוד למה ההעברה הזו מוגדרת כרצועת מעבר למסך מפוצל.