Time zone rules

Android 10 deprecates the APK-based time zone data update mechanism (available in Android 8.1 and Android 9) and replaces it with an APEX-based module update mechanism. AOSP 8.1 to 13 still include the platform code necessary for OEMs to enable APK-based updates, so devices upgrading to Android 10 can still receive partner-provided time zone data updates through APK. However, the APK update mechanism shouldn't be used on a production device that is also receiving module updates as an APK-based update supersedes an APEX-based update (that is, a device that received an APK update would ignore APEX-based updates).

Time zone updates (Android 10 and higher)

The Time Zone Data module supported in Android 10 and higher updates daylight saving time (DST) and time zones on Android devices, standardizing data that can change frequently for religious, political, and geopolitical reasons.

Updates use the following process:

  1. IANA releases an update to the Time Zone Database releases an update in response to one or more governments changing a time zone rule in their countries.
  2. Google or the Android partner prepares a Time Zone Data module update (APEX file) containing the updated time zones.
  3. The end-user device downloads the update, reboots, then applies the changes, after which the device's time zone data contains the new time zone data from the update.

For details on modules, see Modular System Components.

Time zone updates (Android 8.1–9)

Note: The APK-based time zone data update mechanism feature has been completely removed from Android 14 onwards and cannot be found in the source code. Partners should fully migrate to the Time Zone Mainline module.

In Android 8.1 and Android 9, OEMs can use an APK-based mechanism to push updated time zone rules data to devices without requiring a system update. This mechanism enables users to receive timely updates (thus extending the useful lifetime of an Android device) and enables Android partners to test time zone updates independently of system image updates.

The Android core libraries team provides the necessary data files for updating time zone rules on a stock Android device. OEMs can choose to use these data files when creating time zone updates for their devices or can create their own data files if preferred. In all cases, OEMs retain control over the quality assurance/testing, timing, and launch of time zone rule updates for their supported devices.

Android time zone source code and data

All stock Android devices, even those not using this feature, need time zone rules data and must ship with a default set of time zone rules data in the /system partition. This data is then used by code from the following libraries in the Android source tree:

  • Managed code from libcore/ (for example, java.util.TimeZone) uses tzdata and tzlookup.xml files.
  • Native library code in bionic/ (for example, for mktime, localtime system calls) uses the tzdata file.
  • ICU4J/ICU4C library code in external/icu/ uses the icu .dat file.

These libraries keep track of overlay files that may be present in the /data/misc/zoneinfo/current directory. Overlay files are expected to contain improved time zone rules data, thereby enabling devices to be updated without changing /system.

Android system components that need time zone rule data check the following locations first:

  • libcore/ and bionic/ code use the /data copy of the tzdata and tzlookup.xml files.
  • ICU4J/ICU4C code use the files in /data and fall back to /system files for data that isn't present (for formats, localized strings, etc.).

Distro files

Distro .zip files contain the data files needed to populate the /data/misc/zoneinfo/current directory. The distro files also contain metadata that allows devices to detect versioning issues.

The distro file format is Android-release dependent because the contents change with the ICU version, Android platform requirements, and other release changes. Android provides distro files for supported Android releases for every IANA update (in addition to updating the platform system files). To keep their devices up to date, OEMs can use these distro files or create their own using the Android source tree (which contains the scripts and other files needed to generate distro files).

Time zone update components

A time zone rules update involves the transmission of distro files to a device and the safe installation of the files contained within. Transfer and installation requires the following:

  • Platform service functionality (timezone.RulesManagerService), which is disabled by default. OEMs must enable the functionality through configuration. RulesManagerService runs in the system server process and stages time zone update operations by writing to /data/misc/zoneinfo/staged. RulesManagerService can also replace or delete already staged operations.
  • TimeZoneUpdater, a nonupdateable system app (aka the Updater app). OEMs must include this app in the system image of devices using the feature.
  • OEM TimeZoneData, an updateable system app (aka the Data app) that carries distro files to the device and makes them available to the Updater app. OEMs must include this app in the system image of devices using the feature.
  • tzdatacheck, a boot-time binary required for the correct and safe operation of time zone updates.

