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:
- 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.
- Google or the Android partner prepares a Time Zone Data module update (APEX file) containing the updated time zones.
- 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
) usestzdata
andtzlookup.xml
files. - Native library code in
bionic/
(for example, formktime
, localtime system calls) uses thetzdata
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/
andbionic/
code use the/data
copy of thetzdata
andtzlookup.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:
- 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.
Figure 1. Data app updates.
- 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.
Figure 2. Trigger update check.
- During the update check, the Updater app performs the
following tasks:
- Queries the current device state by calling the 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.
Figure 4. Data app updates, get info about distro.
- Queries the current device state by calling the RulesManagerService.
- 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.
Figure 5. Check complete.
- 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.
- Execute the staged operation by handling the creation, replacement,
and/or deletion of the
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.
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.