במסגרת Android נעשה שימוש במקורות זמן שונים לסינכרון הזמן. בדף הזה נתמקד בפרוטוקול הזמן ברשת (NTP) ובמקורות זמן אוטומטיים של זהות הרשת ואזור הזמן (NITZ). כברירת מחדל ב-Android מגרסה 12 ואילך, המסגרת נותנת עדיפות ל-NTP כמקור הזמן על פני NITZ, כי NTP מדויק ואמין יותר מ-NITZ. במצבים שבהם NTP לא זמין, המסגרת חוזרת ל-NITZ. זוהי היפוך של סדר העדיפויות שמוגדר כברירת מחדל בגרסאות קודמות של הפלטפורמה. כברירת מחדל ב-Android מגרסה 11 ומטה, המסגרת נותנת עדיפות ל-NITZ על פני NTP.
פרטים נוספים על השינוי הזה זמינים בתיקוני ה-AOSP הבאים: 1563678, 1513323.
הגדרת העדיפות של מקורות הזמן
כדי להגדיר איזו מקור זמן יקבל עדיפות כברירת מחדל לגרסה ספציפית של Android, צריך להגדיר את המפתח config_autoTimeSourcesPriority ב-frameworks/base/core/res/res/values/config.xml בזמן הבנייה. הצעות לזמן שמגיעות ממקור הזמן שנמצא גבוה יותר ברשימה מקבלות עדיפות על פני מקורות שנמצאים נמוך יותר ברשימה.
מקורות הזמן של Android שאפשר להגדיר נמצאים ב-TimeDetectorStrategy.java.
כברירת מחדל, המקורות הבאים מוגדרים לשימוש:
- טלפוניה (NITZ)
- רשת (NTP)
בדיקה
כדי לוודא שהמכשיר משתמש ב-NITZ כש-NTP לא זמין (כשחבילת הגלישה וה-Wi-Fi מושבתים), מבצעים את הפעולות הבאות:
- מוודאים שיש כרטיס SIM תקין ב-DUT
- השבתת חבילת הגלישה וה-Wi-Fi
- מעבירים את המכשיר למצב טיסה כדי לוודא שרדיו הסלולר מושבת
- השבתת הזיהוי האוטומטי של השעה
- מגדירים את השעון באופן ידני לערך זמן שגוי בעתיד
- הפעלה מחדש של המכשיר
- הפעלת זיהוי אוטומטי של השעה
- להוציא את המכשיר ממצב טיסה
השלבים האלה מפעילים שינוי בשעון המערכת ברגע שמתקבל אות NITZ. כדי לבדוק איך השעה מוגדרת במכשיר, מריצים את הפקודה הבאה:
adb shell dumpsys time_detectorכדי לוודא שהשעון של המערכת משתמש ב-NITZ, בודקים את הפרטים הבאים בפלט של הפקודה:
mEnvironment.isAutoTimeDetectionEnabled()היאtrue.-
mEnvironment.autoOriginPriorities()מכיל רשימה של מקורות זמן, כאשר למקורות שמופיעים גבוה יותר ברשימה יש עדיפות על פני מקורות שמופיעים נמוך יותר ברשימה. - בקטע
Time change logאפשר לראות שהשעון של המערכת מוגדר באמצעות הצעה לשימוש בטלפון. - המקטע
Telephony suggestion historyמכיל הצעות למועדים. - הקטע
Network suggestion historyריק.
המועדים האפשריים לפגישה שמופיעים בקטע Telephony suggestion history ובקטע Network suggestion history נחשבים למקור המידע המהימן לגבי הזמן. אם המכשיר מחובר לאינטרנט ויש בו כרטיס SIM, ההצעות נוצרות באמצעות NTP (רשת) ו-NITZ (טלפוניה). במקרה הבדיקה הזה, רק הקטע Telephony suggestion history מכיל הצעות כי NTP מושבת.
בקטע Time change log מתועדים השינויים שבוצעו בשעון המערכת של המכשיר וההצעה שבה נעשה שימוש. השעון של המערכת מוגדר על סמך סדר מקורות הזמן ברשימת העדיפויות במפתח config_autoTimeSourcesPriority. עם זאת, יכול להיות שהמערכת תתעלם מהצעות ממקור בעדיפות גבוהה יותר אם ההצעה ישנה מדי או לא תקפה.
בנוסף, אם ההצעה התקפה בעדיפות הכי גבוהה תואמת לשעה הנוכחית בשעון המערכת של המכשיר בהפרש של כמה שניות, השעה לא תשתנה.
בתרחיש הבדיקה הזה, כל עוד ההצעות לא מיושנות, השעון של המערכת מוגדר באמצעות אחת מההצעות מ-Telephony suggestion history.
הדוגמה הבאה היא של פלט שבו המכשיר חוזר להשתמש ב-NITZ כש-NTP לא זמין.
TimeDetectorStrategy:
mLastAutoSystemClockTimeSet=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}
mEnvironment.isAutoTimeDetectionEnabled()=true
mEnvironment.elapsedRealtimeMillis()=73059
mEnvironment.systemClockMillis()=1614186767818
mEnvironment.systemClockUpdateThresholdMillis()=2000
mEnvironment.autoTimeLowerBound()=2021-02-24T15:44:15Z(1614181455000)
mEnvironment.autoOriginPriorities()=[network,telephony]
Time change log:
66261 / 2021-02-24T17:12:41.020Z - Set system clock using time=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000} cause=Found good telephony suggestion., bestTelephonySuggestion=TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]}, detectionReason=New telephony time suggested. timeSuggestion=TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]} elapsedRealtimeMillis=66259 newSystemClockMillis=1614186761019
Telephony suggestion history:
key idx: 0=0
val idx: 0=TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]}
Historic values=[
0@PT1M6.258S: TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]}
]
Network suggestion history:
{Empty}
Gnss suggestion history:
{Empty}
External suggestion history:
{Empty}
לצורך השוואה לפלט בתרחיש הבדיקה, הנה דוגמה לפלט אופייני שבו המכשיר מקבל הצעות לשעה ממקורות זמן של NTP ו-NITZ.
TimeDetectorStrategy:
mLastAutoSystemClockTimeSet=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}
mEnvironment.isAutoTimeDetectionEnabled()=true
mEnvironment.elapsedRealtimeMillis()=302926
mEnvironment.systemClockMillis()=1614186997685
mEnvironment.systemClockUpdateThresholdMillis()=2000
mEnvironment.autoTimeLowerBound()=2021-02-24T15:44:15Z(1614181455000)
mEnvironment.autoOriginPriorities()=[network,telephony]
Time change log:
66261 / 2021-02-24T17:12:41.020Z - Set system clock using time=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000} cause=Found good telephony suggestion., bestTelephonySuggestion=TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]}, detectionReason=New telephony time suggested. timeSuggestion=TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]} elapsedRealtimeMillis=66259 newSystemClockMillis=1614186761019
Telephony suggestion history:
key idx: 0=0
val idx: 0=TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]}
Historic values=[
0@PT1M6.258S: TelephonyTimeSuggestion{mSlotIndex='0', mUtcTime=TimestampedValue{mReferenceTimeMillis=66240, mValue=1614186761000}, mDebugInfo=[Sending new time suggestion nitzSignal=TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}}, reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=66240, mValue=NitzData{mOriginalString=21/02/24,17:12:41+00,00, mZoneOffset=0, mDstOffset=0, mCurrentTimeMillis=1614186761000, mEmulatorHostTimeZone=null}})]}
]
Network suggestion history:
0@PT4M4.04S: NetworkTimeSuggestion{mUtcTime=TimestampedValue{mReferenceTimeMillis=244038, mValue=1614186939242}, mDebugInfo=[Origin: NetworkTimeUpdateService. event=3]}
Gnss suggestion history:
{Empty}
External suggestion history:
{Empty}