The Android source tree contains generic source code for the above components, which the OEM can choose to use without modification. Test code is provided to enable OEMs to automatically check that they've enabled the feature correctly.

Distro installation

The distro installation process includes the following steps:

  1. Data app is updated through an app store download or sideload. The system server process (through timezone.RulesManagerServer/timezone.PackageTracker classes) watches for changes to the configured, OEM-specific, Data app package name.

    Data app updates

    Figure 1. Data app updates.

  2. The system server process triggers an update check by broadcasting a targeted intent with a unique, single-use token to the Updater App. The system server keeps track of the most recent token it generated so it can determine when the most recent check it triggered has completed; any other tokens are ignored.

    Trigger update

    Figure 2. Trigger update check.

  3. During the update check, the Updater app performs the following tasks:
    • Queries the current device state by calling the RulesManagerService.

      Call RulesManagerService

      Figure 3. Data app updates, calling RulesManagerService.

    • Queries the Data app by querying a well-defined ContentProvider URL and column specs to get information about the distro.

      Get distro information

      Figure 4. Data app updates, get info about distro.

  4. The Updater app takes the appropriate action based on the information it has. Available actions include:
    • Request an installation. Distro data is read from the Data app and is passed to the RulesManagerService in the system server. The RulesManagerService reconfirms that the distro format version and content is appropriate for the device and stages the install.
    • Request an uninstall (this is rare). For example, if the updated APK in /data is being disabled or uninstalled and the device is returning to the version present in /system.
    • Do nothing. Occurs when the Data app distro is found to be invalid.
    In all cases, the Updater app calls the RulesManagerService with the check token so the system server knows that the check is complete and successful.

    Check complete

    Figure 5. Check complete.

  5. Reboot and tzdatacheck. When the device next boots, the tzdatacheck binary executes any staged operation. The tzdatacheck binary can perform the following tasks:
    • Execute the staged operation by handling the creation, replacement, and/or deletion of the /data/misc/zoneinfo/current files before other system components have opened and started to use the files.
    • Check that the files in /data are correct for the current platform version, which might not be the case if the device has just received a system update and the distro format version has changed.
    • Ensure that the IANA rules version is the same or newer than the version in /system. This protects against a system update leaving a device with older time zone rules data than is present in the /system image.

Reliability

The end-to-end installation process is asynchronous and split across three OS processes. At any point during the installation, the device may lose power, run out of disk space, or encounter other issues, causing the installation check to be incomplete. In the best unsuccessful case, the Updater app informs the system server that it was unsuccessful; in the worst unsuccessful case, the RulesManagerService receives no call at all.

To handle this, the system server code keeps track of whether a triggered update check has completed and what the last checked version code of the Data App is. When the device is idle and charging, the system server code can check the current state. If it discovers an incomplete update check or unexpected Data App version, it spontaneously triggers an update check.

Security

When enabled, the RulesManagerService code in the system server performs several checks to ensure that the system is safe to use.

  • Problems that indicate a badly configured system image prevent a device booting; examples include a bad Updater or Data app configuration or the Updater or Data app not being in /system/priv-app.
  • Problems that indicate a bad Data app has been installed don't prevent a device booting but do prevent an update check being triggered; examples include a lack of required system permissions or the Data app doesn't expose a ContentProvider on the expected URI.

File permissions for the /data/misc/zoneinfo directories are enforced using SELinux rules. As with any APK, the Data app must be signed by the same key used to sign the /system/priv-app version. The Data app is expected to have a dedicated, OEM-specific package name and key.

Integrate time zone updates

To enable the time zone update feature, OEMs typically:

  • Create their own Data app.
  • Include the Updater and Data apps in the system image build.
  • Configure the system server to enable the RulesManagerService.

Preparation

Before starting, OEMs should review the following policy, quality assurance, and security considerations:

  • Create a dedicated app-specific signing key for their Data app.
  • Create a release and versioning strategy for time zone updates to understand which devices are going to be updated and how they can ensure that updates are only installed on devices that need them. For example, OEMs may want to have a single Data app for all their devices or may choose to have different Data apps for different devices. The decision impacts the choice of package name, possibly the version codes used, and the QA strategy.
  • Understand whether they want to use stock Android timezone data from AOSP or create their own.

