Telephony Time Zone Detection

For devices running Android 11 or lower, automatic time zone detection in the AOSP relies on signals from the telephony subsystem. Because of the dependency on the telephony subsystem, automatic time zone detection on Android 11 or lower is limited to telephony devices.

When telephony time zone detection is available, it works using the Mobile Country Code (MCC) and Network Identity and Time Zone (NITZ) signals.

For example, a device in France can identify the time zone based solely on the MCC reported by nearby cell towers. This is possible because France is known to use a single time zone.

When a country uses multiple time zones, the MCC alone isn't enough to identify the time zone. For these countries, the device also uses NITZ signals to identify the correct time zone. This works well in many places around the world but it requires that NITZ signals are both available and correct and it's therefore dependent on carriers.

Telephony time zone detection is a passive detector. It runs at all times and so telephony suggestions are often made even when the time_zone_detector origin isn't currently telephony.

Limitation of telephony time zone detection

Even with correct NITZ signals available, telephony time zone detection doesn't always work well in every country. This is because NITZ only contains offset and daylight savings information, which aren't always enough to uniquely identify a time zone.

There are many places in the world where this time zone problem might occur. For example, Denver Colorado and Phoenix Arizona in the US can't be distinguished using NITZ signals during winter, but can during other seasons. Any location with similarly overlapping time zones may experience this kind of issue.

The following table breaks down the device behavior depending on the season for Denver and Phoenix as an example:

Location and season Information from MCC or NITZ Detected time zone and behavior
Denver, Colorado
Winter
Time: 1st January 2021 12:00:00
Country: US
Offset: UTC-7, no daylight savings
Two zone IDs match:
  • America/Denver
  • America/Phoenix

Device is correctly set to America/Denver.
Phoenix, Arizona
Winter
Time: 1st January 2021 12:00:00
Country: US
Offset: UTC-7, no daylight savings
Two zone IDs match:
  • America/Denver
  • America/Phoenix

Device is incorrectly set to America/Denver.
Denver, Colorado
Summer
Time: 1st July 2021 12:00:00
Country: US
Offset: UTC-6, daylight savings
One zone ID matches:
  • America/Denver

Device is correctly set to America/Denver.
Phoenix, Arizona
Summer
Time: 1st July 2021 12:00:00
Country: US
Offset: UTC-7, no daylight savings
One zone ID matches:
  • America/Phoenix

Device is correctly set to America/Phoenix.

The examples above show that during winter, Android devices in Denver or Arizona must choose one of two matching time zone IDs, which may be incorrect for some devices but still display an apparently correct local time. The device clock, calendars and other apps display the expected local time even if the time zone ID is incorrect because both time zone IDs calculate the same local time during winter.

However, in spring when Denver observes daylight savings time and Phoenix does not, some devices may temporarily show the incorrect local time if they are set to the wrong time zone ID for the user's location. This is corrected as soon as the device receives a new NITZ signal (specifically, one that contains "UTC-7, no daylight savings" offset information), but this can take some time and is dependent on carriers.

As a result, calendars or other apps that store or carry over the time zone ID from winter to spring might display and use the wrong local time until the relevant apps update the time zone ID.

Debugging and testing

The following section describes shell commands for debugging and testing the telephony time zone detection feature.

Test environment setup

Testers typically use a test environment with a test or simulated telephony cell to check telephony time zone detection behavior. The test cell can be used to simulate networks with different MCCs and to send NITZ signals to devices and then monitor their effects.

For the device to detect the time zone, the NITZ signal information must be correct, consistent with the MCC, and match the device's copy of the IANA TZDB (time zone rules). NITZ signals that are inconsistent with the MCC cause the telephony origin to become uncertain.

For example, if the MCC used by the test cell is for the USA, the NITZ signal must contain a UTC time, offset, and daylight savings information that is correct for somewhere in the USA.

Interacting with the com.android.phone service

To verify that the device is receiving correct telephony time zone suggestions, use:

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

This dumps telephony information, which can also be found in Android bug reports. On devices with multiple SIMs, there's information for each SIM radio.

The Time zone Logs show the suggestions that the telephony process has sent to the time_zone_detector and the reasons for sending the suggestions.

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")]}