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 כדי לנפות באגים בבדיקה של הבהובים.
בדיקת הכשל בבדיקה
כדי לזהות את סוג הבעיה ולבדוק את הודעת הכשל של הבדיקה, פועלים לפי השלבים הבאים.
בודקים את שם הבדיקה ואת שם הכיתה כדי לקבוע את סוג הבעיה.
שם הבדיקה ושם הכיתה:
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. פעילות ב-Flickr.
בוחרים את פעילות האפליקציה בתצוגת ההיררכיה. אם לא מוצאים אותו, משביתים את האפשרות הצגת 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 GMT-04:00.
כדי לנפות באג שדווח על ידי משתמש:
טוענים את קובץ הפרטים ב-Winscope. Winscope נפתח עם SurfaceFlinger שנבחר אוטומטית.
איור 6. דף הנחיתה של Winscope עם תצוגה של SurfaceFlinger.
כדי לנווט לחותמת הזמן המשוערת שדווחה על ידי המשתמש, במקרה הזה
3:50 PM GMT-04:00
, מזינים15:50:00
בשדה של חותמת הזמן שניתנת לקריאה על ידי בני אדם.איור 7. תיבת דו-שיח של חותמת זמן.
אפשר להשתמש בתצוגת הריבועים כדי לזהות מה צויר על המסך. כדי לשנות את הפרספקטיבה של המלבנים, משתמשים בפס ההזזה סיבוב. אם מסמנים את האפשרויות הצגת 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. דוח משתמשים.
אחרי שמזהים את הממשקים שמוצגים במסך המפוצל, משתמשים במעקב אחר המעברים כדי לעבור בין פעולות שונות של משתמשים ולמצוא את ההבהוב. לוחצים על הכרטיסייה Transitions ב-Winscope כדי לראות את רשימת המעברים שהופעלו:
איור 9. מעברים.
המעבר שמוצג במהלך המסגרת הזו מודגש בכחול. במקרה הזה, דגלי המעבר כוללים את
TRANSIT_FLAG_IS_RECENTS
, שמציין שהמשתמש נכנס למסך הפעולות האחרונות.לוחצים על הקישור בעמודה Dispatch Time (במקרה הזה
2024-04-18, 15:50:57.205
) כדי לעבור לנקודת הזמן הזו ולאמת את המלבנים בכרטיסייה Surface Flinger. כדי לוודא שהמצב של המכשיר נכון במהלך המעבר, עוברים בין המצבים באמצעות מקש החץ שמאלה ומתבוננים במלבנים.ההפעלה מופיעה בשעה 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. מאפייני הטרנספורמציה.
הטרנספורמציה המחושבת מוחלת על האזור הזה, אבל לא מוגדרת ברמה הזו. הערכים בעמודות המחושבות והעמודות המבוקשות שונים, מה שמצביע על כך שהטרנספורמציה עוברת בירושה מפלטפורמת אב.
מבטלים את הסימון של שטוח בתצוגה ההיררכית כדי להציג את עץ ההיררכיה המלא, ומנווטים לצמתי האב של משטח האפליקציה עד ששני הערכים של טרנספורמציות מחושבות ונדרשות זהים, ורואים שהטרנספורמציה נדרשת במשטח
Surface(name=Task=7934)/@0x1941191_transition-leash#40670
.אפשר לבדוק מתי הוגדר השינוי לראשונה ומה היה הערך שלו. כדי לכווץ את המאפיינים שנבחרו, לוחצים על הסמל לצד הכותרת:
איור 18. מכווצים את הנכסים שנבחרו.
בוחרים באפשרות Show diff (הצגת ההבדלים) בתצוגה Proto Dump כדי להדגיש את המאפיינים שמשתנים בפריים הזה. מקלידים
transform
בשדה החיפוש כדי לסנן את המאפיינים:איור 19. הצגת ההבדלים.
הטרנספורמציה מוגדרת מ-
IDENTITY
ל-SCALE|TRANSLATE|ROT_270
בפריים הזה עבורtransition-leash
.המידע הזה מראה שההבהוב התרחש כשבוצע שינוי (transform) ב-animation leash של אפליקציית המסך המפוצל של חייגן.
איור 20. זיהוי ההבהוב.
מזהים בקוד למה ההעברה הזו מוגדרת כרצועת מעבר למסך מפוצל.