Create a Data app

AOSP includes all source code and build rules needed to create a Data app in packages/apps/TimeZoneData, with instructions and example templates for AndroidManifest.xml and other files located in packages/apps/TimeZoneData/oem_template. Example templates include both a build target for the real Data app APK and extra targets for creating test versions of the Data app.

OEMs can customize the Data app with their own icon, name, translations, and other details. However, as the Data app can't be launched, the icon appears only in the Settings > Apps screen.

The Data app is intended to be built with a tapas build that produces APKs suitable to be added to the system image (for the initial release) and signed and distributed through an app store (for subsequent updates). For details on using tapas, see Building the Data app using tapas.

OEMs must install the Data app prebuilt in the system image of a device in /system/priv-app. To include prebuilt APKs (generated by the tapas build process) in the system image, OEMs can copy the example files in packages/apps/TimeZoneData/oem_template/data_app_prebuilt. The example templates also include build targets for including test versions of the Data app in test suites.

Include the Updater and Data apps in the system image

OEMs must place the Updater and Data app APKs in the /system/priv-app directory of the system image. To do this, the system image build must explicitly include the Updater app and Data app prebuilt targets.

The Updater app should be signed with the platform key and included as any other system app. The target is defined in packages/apps/TimeZoneUpdater as TimeZoneUpdater. The Data app inclusion is OEM-specific and depends on the target name chosen for the prebuild.

Configure the system server

To enable time zone updates, OEMs can configure the system server by overriding configuration properties defined in frameworks/base/core/res/res/values/config.xml.

Property Description Override Required?
config_enableUpdateableTimeZoneRules
Must be set to true to enable the RulesManagerService. Yes
config_timeZoneRulesUpdateTrackingEnabled
Must be set to true to have the system listen for changes to the Data app. Yes
config_timeZoneRulesDataPackage
Package name of the OEM-specific Data app. Yes
config_timeZoneRulesUpdaterPackage
Configured for the default Updater app. Change only when providing a different Updater app implementation. No
config_timeZoneRulesCheckTimeMillisAllowed
Time allowed between an update check being triggered by the RulesManagerService and an install, uninstall, or do nothing response. After this point, a spontaneous reliability trigger may be generated. No
config_timeZoneRulesCheckRetryCount
The number of sequential unsuccessful update checks allowed before the RulesManagerService stops generating more. No

Configuration overrides should be in the system image (not vendor or other) as a misconfigured device can refuse to boot. If the configuration overrides were in the vendor image, updating to a system image without a Data app (or with different Data app/Updater app package names) would be considered a misconfiguration.

xTS testing

xTS refers to any OEM-specific test suite that is similar to standard Android test suites using Tradefed (such as CTS and VTS). OEMs that have such test suites can add the Android time zone update tests provided in the following locations:

  • packages/apps/TimeZoneData/testing/xts includes the code needed for basic automated functional testing.
  • packages/apps/TimeZoneData/oem_template/xts contains a sample directory structure for including tests in a Tradefed-like xTS suite. As with other template directories, OEMs are expected to copy and customize to their needs.
  • packages/apps/TimeZoneData/oem_template/data_app_prebuilt contains build-time configuration for including the pre-built test APKs required by the test.

Create time zone updates

When IANA releases a new set of time zone rules, the Android core libraries team generates patches to update releases in AOSP. OEMs using the stock Android system and distro files can pick up these commits, use them to create a new version of their Data app, then release the new version to update their devices in production.

Because Data apps contain distro files closely tied to Android versions, OEMs must create a new version of the Data app for every supported Android release that an OEM wants to update. For example, if an OEM wants to provide updates for Android 8.1, 9, and 10 devices, they must complete the process three times.

Step 1: Update system/timezone and external/icu data files

In this step, OEMs take stock Android commits for system/timezone and external/icu from the release-dev branches in AOSP and apply those commits to their copy of the Android source code.

The system/timezone AOSP patch contains updated files in system/timezone/input_data and system/timezone/output_data. OEMs who need to make additional local fixes can modify the input files then use the files in system/timezone/input_data and external/icu to generate files in output_data.

