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

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