電話通訊時區偵測

如果是搭載 Android 11 以下版本的裝置,Android 開放原始碼計畫的自動時區偵測功能會參考電話子系統的信號。由於電話子系統的依附元件的關係,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 相符:
  • 美洲/丹佛
  • America/Phoenix

裝置已正確設為美國/丹佛。
亞利桑那州鳳凰城
冬季
時間: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 為止。

偵錯和測試

以下章節說明用於偵錯及測試電話時區偵測功能的殼層指令。

設定測試環境

測試人員通常會使用具有測試或模擬電話儲存格的測試環境,檢查電話時區偵測行為。測試單元可用於模擬具有不同 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")]}