The most important file is system/timezone/output_data/distro/distro.zip, which is automatically included when the Data app APK is built.

Step 2: Update the version code of the Data app

In this step, OEMs update the version code of the Data app. The build automatically picks up distro.zip, but the new version of the Data app must have a new version code so it's recognized as new and is used to replace a preloaded Data app or a Data app installed on a device by a previous update.

When building the Data app using files copied from package/apps/TimeZoneData/oem_template/data_app, you can find the version code/version name applied to the APK in the Android.mk:

TIME_ZONE_DATA_APP_VERSION_CODE :=
TIME_ZONE_DATA_APP_VERSION_NAME :=

Similar entries can be found in testing/Android.mk (however, the test version codes must be higher than the system image version). For details, see the example version code strategy scheme; if the example scheme or a similar scheme is used, the test version codes don't need to be updated because they're guaranteed to be higher than the real version codes.

Step 3: Rebuild, sign, test, and release

In this step, OEMs rebuild the APK using tapas, sign the generated APK, then test and release the APK:

  • For unreleased devices (or when preparing a system update for a released device), submit the new APKs in the Data app prebuilt directory to ensure that the system image and xTS tests have the latest APKs. OEMs should test that the new file works correctly (that is, it passes CTS and any OEM-specific automated and manual tests).
  • For released devices that no longer receive system updates, the signed APK might only be released through an app store.

OEMs are responsible for quality assurance and testing the updated Data app on their devices before release.

Data app version code strategy

The Data app must have a suitable versioning strategy to ensure that devices receive the correct APKs. For example, if a system update is received that contains an older APK than one downloaded from the app store, the app store version should be retained.

The APK version code should include the following information:

  • Distro format version (major + minor)
  • An incrementing (opaque) version number

