Android14自动时区更新

Android14自动时区更新
AOSP14 时区更新本文面向刚接触 AOSP Framework 的同学按“先知道数据在哪里再知道怎么更新最后知道系统怎么用起来”的顺序整理。参考当前源码system/timezoneexternal/icuexternal/cldrpackages/modules/GeoTZframeworks/base/services/core/java/com/android/server/timezonedetectorframeworks/base/services/core/java/com/android/server/timezonedetector/location参考文档aaa/自动时区设置.mdaaa/geotz_gnss_sequence.mdaaa/geotz_architecture.md1. AOSP14 中时区数据分两类很多人看到“时区更新”会以为只改一个文件其实 AOSP14 里至少要分清两条线。第一类是普通时区规则数据也就是 IANA tzdata。它决定Asia/Shanghai、Europe/London这类时区 ID 的历史偏移、夏令时规则、国家映射、ICU 时区显示等。这条线主要在system/timezone external/icu external/cldr第二类是“位置到时区”的离线边界数据。GNSS / LocationManager 给系统一个经纬度后GeoTZ 用本地tzs2.dat判断这个经纬度属于哪些时区。这条线主要在packages/modules/GeoTZ简单说IANA tzdata时区规则例如 Asia/Shanghai 当前 UTC8 GeoTZ tzs2.dat经纬度查时区例如 31.2,121.4 - Asia/Shanghai这两者都和时区有关但用途不一样更新方法也不一样。2. AOSP14 世界时间的数据来源2.1 IANA tzdata当前源码中的 IANA 输入文件在system/timezone/input_data/iana/tzdata2023a.tar.gz当前生成后的 Android 运行时文件在system/timezone/output_data/iana/tzdata system/timezone/output_data/android/tzlookup.xml system/timezone/output_data/android/telephonylookup.xml system/timezone/output_data/android/tzids.prototxt system/timezone/output_data/icu_overlay/icu_tzdata.dat system/timezone/output_data/version/tz_version当前工程里的版本文件内容是007.001|2023a|001可以理解为2023aIANA tzdata 版本。001Android 自己的修订号。007.001Android 时区数据集格式版本。2.2 ICU / CLDRICU 负责很多 Java / native 层国际化相关能力时区显示、格式化、部分时区名称也会受它影响。相关目录external/icu external/cldrsystem/timezone/update-tzdata.py会重新生成system/timezone/output_data也会更新 ICU runtime 数据。所以改 IANA tzdata 时不要只盯着system/timezone/output_data/iana/tzdata。2.3 GeoTZ 的 timezone-boundary-builder 数据GeoTZ 的边界数据来自外部 timezone-boundary-builder 项目。当前源码输入文件packages/modules/GeoTZ/tzbb_data/input-data.zip packages/modules/GeoTZ/tzbb_data/timezones.geojson.zip当前源码输出文件packages/modules/GeoTZ/output_data/odbl/tzs2.dattzs2.dat是离线经纬度查时区的核心数据文件。3. AOSP14 时区更新机制3.1 com.android.tzdata APEX 更新AOSP14 的系统时区规则通过com.android.tzdataAPEX 承载。定义位置system/timezone/apex/Android.bpAPEX 中包含这些预置数据apex_tz_version apex_tzlookup.xml apex_telephonylookup.xml apex_tzdata apex_icu_tzdata.dat对应来源在system/timezone/output_data这条更新影响系统里的时区规则、国家到时区映射、Telephony 时区查找、ICU 时区 overlay。3.2 固件 / OTA 更新如果产品没有单独走 Mainline APEX 更新也可以通过整包 OTA 或刷机方式更新系统镜像里的数据。兜底文件还会安装到/system/usr/share/zoneinfo/tzdata源码定义在system/timezone/output_data/iana/Android.bp3.3 GeoTZ APEX 或 APK 更新GeoTZ 也支持不同部署形态packages/modules/GeoTZ/apex/com.android.geotz packages/modules/GeoTZ/appapex是com.android.geotzAPEX 形态里面带tzs2.dat。app是OfflineLocationTimeZoneProviderServiceprivileged APK 形态里面也可以把tzs2.dat作为资源带进去。也就是说IANA 时区规则和 GeoTZ 位置边界可以分开更新。4. AOSP14 中如何更新普通时区规则这一节对应system/timezone。4.1 准备编译环境先进入 AOSP 根目录sourcebuild/envsetup.sh lunchyour_target脚本依赖ANDROID_BUILD_TOP所以不要直接在普通 shell 里运行。4.2 下载新的 IANA 数据官方脚本system/timezone/download-iana-files.py--data如果要更新 zic / tzcode 工具再跑system/timezone/download-iana-files.py--tools普通时区规则更新通常先只做--data。脚本会从 IANA 下载新的tzdata20xx?.tar.gz放入system/timezone/input_data/iana4.3 检查 Android 自己维护的映射这些文件不是 IANA 原始数据而是 Android 自己维护的输入system/timezone/input_data/android/countryzones.txt system/timezone/input_data/android/telephonylookup.txt如果某个国家、MCC、默认时区映射发生变化要检查这些文件。4.4 重新生成输出数据执行system/timezone/update-tzdata.py它会生成或更新system/timezone/output_data/iana/tzdata system/timezone/output_data/android/tzlookup.xml system/timezone/output_data/android/telephonylookup.xml system/timezone/output_data/android/tzids.prototxt system/timezone/output_data/icu_overlay/icu_tzdata.dat system/timezone/output_data/version/tz_version external/icu runtime 数据脚本内部会调用 Soong 编译 host 工具例如zone_compactor tzlookup_generator telephonylookup_generator4.5 编译相关模块可以先单独编译m com.android.tzdata如果要确认整体系统镜像m如果只验证 framework 侧逻辑可以根据修改范围选择m services m framework5. AOSP14 中如何更新 GeoTZ 离线位置时区数据这一节对应packages/modules/GeoTZ。GeoTZ 的目标不是更新Asia/Shanghai的 UTC 偏移规则而是更新“经纬度落在哪个时区边界里”。5.1 下载 timezone-boundary-builder 数据脚本packages/modules/GeoTZ/download-tzbb-files.shrelease-id例子packages/modules/GeoTZ/download-tzbb-files.sh 2023d脚本会刷新packages/modules/GeoTZ/tzbb_data/DATA_LICENSE packages/modules/GeoTZ/tzbb_data/input-data.zip packages/modules/GeoTZ/tzbb_data/timezones.geojson.zip packages/modules/GeoTZ/tzbb_data/METADATA5.2 运行 GeoTZ 数据流水线脚本packages/modules/GeoTZ/run-data-pipeline.sh它大致做这些步骤Step 0解压 timezones.geojson.zip Step 1geojson - TzS2Polygon proto Step 2用 system/timezone/output_data/android/tzids.prototxt 做时区 ID 规范化 Step 3TzS2Polygon - S2 CellUnion Step 4S2 CellUnion - TzS2Range Step 5合并多个 TzS2Range Step 6生成 geotz_createtzs2file 输入 Step 7生成 output_data/odbl/tzs2.dat最终文件packages/modules/GeoTZ/output_data/odbl/tzs2.dat注意run-data-pipeline.sh默认S2_LEVEL12并且 Java 参数使用-Xmx32G说明这个流程比较吃内存不是普通轻量脚本。5.3 GeoTZ 的运行时查找链路运行时核心类packages/modules/GeoTZ/geotz_lookup/src/main/java/com/android/timezone/location/lookup/GeoTimeZonesFinder.java packages/modules/GeoTZ/geotz_lookup/src/main/java/com/android/timezone/location/lookup/S2RangeFileBasedGeoTimeZonesFinder.java调用逻辑是lat/lng - S2CellId - TzS2RangeFileReader.findEntryByCellId() - tzId list也就是经纬度 - S2 网格 - tzs2.dat 范围查询 - 时区 ID 列表6. 自动时区设置和更新数据的关系自动时区开关不是直接写时区数据它只是决定系统使用哪种检测算法。参考aaa/自动时区设置.md应用侧常见入口是timeManager.updateTimeZoneConfiguration(newTimeZoneConfiguration.Builder().setAutoDetectionEnabled(true).setGeoDetectionEnabled(true).build());对应 SettingsSettings.Global.AUTO_TIME_ZONE Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLEDFramework 侧核心类frameworks/base/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java frameworks/base/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java frameworks/base/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java frameworks/base/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.javaConfigurationInternal.getDetectionMode()会决定当前模式DETECTION_MODE_MANUAL DETECTION_MODE_GEO DETECTION_MODE_TELEPHONY DETECTION_MODE_UNKNOWN如果进入DETECTION_MODE_GEO系统会使用 location time zone provider。7. GNSS / 位置自动时区调用链结合aaa/geotz_gnss_sequence.md和aaa/geotz_architecture.md可以把调用链理解成Settings / 系统应用 - TimeManager - TimeZoneDetectorService - TimeZoneDetectorStrategyImpl - LocationTimeZoneManagerService - LocationTimeZoneProviderController - RealLocationTimeZoneProviderProxy - OfflineLocationTimeZoneProviderService - OfflineLocationTimeZoneDelegate - EnvironmentImpl - LocationManager - GeoTimeZonesFinder - tzs2.dat - TimeZoneProviderSuggestion - TimeZoneDetectorStrategyImpl - AlarmManagerInternal.setTimeZone() - persist.sys.timezone源码中的关键点LocationTimeZoneManagerService 使用 TimeZoneProviderService.PRIMARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE RealLocationTimeZoneProviderProxy 绑定实现 TimeZoneProviderService 的远端 provider OfflineLocationTimeZoneProviderService 继承 android.service.timezone.TimeZoneProviderService OfflineLocationTimeZoneDelegate 根据 Location 查询 tzs2.dat 并构造 TimeZoneProviderSuggestion TimeZoneDetectorStrategyImpl 如果 geo suggestion 有结果则选择 zoneId 并设置系统时区当前源码中EnvironmentImpl.setDeviceTimeZoneAndConfidence()最终会调用AlarmManagerInternal.setTimeZone(zoneId,confidence,logInfo);而系统属性读取点是persist.sys.timezone8. 设置中添加或调整时区显示如果只是想在 Settings 页面里显示新的城市 / 时区项通常不是改 GeoTZ。需要先区分目标改时区规则看system/timezone、external/icu。改时区名称 / 本地化显示看external/icu、external/cldr和 Settings 资源。改经纬度到时区边界看packages/modules/GeoTZ。改自动时区开关逻辑看frameworks/base/services/core/java/com/android/server/timezonedetector。Settings 具体资源路径不同产品可能有定制需要在当前源码中搜索rg-ntimezones|timezone|Asia/Shanghaipackages/apps frameworks/base/packages不要把 Settings 展示问题误判成 tzdata 数据问题。9. 常用验证方法9.1 查看当前设备时区adb shell getprop persist.sys.timezone adb shelldate9.2 打开自动时区调试方式adb shell settings put global auto_time_zone1如果要打开位置时区检测还要关注adb shell settings get secure location_time_zone_detection_enabled正式系统应用更推荐走TimeManager.updateTimeZoneConfiguration()因为它会经过权限、capability 和用户配置检查。9.3 查看 tzdata 版本源码侧catsystem/timezone/output_data/version/tz_version设备侧路径会和 APEX 挂载相关可以重点看adb shellls-l/apex/com.android.tzdata/etc/tz adb shellls-l/system/usr/share/zoneinfo9.4 验证 GeoTZ 数据是否进包源码侧ls-lhpackages/modules/GeoTZ/output_data/odbl/tzs2.datAPEX 形态配置中使用geodata.path/apex/com.android.geotz/etc/tzs2.datAPK 形态配置中使用geodata.resourcetzs2.dat对应文件packages/modules/GeoTZ/apex/com.android.geotz/resources/offlineltzprovider.properties packages/modules/GeoTZ/app/resources/offlineltzprovider.properties9.5 跑测试普通时区规则建议至少跑atest CtsLibcoreTestCases atest CtsIcuTestCasesGeoTZ 相关测试可以看packages/modules/GeoTZ/common/src/TEST_MAPPING packages/modules/GeoTZ/geotz_lookup/TEST_MAPPING packages/modules/GeoTZ/locationtzprovider/TEST_MAPPING常见模块atest GeotzCommonTests atest GeotzLookupTests atest OfflineLocationTimeZoneProviderTests10. 常见误区10.1 改了 tzdata不代表 GNSS 自动时区边界会变system/timezone/output_data/iana/tzdata影响时区规则。packages/modules/GeoTZ/output_data/odbl/tzs2.dat影响经纬度查时区。如果问题是“某个边境坐标识别错时区”大概率要看 GeoTZ / timezone-boundary-builder。如果问题是“某个国家夏令时规则变了”大概率要看 IANA tzdata。10.2 直接写 persist.sys.timezone 不是自动时区自动时区的系统入口在TimeZoneDetectorService和TimeZoneDetectorStrategyImpl。直接设置adb shell setprop persist.sys.timezone Asia/Shanghai只适合临时调试不等于验证自动时区链路。10.3 打开 AUTO_TIME_ZONE 不一定使用 GeoTZ系统会根据ConfigurationInternal.getDetectionMode()选择geo 可用且位置开关允许 - DETECTION_MODE_GEO geo 不可用但 telephony 可用 - DETECTION_MODE_TELEPHONY 用户关闭自动时区 - DETECTION_MODE_MANUAL所以只打开auto_time_zone1不代表一定会走 GNSS / GeoTZ。10.4 APEX 和 APK 是部署形态不是两套算法packages/modules/GeoTZ/app是 privileged APK 形态。packages/modules/GeoTZ/apex/com.android.geotz是 APEX 形态。核心算法仍然来自locationtzprovider geotz_lookup s2storage common11. 新手建议的排查顺序如果你接到一个“时区不对”的问题建议按下面顺序判断。第一步确认当前系统时区adb shell getprop persist.sys.timezone adb shelldate第二步确认是手动时区、Telephony 自动时区还是 Geo 自动时区adb shell settings get global auto_time_zone adb shell settings get secure location_time_zone_detection_enabled第三步确认问题类型时区规则错查 system/timezone、external/icu 经纬度识别错查 packages/modules/GeoTZ/output_data/odbl/tzs2.dat Settings 页面显示错查 Settings 资源、ICU / CLDR 自动时区没触发查 timezonedetector 和 location time zone manager第四步看源码调用链TimeZoneDetectorService TimeZoneDetectorStrategyImpl LocationTimeZoneManagerService RealLocationTimeZoneProviderProxy OfflineLocationTimeZoneProviderService GeoTimeZonesFinder第五步再决定改哪条数据线。12. 总结AOSP14 的时区更新可以分成两件事1. 更新时区规则system/timezone external/icu external/cldr 2. 更新离线位置边界packages/modules/GeoTZ普通世界时间、夏令时、国家映射、ICU 显示优先看system/timezone。GNSS / 经纬度自动识别时区优先看packages/modules/GeoTZ。自动时区是否真的生效要看 Framework 的timezonedetector策略不要只看某一个 setting 或某一个数据文件。参考AOSP世界时间的更新https://data.iana.org/time-zones/tz-link.htmlhttps://blog.poormansmath.net/how-much-is-time-wrong-around-the-world/