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

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

עקבות נתמכים

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

  • EventLog: איסוף של רשומת אירוע אבחון המערכת באמצעות ‫EventLog. ב-Winscope, המידע הזה משמש רק לזיהוי ולהצגה של סימוני CUJ.
  • IME: מעקב אחרי אירועים מצינור הנתונים של עורך שיטות הקלט (IME), כולל IMS,‏ IMMS ו-IME Client.
  • קלט: מעקב אחר אירועי קלט מחלקים שונים בצינור של אירועי הקלט.
  • 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 a single Window Manager state.
  • 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 במסך. המסכים הבאים מוצגים בפריים הזה:

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

    פעילות ב-Flickr

    איור 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 rect נמצא לפני NotificationActivity rect בתצוגה התלת-ממדית, ו-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. אפשר להשתמש בתצוגת ה-rects כדי לזהות מה צויר על המסך. כדי לשפר את התצוגה, משתמשים בפס ההזזה סיבוב כדי לשנות את הפרספקטיבה של המלבנים. אם מסמנים את האפשרויות הצגת 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

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

    דוח משתמשים

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

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

    מעברים

    איור 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. בוחרים באפשרות הצגת ההבדלים בתצוגה Proto Dump כדי להדגיש את המאפיינים שמשתנים בפריים הזה. מקלידים transform בשדה החיפוש כדי לסנן את המאפיינים:

    הצגת ההבדלים

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

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

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

    זיהוי ההבהוב

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

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