Currently, platform API level is strongly correlated to distro format version because each API level is usually associated with a new version of ICU (which makes the distro files incompatible). In the future, Android may change this so that a distro file can work across multiple Android platform releases (and API level isn't used in the Data app version code scheme).

Example version code strategy

This example versioning number scheme ensures that higher distro format versions supersede lower distro format versions. AndroidManifest.xml uses android:minSdkVersion to ensure that old devices don't receive versions with a higher distro format version than they can handle.

Version check

Figure 6. Example version code strategy.

Example Value Purpose
Y Reserved Allows for future alternative schemes/test APKs. It's initially (implicitly) 0. Because the underlying type is a signed 32-bit int type, this scheme supports up to two future numbering scheme revisions.
01 Major format version Tracks the 3 decimal digit major format version. The distro format supports 3 decimal digits but only 2 digits are used here. It's unlikely to reach 100 given the expected major increment per API level. Major version 1 is equivalent to API level 27.
1 Minor format version Tracks the 3 decimal digit minor format version. The distro format supports 3 decimal digits but only 1 digit is used here. It's unlikely to reach 10.
X Reserved Is 0 for production releases (and may be different for test APKs).
ZZZZZ Opaque version number Decimal number allocated on demand. Includes gaps to allow interstitial updates to be made if required.

The scheme could be packed better if binary were used instead of decimal, but this scheme has the advantage of being human-readable. If the full number range is exhausted, the Data app package name could change.

The version name is a human-readable representation of the details, for example: major=001,minor=001,iana=2017a, revision=1,respin=2. Examples are shown in the following table.

# Version code minSdkVersion {Major format version},{Minor format version},{IANA rules version},{Revision}
1 11000010 O-MR1 major=001,minor=001,iana=2017a,revision=1
2 21000010 P major=002,minor=001,iana=2017a,revision=1
3 11000020 O-MR1 major=001,minor=001,iana=2017a,revision=2
4 11000030 O-MR1 major=001,minor=001,iana=2017b,revision=1
5 21000020 P major=002,minor=001,iana=2017b,revision=1
6 11000040 O-MR1 major=001,minor=001,iana=2018a,revision=1
7 21000030 P major=002,minor=001,iana=2018a,revision=1
8 1123456789 - -
9 11000021 O-MR1 major=001,minor=001,iana=2017a,revision=2,respin=2
  • Examples 1 and 2 show two APK versions for the same 2017a IANA release with different major format versions. 2 is numerically higher than 1, which is needed to ensure that newer devices receive the higher format versions. The minSdkVersion ensures that the P version won't be supplied to O devices.
  • Example 3 is a revision/fix for 1 and is numerically higher than 1.
  • Examples 4 and 5 show the 2017b releases for O-MR1 and P. Being numerically higher, they replace prior IANA releases/Android revisions of their respective predecessors.
  • Examples 6 and 7 show the 2018a releases for O-MR1 and P.
  • Example 8 demonstrates the use of Y to completely replace the Y=0 scheme.
  • Example 9 demonstrates the use of the gap left between 3 and 4 to re-spin the apk.

As each device ships with a default, appropriately versioned APK in the system image, there's no risk of an O-MR1 version being installed on a P device because it has a lower version number than a P system image version. A device with an O-MR1 version installed in /data that then receives a system update to P uses the /system version in preference to the O-MR1 version in /data because the P version is always higher than any app intended for O-MR1.

Build the Data app using tapas

OEMs are responsible for managing most aspects of the time zone Data app and configuring the system image correctly. The Data app is intended to be built with a tapas build that produces APKs suitable to be added to the system image (for the initial release) and signed and distributed through an app store (for subsequent updates).

Tapas is a slimmed-down version of the Android build system that uses a reduced source tree to produce distributable versions of apps. OEMs familiar with the normal Android build system should recognize the build files from the normal Android platform build.

Create the manifest

A reduced source tree is usually achieved with a custom manifest file that refers only to the Git projects needed by the build system and for building the app. After following the instructions in Creating a Data app, OEMs should have at least two OEM-specific Git projects created by using the template files under packages/apps/TimeZoneData/oem_template:

  • One Git project contains app files such as the manifest and the build files required to create the app APK file (for example, vendor/oem/apps/TimeZoneData). This project also contains build rules for test APKs that can be used by xTS tests.
  • One Git project contains the signed APKs produced by the app build for inclusion in the system image build and xTS tests.

The app build leverages several other Git projects that are shared with the platform build or contain OEM-independent code libraries.

The following manifest snippet contains the minimal set of Git projects needed to support an O-MR1 build of the time zone Data app. OEMs must add their OEM-specific Git projects (which typically include a project that contains the signing certificate) to this manifest, and may configure different branches accordingly.

   <!-- Tapas Build -->
    <project
        path="build"
        name="platform/build">
        <copyfile src="core/root.mk" dest="Makefile" />
    </project>
    <project
        path="prebuilts/build-tools"
        name="platform/prebuilts/build-tools"
        clone-depth="1" />
    <project
        path="prebuilts/go/linux-x86"
        name="platform/prebuilts/go/linux-x86"
        clone-depth="1" />
    <project
        path="build/blueprint"
        name="platform/build/blueprint" />
    <project
        path="build/kati"
        name="platform/build/kati" />
    <project
        path="build/soong"
        name="platform/build/soong">
        <linkfile src="root.bp" dest="Android.bp" />
        <linkfile src="bootstrap.bash" dest="bootstrap.bash" />
    </project>

    <!-- SDK for system / public API stubs -->
    <project
        path="prebuilts/sdk"
        name="platform/prebuilts/sdk"
        clone-depth="1" />
    <!-- App source -->
    <project
        path="system/timezone"
        name="platform/system/timezone" />
    <project
        path="packages/apps/TimeZoneData"
        name="platform/packages/apps/TimeZoneData" />
    <!-- Enable repohooks -->
    <project
        path="tools/repohooks"
        name="platform/tools/repohooks"
        revision="main"
        clone_depth="1" />
    <repo-hooks
        in-project="platform/tools/repohooks"
        enabled-list="pre-upload" />

Run the tapas build

After the source tree is established, invoke the tapas build using the following commands:

source build/envsetup.sh
tapas
make -j30 showcommands dist TARGET_BUILD_APPS='TimeZoneData TimeZoneData_test1 TimeZoneData_test2'  TARGET_BUILD_VARIANT=userdebug

A successful build generates files in the out/dist directory for testing. These files can be placed into the prebuilts directory for inclusion in the system image and/or distributed through an app store for compatible devices.