電話時區檢測

對於運行 Android 11 或更低版本的設備,AOSP 中的自動時區檢測依賴於來自電話子系統的信號。由於依賴於電話子系統,Android 11 或更低版本上的自動時區檢測僅限於電話設備。

當電話時區檢測可用時,它使用移動國家代碼 (MCC)網絡身份和時區 (NITZ)信號工作。

例如,法國的設備可以僅根據附近基站報告的 MCC 來識別時區。這是可能的,因為眾所周知法國使用單一時區。

當一個國家/地區使用多個時區時,僅 MCC 不足以識別時區。對於這些國家/地區,該設備還使用 NITZ 信號來識別正確的時區。這在世界上許多地方都很好用,但它要求 NITZ 信號既可用又正確,因此它依賴於運營商。

電話時區檢測是一種無源檢測器。它始終運行,因此即使time_zone_detector來源當前不是電話,也經常提出電話建議。

電話時區檢測的限制

即使有正確的 NITZ 信號可用,電話時區檢測也並不總是在每個國家都能正常工作。這是因為 NITZ 僅包含偏移量和夏令時信息,這些信息並不總是足以唯一地標識時區。

世界上有很多地方可能會出現這個時區問題。例如,美國的科羅拉多州丹佛市和亞利桑那州的鳳凰城在冬季無法使用 NITZ 信號進行區分,但在其他季節可以。任何具有類似重疊時區的位置都可能遇到此類問題。

下表以丹佛和鳳凰城為例,根據季節細分了設備行為:

地點和季節來自 MCC 或 NITZ 的信息檢測到的時區和行為
科羅拉多州丹佛
冬天
時間:2021年1月1日12:00:00
國家:美國
偏移量:UTC-7,無夏令時
兩個區域 ID 匹配:
  • 美國/丹佛
  • 美國/鳳凰

設備正確設置為美國/丹佛。
亞利桑那州鳳凰城
冬天
時間:2021年1月1日12:00:00
國家:美國
偏移量:UTC-7,無夏令時
兩個區域 ID 匹配:
  • 美國/丹佛
  • 美國/鳳凰

設備被錯誤地設置為美國/丹佛。
科羅拉多州丹佛
夏天
時間:2021年7月1日12:00:00
國家:美國
偏移量:UTC-6,夏令時
一個區域 ID 匹配:
  • 美國/丹佛

設備正確設置為美國/丹佛。
亞利桑那州鳳凰城
夏天
時間:2021年7月1日12:00:00
國家:美國
偏移量:UTC-7,無夏令時
一個區域 ID 匹配:
  • 美國/鳳凰

設備正確設置為 America/Phoenix。

上面的示例表明,在冬季,丹佛或亞利桑那州的 Android 設備必須選擇兩個匹配的時區 ID 之一,這對於某些設備可能不正確,但仍顯示明顯正確的本地時間。即使時區 ID 不正確,設備時鐘、日曆和其他應用程序也會顯示預期的本地時間,因為兩個時區 ID 在冬季計算的本地時間相同。

但是,在春季丹佛實行夏令時而鳳凰城沒有時,如果某些設備為用戶所在位置設置了錯誤的時區 ID,則它們可能會暫時顯示不正確的本地時間。一旦設備接收到新的 NITZ 信號(特別是包含“UTC-7,無夏令時”偏移信息的信號),此問題就會得到糾正,但這可能需要一些時間並且取決於運營商。

因此,從冬季到春季存儲或攜帶時區 ID 的日曆或其他應用程序可能會顯示和使用錯誤的本地時間,直到相關應用程序更新時區 ID。

調試和測試

以下部分描述了用於調試和測試電話時區檢測功能的 shell 命令。

測試環境設置

測試人員通常使用帶有測試或模擬電話單元的測試環境來檢查電話時區檢測行為。測試單元可用於模擬具有不同 MCC 的網絡,並將 NITZ 信號發送到設備,然後監測其效果。

設備要檢測時區,NITZ 信號信息必須正確,與 MCC 一致,並且與設備的 IANA TZDB(時區規則)副本相匹配。與 MCC 不一致的 NITZ 信號會導致電話來源變得不確定。

例如,如果測試單元使用的 MCC 用於美國,則 NITZ 信號必須包含適用於美國某處的“通用時間”、偏移量和夏令時信息。

與 com.android.phone 服務交互

要驗證設備是否正在接收正確的電話時區建議,請使用:

adb shell dumpsys activity service \
    com.android.phone/com.android.phone.TelephonyDebugService

這會轉儲電話信息,這些信息也可以在 Android 錯誤報告中找到。在具有多個 SIM 卡的設備上,每個 SIM 卡無線電都有信息。

時區日誌顯示電話進程已發送到 time_zone_detector 的建議以及發送建議的原因。

TimeServiceHelperImpl:
          SystemClock.elapsedRealtime()=11864061
          System.currentTimeMillis()=1620652067178
          Time Logs:
...

Time zone Logs:
    18602 / 2021-05-10T09:50:21.718Z - Suggesting time zone update:
    TelephonyTimeZoneSuggestion{mSlotIndex=0, mZoneId='null', mMatchType=0, mQuality=0,
    mDebugInfo=[getTimeZoneSuggestion: nitzSignal=TimestampedValue{mReferenceTimeMillis=14098,
    mValue=NitzData{mOriginalString=21/05/10,09:50:18+04,01, mZoneOffset=3600000,
    mDstOffset=3600000, mCurrentTimeMillis=1620640218000, mEmulatorHostTimeZone=null}},
    countryIsoCode=null, Detection
    reason=handleNitzReceived(TimestampedValue{mReferenceTimeMillis=14098,
    mValue=NitzData{mOriginalString=21/05/10,09:50:18+04,01, mZoneOffset=3600000,
    mDstOffset=3600000, mCurrentTimeMillis=1620640218000, mEmulatorHostTimeZone=null}})]}
    18831 / 2021-05-10T09:50:21.948Z - Suggesting time zone update:
    TelephonyTimeZoneSuggestion{mSlotIndex=0, mZoneId='Europe/London', mMatchType=3, mQuality=1,
    mDebugInfo=[findTimeZoneFromCountryAndNitz: countryIsoCode=gb,
    nitzSignal=TimestampedValue{mReferenceTimeMillis=14098,
    mValue=NitzData{mOriginalString=21/05/10,09:50:18+04,01, mZoneOffset=3600000,
    mDstOffset=3600000, mCurrentTimeMillis=1620640218000, mEmulatorHostTimeZone=null}},
    findTimeZoneFromCountryAndNitz: lookupResult=OffsetResult{mTimeZone(ID)=Europe/London,
    mIsOnlyMatch=true}, Detection reason=handleCountryDetected("gb")]}