העדיפות של מקור הזמן

המערכת של Android משתמשת במקורות זמן שונים לסנכרון זמן. הדף הזה מתמקד במקורות הזמן האוטומטיים של Network Time Protocol‏ (NTP) ו-Network Identity and Time Zone‏ (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 בזמן ה-build. השעה הצעות ממקור הזמן שנמצא במיקום גבוה יותר ברשימה מקבלות עדיפות לעומת מקורות שנמוכים יותר ברשימה.

מקורות הזמן של Android שאפשר להגדיר נמצאים ב TimeDetectorStrategy.java המקורות הבאים מוגדרים לשימוש כברירת מחדל:

  • טלפוניה (NITZ)
  • רשת (NTP)

בדיקה

כדי לוודא שהמכשיר משתמש ב-Nitz כש-NTP לא זמין (כשחבילת הגלישה וה-Wi-Fi מושבתים), מבצעים את הפעולות הבאות:

  1. מוודאים שיש כרטיס SIM פעיל ב-DUT
  2. איך משביתים את חבילת הגלישה ואת ה-Wi-Fi
  3. מעבירים את המכשיר למצב טיסה כדי לוודא שהרדיו הסלולרי כבוי
  4. איך משביתים את זיהוי הזמן האוטומטי
  5. אפשר להגדיר את השעון באופן ידני לערך זמן שגוי בעתיד
  6. הפעלה מחדש של המכשיר
  7. הפעלת זיהוי הזמן האוטומטי
  8. הוצאת המכשיר ממצב טיסה

השלבים האלה מפעילים שינוי בשעון המערכת ברגע שמתקבל אות 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}