Time Zone Rules

Android 8.1 provides a new mechanism for OEMs 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 OEMs to test time zone updates independently of system image updates.

The Android core libraries team will provide 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/ (e.g. java.util.TimeZone) uses tzdata and tzlookup.xml files.
  • Native library code in bionic/ (e.g. for mktime, localtime system calls) uses the tzdata file.
  • ICU4J/ICU4C library code in external/icu/ uses the icu .dat file.

These libraries are configured to be aware 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 fallback 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 file also contains 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, etc. 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 choose to take this distro file or create their own distro file 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 a distro file 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 via configuration. The RulesManagerService runs in the system server process and stages time zone update operations by writing to /data/misc/zoneinfo/staged. It can also replace or delete already staged operations.
  • Time Zone Updater, a non-updateable system application (aka the Updater App). OEMs must include this application in the system image of devices using the feature.
  • OEM Time Zone Data, an updateable system application (aka the Data App) that carries the distro file to the device and makes it available to the Updater App. OEMs must include this application 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 have enabled the feature correctly.

Distro installation

The distro installation process includes the following steps:

  1. Data App is updated via an app store download or sideload. The system server process (via 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. 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 later tell when the most recent check it triggered has completed; any other tokens are ignored.
    Trigger update
    Figure 2. Trigger update check.
  3. Update check, in which 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. 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 re-confirms 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 Updated App calls the RulesManagerService with the check token so the system server knows 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 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 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, etc., causing the installation check to not complete successfully. In the best unsuccessful case, the Updater App is able to inform the system server 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 the system is safe to use.

  • Problems that indicate a badly configured system image will 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 will not prevent a device booting but will 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 via 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.

Integrating 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.

Preparing

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

  • OEMs should create a dedicated app-specific signing key for their Data App.
  • OEMs should create a release and versioning strategy for time zone updates to understand which devices are going to be updated and how they will ensure 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.
  • OEMs should understand whether they want to use stock Android timezone data from AOSP or create their own.

Creating 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 file and extra targets for creating test versions of the Data App.

OEMs can customize the Data App with their own icon, name, translations, etc. However, as the Data App cannot 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 via 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.

Including the Updater and Data Apps in the system image

OEMs must place the Updater and Data App .apk files 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.

Configuring 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 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 /vendor, 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 .apk files required by the test.

Creating 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 an OEM wants to update. For example, if an OEM wants to provide updates for O-MR1, P, and Q devices, they must complete the process three times.

Step 1: Updating 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: Updating the version code of the Data App

In this step, OEMs update the version code of the Data App. The build automatically picks up the distro.zip, but the new version of the Data App must have a new version code so it is recognized as new and is used to replace a pre-loaded 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 do not need to be updated because they are guaranteed to be higher than the real version codes.

Step 3: Rebuild, sign, test, and release

In this step, OEMs rebuild the .apk files using tapas, sign the generated .apk files, then test and release the .apks:

  • For unreleased devices (or when preparing a system update for a released device), submit the new .apk files in the Data App prebuilt directory to ensure the system image and xTS tests have the latest .apks. OEMs should test the new file works correctly (i.e. 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 via an app store.

OEMs are entirely 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 .apk files. 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 is not used in the Data App version code scheme).

Example version code strategy

This example versioning number scheme ensures that higher distro format versions beat lower distro format versions. The AndroidManifest.xml uses android:minSdkVersion to ensure 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 and/or test APKs. It will initially be (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 is unlikely 100 will be reached given the expected major increment per API level. Major version 1 == 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 is unlikely 10 will be reached.
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, future releases could change the Data App package name and start again.

Version name will be a human-readable representation of the details, e.g.: major=001,minor=001,iana=2017a, revision=1,respin=2. Examples:

# 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 the P version will not be supplied to O devices.
  • Example 3 is an example 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 will ship with a default, appropriately versioned .apk in the system image, there is no risk of an O-MR1 version being installed on a P device because it will have 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 will use the /system version in preference to the O-MR1 version in /data because the P version will always be higher than any app intended for O-MR1.

Building 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 via 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 will recognize the build files from the normal Android platform build.

Creating 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 application files such as the manifest and the build files required to create the application .apk file (e.g. 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 .apk files 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 (future versions of Android will have different lists or may even change the build system). 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="master"
        clone_depth="1" />
    <repo-hooks
        in-project="platform/tools/repohooks"
        enabled-list="pre-upload" />

Running 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 via an app store for compatible devices.