Winscope הוא כלי אינטרנט שמאפשר למשתמשים לתעד, להפעיל מחדש ולנתח את המצבים של כמה שירותי מערכת במהלך אנימציות ומעברים ואחריהן. Winscope מתעד את כל מצבי השירות הרלוונטיים במערכת בקובץ מעקב. באמצעות ממשק המשתמש של Winscope עם קובץ המעקב, אפשר לבדוק את המצב של השירותים האלה בכל פריים של האנימציה, עם או בלי הקלטת מסך, על ידי הפעלה חוזרת של המעברים, ניתוח שלהם בניתוחים צעדים ותיקון באגים.
מעקבים נתמכים
Winscope מאפשר לאסוף מעקבים שונים או רצפים של מצבי שירות המערכת ולהציג אותם באופן חזותי. אפשר להגדיר את הטרייסים האלה בהתאם לתרחישי שימוש ספציפיים, החל מעומסי עבודה נמוכים ועד לרמת פירוט גבוהה. אלה הטראסים שנתמכים ב-Winscope:
- EventLog: איסוף הרשומה של אירוע האבחון של המערכת באמצעות
EventLog
. ב-Winscope, המידע הזה משמש רק לזיהוי ולתצוגה של סימנים של CUJ. - IME: מעקב אחר אירועים מצינור עיבוד הנתונים של עורך שיטות הקלט (IME), כולל IMS, IMMS ו-IME Client.
- קלט: מעקב אחר אירועי קלט מחלקים שונים בצינור עיבוד הנתונים של אירועי הקלט.
- ProtoLog: איסוף הודעות ProtoLog משירותי המערכת והקוד של שירותי המערכת שפועלים בתהליכי הלקוח.
- הקלטת מסך: צילום מסך לצד הנתונים.
- מעבר בין מעטפות: תיעוד פרטי המערכת של מעבר בין חלונות ופעילויות.
- SurfaceFlinger: איסוף נתוני מעקב של SurfaceFlinger שמכילים מידע על משטחים (שכבות), כמו מיקום, מאגר ותמהיל.
- Transactions: מעקב אחרי קבוצת השינויים האטומיים שהתקבלו על ידי SurfaceFlinger באמצעות
SurfaceControl
לצורך יצירה. - ViewCapture: צילום מגוון מאפיינים של כל התצוגות מחלונות המערכת שתומכים ב-ViewCapture, כמו ממשק המשתמש של המערכת ומרכז האפליקציות.
- מנהל חלונות: מעקב אחרי מצבים של מנהל החלונות שמכילים פרטים שקשורים לחלונות, כולל אירועי קלט ומיקוד, כיוון המסך, מעברים, אנימציות, מיקום וטרנספורמציות.
קובצי dump נתמכים
Winscope יכול לאסוף ולהציג דמפים של מצב, שהם קובצי snapshot של מצב המכשיר שצולמו ברגעים ספציפיים שהוגדרו על ידי המשתמש. בניגוד למעקב אחר נתונים, שנאסף באופן רציף במהלך השימוש במכשיר ויכול להשפיע על הביצועים, יצירת קבצים זמניים מתבצעת רק ברגעים שהוגדרו על ידי המשתמש, כדי להבטיח שהביצועים והרמת רמת הפירוט לא יושפעו. כך אפשר לבצע ניתוח ממוקד ויעיל יותר של מצב המכשיר בנקודות זמן ספציפיות. אלה קובצי ה-dump שנתמכים ב-Winscope:
- מנהל חלונות: יצירת גרסת dump של מצב יחיד של מנהל החלונות.
- SurfaceFlinger: יצירת dump של קובץ snapshot יחיד של SurfaceFlinger.
- צילום מסך: צריך לצלם מסך לצד ה-dumps.
משאבים
במאמר הפעלת Winscope מוסבר איך יוצרים ומפעילים את Winscope.
מידע נוסף על איסוף נתוני מעקב זמין במאמר תיעוד נתוני מעקב.
במאמר העלאת נתוני מעקב מוסבר איך מעלים נתוני מעקב באמצעות ממשק המשתמש של Winscope באינטרנט.
מידע נוסף על ניתוח נתוני מעקב זמין במאמר ניתוח נתוני מעקב.
דוגמאות
בדוגמה הבאה מוסבר איך לנפות באגים של כשל בבדיקה של הבהוב ובאג שדווח על ידי משתמש.
הבדיקה של התנודות בבהירות נכשלה
בדוגמה הזו מוסבר איך משתמשים ב-Winscope כדי לנפות באגים בבדיקה של הבהוב.
בדיקת הכישלון בבדיקה
כדי לקבוע את סוג הבעיה ולבדוק את הודעת הכישלון של הבדיקה, פועלים לפי השלבים הבאים.
כדי לקבוע את סוג הבעיה, בודקים את שם המבחן ואת שם הכיתה.
שם הבדיקה והכיתה:
FlickerTestsNotification com.android.server.wm.flicker.notification.OpenAppFromLockscreenNotificationColdTest#appLayerBecomesVisible[ROTATION_0_GESTURAL_NAV]
סוג הבעיה:
ב-CUJ מתייחסים להפעלת אפליקציה מהתראה במסך הנעילה (
OpenAppFromLockscreenNotificationColdTest
).לפי הבדיקה, האפליקציה אמורה להיות גלויה (
#appLayerBecomesVisible
).
בודקים את הודעת הכשל של הבדיקה, שמספקת מידע מקיף על הכשל, כולל:
- השוואה בין התוצאה הצפויה לבין התוצאה הגלויה בפועל
- חותמות זמן שיעזרו לכם לזהות מתי אירעה התקלה
- השם של הארטיפקט או הקובץ שמשויכים לכשלים
- מידע נוסף לפי הקשר שרלוונטי להבנת התקלה ולניפוי הבאגים שלה
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
.
ניפוי באגים
כדי לקבוע מה גורם לרטט:
מורידים את קובצי המעקב ומטעינים אותם ב-Winscope. Winscope נפתח עם SurfaceFlinger שנבחר באופן אוטומטי:
איור 1. דף נחיתה של Winscope עם תצוגת SurfaceFlinger.
כדי לנווט לחותמת הזמן שבה מתרחשת הבעיה, מעתיקים את חותמת הזמן מהודעת החריגה ומדביקים אותה בשדה חותמת הזמן. אפשר להעתיק את חותמת הזמן בפורמט שקריא לבני אדם (
2024-05-10T11:04:14.227572545
) ולהדביק אותה בשדה הראשון, או להעתיק את חותמת הזמן בננו-שניות (1715339054227572545ns
) ולהדביק אותה בשדה השני.איור 2. תיבת הדו-שיח של חותמת הזמן.
מקישים על מקש החץ שמאלה כדי לנווט לפריים הקודם. במצב הזה, אפליקציית 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. כשהאפליקציה מופעלת.
מקישים על מקש החץ ימינה כדי לנווט חזרה לפריים הבא, שבו מתרחש הפליקרים. בתצוגת rects,
NotificationShade
מוצג במסך במקום האפליקציה. המשטחים הבאים מוצגים בפריים הזה:- שכבות-על לקישוט המסך (למעלה ולמטה)
- סרגל הניווט
מיקום הסמן (מהקלטת המסך)
איור 4. פעילות של הבהוב.
בוחרים את פעילות האפליקציה בתצוגת ההיררכיה. אם הוא לא מופיע, משביתים את המתג שליד Show only 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
הגלוי (הירוק) הוא השכבה שנבחרה.כדי לאמת את ההשערה הזו, בוחרים את פני השטח
NotificationShade
הגלוי בפריים הנוכחי ובודקים את המאפיינים שלו. הדגלים מוגדרים לערךOPAQUE|ENABLE_BACKPRESSURE (0x102)
. שם הפלטפורמה שלNotificationShade
הואNotificationShade#3447
. לאחר מכן, לוחצים על החץ ימינה כדי לחזור לפריים הקודם (לפני הפליקרים) ובודקים שוב את המאפיינים של המשטחNotificationShade
. שימו לב שבמקוםOPAQUE
, הדגלENABLE_BACKPRESSURE (0x100)
מופיע רק על פני השטח. כך אפשר לוודא ש-NotificationShade
הופך לאטום לפני שהאפליקציה מוכנה להשקה. מכיוון שה-NotificationShade
מופיע לפני ה-NotificationActivity
, האפליקציה לא מוצגת. ה-NotificationShade
הוא שחור, ולכן המסך משחיר לרגע, מה שגורם לרטט.בודקים בקוד למה
NotificationShade
הופך לאטום מוקדם מדי.
באג שדווח על ידי משתמש
לפעמים קשה לנפות באגים שדווחו על ידי משתמשים כי לרוב הם לא כוללים מידע מפורט. בניגוד לכשל בבדיקה של הבהוב, שמספק חותמות זמן ספציפיות, פרטי רכיבים והקלטות מסך, בדרך כלל באגים שמדווחים על ידי משתמשים כוללים רק תיאור קצר של הבעיה.
בדוח המחקר שלנו, המידע היחיד שסופק הוא הכותרת המסך הבהיק כשפתחתי מחדש את האפליקציה מהמסך המפוצל וחותמת זמן משוערת של 18 באפריל 2024, 15:51 (שעון גריניץ', שעה פחות 4).
כדי לנפות באג שדווח על ידי משתמש:
טוענים את קובץ המעקב ב-Winscope. Winscope נפתח עם SurfaceFlinger שנבחר באופן אוטומטי.
איור 6. דף נחיתה של Winscope עם תצוגת SurfaceFlinger.
כדי לנווט לחותמת הזמן המשוערת שדווחה על ידי המשתמש, במקרה הזה
3:50 PM GMT-04:00
, מזינים15:50:00
בשדה של חותמת הזמן שקריא לבני אדם.איור 7. תיבת הדו-שיח של חותמת הזמן.
משתמשים בתצוגת rects כדי לזהות מה צויר על המסך. כדי לקבל תצוגה טובה יותר, משתמשים בפס ההזזה Rotation כדי לשנות את הפרספקטיבה של המלבנים. אם מסמנים את האפשרויות Show only V ו-Flat בתצוגה Hierarchy, אפשר לראות את הטפט, שכבת-העל של 'עיצוב המסך', פורמט Letterbox, מרכז האפליקציות, אנשי הקשר ומסך החיוג.
שמות החבילות הם:
מרכז האפליקציות:
com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#40602
אנשי קשר:
com.google.android.contacts/com.android.contacts.activities.PeopleActivity#40565
Dialer:
com.google.android.dialer/com.google.android.dialer.extensions.GoogleDialtactsActivity#40564
בנוסף למשטחים הגלויים (ריבועים ירוקים), מוצג מלבן אפור שמייצג את המשטח של אזור התצוגה, שנקרא Unknown display. כדי לשפר את החשיפה, לוחצים על (
) לצד המשטח
ScreenDecorHwcOverlay#64
כדי להסתיר את המלבן התואם ולהציג את המשטחים שמאחוריו. אנחנו מסירים את שכבת-העל לצורך הניתוח כי היא לא גלויה למשתמש ולא תדווח כאנימציה מהבהבת.איור 8. דוח משתמש.
אחרי שמזהים את המשטחים שקשורים לתצוגת המסך המפוצל, משתמשים בניתוח המעברות כדי לעבור על פעולות שונות של משתמשים ולמצוא את התנודות. לוחצים על הכרטיסייה Transitions ב-Winscope כדי להציג גרפית את רשימת המעברים שהופעלו:
איור 9. מעברים.
המעבר שהופעל במהלך הפריים הזה מודגש בכחול. במקרה הזה, דגלים המעבר כוללים את הערך
TRANSIT_FLAG_IS_RECENTS
, שמציין שהמשתמש נכנס למסך 'מהזמן האחרון'.לוחצים על הקישור בעמודה Dispatch Time (במקרה הזה
2024-04-18, 15:50:57.205
) כדי לנווט לנקודת הזמן הזו ולאמת את ה-rects בכרטיסייה Surface Flinger. כדי לוודא שהמצב של המכשיר תקין במהלך המעבר, אפשר להקיש על מקש החץ הימני ולעקוב אחרי המעבר תוך התבוננות ב-rects.מרכז האפליקציות מופיע בשעה 15:50:57.278, אבל האנימציה לא מתחילה באותו זמן. הטפט כבר גלוי כי לא מצויר דבר בין האפליקציות במסך המפוצל (המחיצה). בפריים אחד קודם (15:50:57.212), הטפט לא גלוי והמפריד מוצג. כך נראה המסך המפוצל כשאין אנימציה.
איור 10. המסך לפני אירוע הבהוב.
כדי לבדוק את המעבר הבא, לוחצים ישירות על ציר הזמן. המצבים של SurfaceFlinger מיוצגים בשורה של בלוקים כחולים בהירים. מעברים מיוצגים בשורה של בלוקים ורוד.
איור 11. סוף המעבר הראשון.
לוחצים על השורה SurfaceFlinger במיקום ההתחלה של המעבר הבא. באיור 11, המיקום האנכי של הסמן מסומן על ידי הקו הכחול הדק. הרקע הכחול בהיר של השורה SurfaceFlinger מציג את המיקום האופקי שלה. מקישים על מקש החץ ימינה כדי לעבור בין התמונות ולראות אם יש הבהוב. מוודאים שהמכשיר נראה מתאים למעבר הזה.
כדאי לדלג על המעבר הבא כי משך הזמן שלו קצר מאוד, ולכן סביר להניח שהוא לא מכיל הבהוב. במקום זאת, לוחצים על ציר הזמן בשורה של SurfaceFlinger במיקום ההתחלה של המעבר הארוך הבא, כפי שמצוין על ידי הסמן בתמונה הבאה.
איור 12. סוף המעבר השני.
במהלך המעבר הזה, בשלב
15:51:13.239
, אפשר לראות שהשכבותSplash Screen
של שתי האפליקציות, אנשי הקשר והמרכז לחיוג נמצאות באותו צד של המסך:איור 13. מסכי פתיחה.
יש לציין איזו אפליקציה נמצאת בצד הלא נכון. כדי להוסיף סימנייה למיקום הנוכחי, לוחצים על סמל הדגל לצד שדה הקלט ns. כך תוכלו לחזור למסגרת הזו מאוחר יותר.
איור 14. מוסיפים סימנייה.
כדי לנווט למסגרת בסוף המעבר, לוחצים ישירות על ציר הזמן, למשל על
15:51:13.859
. כאן שתי האפליקציות נמצאות במיקום הסופי שלהן, עם חייגן בצד ימין ואנשי קשר בצד שמאל:איור 15. המסך המפוצל הסופי.
לוחצים על הדגל של הסימניה בציר הזמן כדי לחזור לפריים עם התנודות.
איור 16. ציר הזמן של הסימניות.
שתי האפליקציות נמצאות בצד שמאל, מה שמצביע על כך שהחייגן נמצא במיקום שגוי.
לוחצים על מסך הפתיחה של חייגן כדי להציג את המאפיינים שלו. כדאי לבדוק במיוחד את מאפייני הטרנספורמציה שלו בתצוגה נכסים שנבחרו.
איור 17. טרנספורמציה של מאפיינים.
הטרנספורמציה המחושבת חלה על המשטח הזה, אבל לא מוגדרת ברמה הזו. העמודות המחושבות והעמודות המבוקשות כוללות ערכים שונים, מה שמציין שהטרנספורמציה עוברת בירושה מפני השטח של ההורה.
מבטלים את הבחירה באפשרות Flat בתצוגה היררכית כדי להציג את עץ ההיררכיה כולו, מנווטים לקודמי העץ של ממשק האפליקציה עד שהטרנספורמציות Calculated ו-Requested זהות, ומציגים את הטרנספורמציה שנשלחה לממשק
Surface(name=Task=7934)/@0x1941191_transition-leash#40670
.מוודאים מתי הטרנספורמציה הוגדרה לראשונה ואיזה ערך הוגדרה. כדי לכווץ את הנכסים שנבחרו, לוחצים על הסמל לצד השם:
איור 18. מכווצים את הנכסים שנבחרו.
בוחרים באפשרות Show diff בתצוגה Proto Dump כדי להדגיש את המאפיינים שמשתנים בפריים הזה. מקלידים
transform
בשדה החיפוש של הטקסט כדי לסנן את המאפיינים:איור 19. הצגת ההבדלים.
ההמרה מוגדרת מ-
IDENTITY
ל-SCALE|TRANSLATE|ROT_270
בפריים הזה שלtransition-leash
.המידע הזה מראה שהבהוב התרחש כשהטרנספורמציה הוחלו על שרשור האנימציה של האפליקציה של חייגן המסך המפוצל.
איור 20. זיהוי התנודות.
מאתרים בקוד את הסיבה לכך שהטרנספורמציה הזו מוגדרת לשרשור המעבר למסך מפוצל.