テレフォニーによるタイムゾーン検出

Android 11 以前を搭載しているデバイスの場合、AOSP の自動タイムゾーン検出は、テレフォニー サブシステムからの信号に依存します。テレフォニー サブシステムに依存しているため、Android 11 以前では、タイムゾーンの自動検出はテレフォニー デバイスに限定されています。

テレフォニーによるタイムゾーン検出を使用できる場合は、MCC(モバイル カントリー コード)NITZ(ネットワーク ID とタイムゾーン)の信号を使用して動作します。

たとえば、フランスにあるデバイスは、近くの基地局から報告された MCC のみに基づいてタイムゾーンを識別できます。これは、フランスでは 1 つのタイムゾーンを使用することがわかっているためです。

1 つの国で複数のタイムゾーンが使用されている場合、MCC だけではタイムゾーンを特定できません。そのような国では、デバイスは NITZ 信号を使用して正しいタイムゾーンを識別します。これは世界中の多くの地域でうまく機能しますが、NITZ 信号が利用可能かつ正確であることが必要なため、携帯通信会社に依存します。

テレフォニーによるタイムゾーン検出は、受動的な検出機能です。これは常に実行されるため、多くの場合、time_zone_detector オリジンが現在テレフォニーでない場合でも、テレフォニーによる提案が行われます。

テレフォニーによるタイムゾーン検出に関する制限

正しい NITZ 信号が利用可能な場合でも、テレフォニーによるタイムゾーン検出がすべての国で常に機能するとは限りません。これは、NITZ に含まれているのはオフセットと夏時間情報だけであるため、必ずしもタイムゾーンを一意に特定できるとは限らないためです。

このようなタイムゾーンの問題が発生する場所は世界中に多数あります。たとえば、米国のコロラド州デンバーとアリゾナ州フェニックスは、冬の間は NITZ 信号を使用して区別することはできませんが、他の季節では区別できます。タイムゾーンに同じような重複が発生する場所では、この種の問題が発生する可能性があります。

以下の表は、例としてデンバーとフェニックスの季節ごとにデバイスの動作を分類したものです。

場所と季節 MCC または NITZ からの情報 検出されたタイムゾーンと動作
コロラド州デンバー
時刻: 2021 年 1 月 1 日 12:00:00
国: 米国
オフセット: UTC-7、夏時間なし
2 つのゾーン ID が一致:
  • America/Denver
  • America/Phoenix

デバイスは正しく「America/Denver」に設定される。
アリゾナ州フェニックス
時刻: 2021 年 1 月 1 日 12:00:00
国: 米国
オフセット: UTC-7、夏時間なし
2 つのゾーン ID が一致:
  • America/Denver
  • America/Phoenix

デバイスが誤って「America/Denver」に設定される。
コロラド州デンバー
時刻: 2021 年 7 月 1 日 12:00:00
国: 米国
オフセット: UTC-6、夏時間
1 つのゾーン ID が一致:
  • America/Denver

デバイスは正しく「America/Denver」に設定される。
アリゾナ州フェニックス
時刻: 2021 年 7 月 1 日 12:00:00
国: 米国
オフセット: UTC-7、夏時間なし
1 つのゾーン ID が一致:
  • America/Phoenix

デバイスは正しく「America/Phoenix」に設定される。

上記の例では、冬の間、デンバーまたはアリゾナにある Android デバイスは、タイムゾーン ID が一致した 2 つのうちいずれかを選択しなければならないということを示しています。一部のデバイスでは選択されたタイムゾーン ID が正しくない場合もありますが、現地時刻は正しく表示されます。タイムゾーン ID が正しくない場合でも、デバイス クロック、カレンダーなどのアプリでは、正しい現地時刻が表示されます。これは、冬の間はどちらのタイムゾーン ID でも同じ現地時刻が算出されるためです。

しかし、春になるとデンバーは夏時間を実施し、フェニックスは実施しないため、ユーザーの位置情報に間違ったタイムゾーン ID が設定されていると一時的に間違った現地時刻が表示される場合があります。これは、デバイスが新しい NITZ 信号(具体的には「UTC-7、夏時間なし」のオフセット情報を含む信号)を受信するとすぐに修正されますが、これには時間がかかることがあり、その動作は携帯通信会社に依存します。

そのため、冬から春までの間、タイムゾーン ID の保存または持ち越しを行うカレンダーなどのアプリでは、関連するアプリがタイムゾーン ID を更新するまで、間違った現地時刻が表示、使用される可能性があります。

デバッグとテスト

以下では、テレフォニーによるタイムゾーン検出機能のデバッグとテストを行うためのシェルコマンドについて説明します。

テスト環境の設定

一般に、テスターは、テスト用のテレフォニー セルまたはシミュレートされたテレフォニー セルのあるテスト環境を使用して、テレフォニーによるタイムゾーン検出の動作を確認します。テストセルを使用して、さまざまな MCC を含むネットワークをシミュレートし、NITZ 信号をデバイスに送信して、その結果をモニタリングできます。

デバイスがタイムゾーンを検出するには、NITZ 信号の情報が正確であり、MCC と一致していて、デバイスの IANA TZDB(タイムゾーン ルール)と一致している必要があります。NITZ 信号が MCC と一致しないと、テレフォニーのオリジンが不確定となります。

たとえば、テストセルで使用する 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")]}