本页面介绍了 Android 上时间和时区检测的工作原理。其中包括 Android 如何自动检测时间和时区、设备制造商的配置选项以及测试信息。
时间和时区概览
为了确定用户在状态栏等位置显示的本地时间,Android 会跟踪两个相关但独立的状态
- 当前的 Unix 纪元时间
- 当前时区
当前的 Unix 纪元时间和当前时区是设备范围的状态,这意味着设备的所有用户共享这些状态。
当前的 Unix 纪元时间不是固定值。它会自动更新以反映时间的推移。除了正常的时间推移之外,如果发现设备的当前 Unix 纪元时间不正确(例如,设备断电后),则会对其进行调整。
当前时区决定了将当前 Unix 纪元时间转换为本地时间时要进行的调整。例如,在洛杉矶的夏季,设备从当前 Unix 纪元时间中减去 7 小时,而在冬季则减去 8 小时。
为了支持这些本地时间计算,所有 Android 设备都有一个所有全球时区规则的数据库。如需详细了解时区规则,请参阅时区规则。
当用户前往使用不同时区的新位置时,无需调整当前的 Unix 纪元时间,但用户通常希望看到本地时间,而不是他们之前位置的时间。更改当前时区可确保将正确的偏移量应用于当前的 Unix 纪元时间,以显示新位置的正确本地时间。
AOSP 允许用户通过以下机制独立控制时间和时区是否自动设置。
- 自动时间检测:确保设备具有正确的当前 Unix 纪元时间。
- 自动时区检测:确保设备具有正确的当前时区。
自动时间检测
本部分概述了管理自动时间检测、用户控件、配置选项和测试详情的 time_detector
服务。
time_detector 服务
在运行 Android 10 或更高版本的设备上提供的 time_detector
服务管理自动时间检测。启用自动时间检测后,它会根据需要调整设备的当前 Unix 纪元时间。
time_detector
服务始终处于两种状态之一:不确定或确定。服务的确定或不确定状态由它从各种来源接收的时间建议决定。
当 time_detector
服务处于确定状态(意味着它已收到包含 Unix 纪元时间信息的建议)时,如果时间建议与当前的 Unix 纪元时间不同,它会替换当前的 Unix 纪元时间。
当 time_detector
处于不确定状态时,它不会替换当前时间。不确定状态通常意味着 time_detector
服务尚未收到时间建议。time_detector
服务在收到的建议被认为过旧而无法使用时也会变为不确定状态。之所以考虑建议的时效性,是因为使用旧的 Unix 纪元时间建议进行调整依赖于设备上的经过时间实时时钟,而该时钟在长时间内被认为是不可靠的。
为了自动建立当前的 Unix 纪元时间,设备可以使用各种来源。在本文档中,这些来源称为来源。time_detector
服务根据建议的来源将建议序列视为不同的序列。
time_detector
服务是有状态的,这意味着它会记录每个来源提出的最新建议。如果某个来源有更新的 Unix 纪元时间信息可用,则会向 time_detector
提出新建议。time_detector
服务会重新评估新的和现有的建议,并在收到建议时更新设备状态。
尽管国际上对 UTC 时间已达成一致,但 Android 设备建立当前 Unix 纪元时间并非始终简单明了,原因如下
- Unix 纪元时间与 UTC 时间是略有不同的计时系统。两者之间的转换需要了解闰秒何时发生以及来源如何处理闰秒。
- 来源可能仅在特定时间或特定情况下可用。例如,如果来源需要网络连接,则可能仅在设备连接到互联网时才可用。
- 来源可能不准确或不精确,或者存在错误。例如,如果某个电信蜂窝基站未正确跟踪“世界协调时间”,则电信来源可能会提供不准确的时间建议。
- 在获取 Unix 纪元时间时可能会引入不准确性。例如,网络延迟、缓冲或进程调度可能会导致 Unix 纪元时间不准确。
- 用于调整自收到建议后经过的时间的参考时钟可能不准确。
AOSP 中默认配置了两个主要的时间检测来源
- 网络:使用网络时间协议 (NTP) 时间服务器。
- 电信网络:使用网络身份和时区 (NITZ) 电信信号。
电信网络和网络来源都需要连接到外部网络,但外部网络并非始终可用。
从 Android 12 开始,Android 还支持以下来源,这些来源默认情况下未配置为使用
时间设置
用户可以在 AOSP“设置”应用中的系统 > 日期和时间中启用自动时间检测。
图 1. “设置”中的自动时间检测。
下表介绍了 AOSP“设置”应用中用于时间检测的用户控件。
*在 Android 11 及更低版本中,此设置标记为使用网络提供的时间 |
|||
AOSP “设置”位置 | AOSP “设置”名称 | 范围 | 行为 |
---|---|---|---|
系统 > 日期和时间 | 自动设置时间* | 所有用户 | 切换开关。 当设置为开启时,设备负责检测当前的 Unix 纪元时间。当设置为关闭时,用户可以使用控件手动设置设备的时间。 |
当用户手动输入时间时,他们输入的是本地时间,而不是 Unix 纪元时间。当前的 Unix 纪元时间是通过使用当前时区推导 Unix 纪元时间来计算的。
配置
设备制造商可以通过多种方式配置 time_detector
服务,例如要使用哪些来源以及如何确定来自这些来源的信号的优先级。
来源优先级
从 Android 12 开始,设备制造商可以更改 core/res/res/values/config.xml
配置文件,以指定要在自动时间检测中包含哪些时间来源,以及 time_detector
考虑这些来源的优先级。
对于运行 Android 11 或更低版本的设备,来源优先级硬编码为 ["telephony", "network"]
,这意味着电信网络建议的优先级高于网络建议。
默认的 AOSP 配置如下所示
<!-- Specifies priority of automatic time sources. Suggestions from higher entries in the list
take precedence over lower ones.
See com.android.server.timedetector.TimeDetectorStrategy for available sources. -->
<string-array name="config_autoTimeSourcesPriority">
<item>network</item>
<item>telephony</item>
</string-array>
在 Android 12 中,网络和电信网络建议配置为默认使用的来源。网络时间建议的优先级高于电信网络时间建议。设备制造商可以更改来源的顺序,以恢复到 Android 11 或更低版本中的行为,在这些版本中,电信网络具有更高的优先级。
默认情况下,如果优先级最高的有效建议与设备当前的系统时钟时间在几秒钟内匹配,则不会更改设备时间。这是为了避免为侦听 ACTION_TIME_CHANGED
intent 的已安装应用创建工作。
允许的来源值包括
允许的时间范围
Android 14 为 time_detector
服务接收的时间建议引入了上限。如果设备支持 32 位进程,则框架会设置时间上限,以防止设备使用可能触发 Y2038 问题的建议。
Android 12 引入了下限,用于验证 time_detector
服务接收的时间建议。用于自动建议的下限值是从构建时间戳设置的。这基于以下原则:有效时间不能早于设备系统映像的构建时间。如果时间建议早于下限,则 time_detector
服务会舍弃该建议,因为如果构建时间戳正确,则该建议无效。
对于运行 Android 11 或更低版本的设备,time_detector
服务不会验证传入的 Unix 纪元时间建议。
时间调试和测试
本部分提供有关如何调试和测试 time_detector
服务以及所有来源共享的其他组件的行为的信息。
与 time_detector 服务交互
要查看 time_detector
服务的配置和 time_detector
服务的状态,请使用
adb shell cmd time_detector dump
要查看用于调试和测试时区检测的其他命令,请使用
adb shell cmd time_detector help
帮助输出还介绍了可用于影响 time_detector
行为以进行测试或在生产环境中使用的 device_config 服务属性。如需了解详情,请参阅使用 device_config 服务配置设备。
要验证自动时间检测,测试人员必须了解 time_detector
服务正在使用哪些来源。以下是 adb shell cmd time_detector dump
命令的输出示例,其中以粗体显示了有关当前来源和服务状态的信息
$ adb shell cmd time_detector dump
TimeDetectorStrategy:
mLastAutoSystemClockTimeSet=null
mEnvironment.isAutoTimeDetectionEnabled()=true
mEnvironment.elapsedRealtimeMillis()=23717241
mEnvironment.systemClockMillis()=1626707861336
mEnvironment.systemClockUpdateThresholdMillis()=2000
mEnvironment.autoTimeLowerBound()=2021-07-19T07:48:05Z(1626680885000)
mEnvironment.autoOriginPriorities()=[network,telephony]
Time change log:
...
Telephony suggestion history:
...
Network suggestion history:
...
Gnss suggestion history:
...
External suggestion history:
...
信息可以解释如下
键 | 值 |
---|---|
mEnvironment.isAutoTimeDetectionEnabled() |
是否启用了自动时间检测。 |
mEnvironment.autoTimeLowerBound() |
用于验证时间建议的当前下限。 |
mEnvironment.autoOriginPriorities() |
正在使用的来源和优先级顺序。 |
时间更改日志指示 time_detector
服务何时更改了设备的当前 Unix 纪元时间。
建议历史记录信息指示每个来源提出了哪些建议。
自动时区检测
本部分概述了管理自动时区检测、设置中的用户控件、电信网络和位置时区检测以及测试详情的 time_zone_detector
服务。
time_zone_detector 服务
在运行 Android 11 或更高版本的设备上提供的 time_zone_detector
服务管理自动时区检测。启用自动时区检测后,它会根据需要调整设备的当前时区。
启用自动时区检测后,time_zone_detector
可以处于两种状态之一:不确定和确定。
当 time_zone_detector
服务处于确定状态时,这意味着 time_zone_detector
服务已收到可靠的时区信息,这可能会导致它替换当前时区。当它处于不确定状态时,这意味着它未收到任何信息或仅收到低置信度信息,这意味着它不会替换当前时区。
time_zone_detector
服务的确定状态可以包括 time_zone_detector
没有可用的时区信息的状态,或者它可以选择多个时区的状态。这些状态如下所示
- 当设备位于没有时区的位置(例如在国际水域或争议地区)时,会进入零时区的确定状态。此状态与不确定状态类似,但表示
time_zone_detector
无需采取进一步措施来尝试确定时区。 - 当存在歧义或边界条件时,会进入多个时区的确定状态。在此状态下,如果当前时区是
time_zone_detector
确定的时区之一,则当前时区保持不变。否则,将使用其中一个可用时区。如果用户之前手动选择了他们的时区,或者当设备接近边界时,这会为time_zone_detector
提供一定的粘性。
time_zone_detector
服务的确定或不确定状态由算法发送的时区建议决定。
通常,建议有两种类型,这两种类型与 time_zone_detector
的可能状态非常匹配:确定和不确定。以下是建议类型的示例
类型 =
uncertain
,zoneIds = []
- 算法不知道时区是什么。
类型 =
certain
,zoneIds = ["Europe/London"]
- 算法确定时区为 Europe/London。
类型 =
certain
,zoneIds = []
`- 算法是确定的,但没有与当前位置关联的时区 ID。
类型 =
certain
,zoneIds = ["America/Denver", "America/Phoenix"]
- 算法确定答案是两个时区之一,但无法在“America/Denver”和“America/Phoenix”之间做出选择。
time_zone_detector
服务根据其算法将建议序列视为不同的序列。根据算法的不同,建议也可能包含指示算法确定程度的元数据。
time_zone_detector
服务是有状态的,这意味着它会记录每个算法提出的最新建议。如果先前的建议不再正确,则会向 time_zone_detector
服务发送新建议;也就是说,如果某个算法现在有不同的建议,或者它已失去检测时区的功能。time_zone_detector
服务会重新评估新的和现有的建议,并在收到建议时更新设备状态。
Android 支持两种时区检测算法
- 电信网络
- 位置
time_zone_detector
服务通常使用单个算法来确定时区。当设备支持位置算法时,设备使用的算法取决于用户配置的时区设置。当使用的算法变得不确定时区时,time_zone_detector
通常不使用来自不同算法的建议。与未使用的算法关联的建议可以由 time_zone_detector
保存在内存中,但除非算法更改,否则不会使用这些建议。当用户更改自动时区检测的设置并且算法更改时,将使用新算法可用的最新建议。
如需详细了解使用多种算法确定时区的情况,请参阅电信网络回退模式。
电信网络回退模式
在运行 Android 13 及更高版本的设备上,time_zone_detector
服务支持电信网络回退模式。此模式允许 Android 在位置检测无法检测到时区或位置检测检测时区的时间比电信网络检测长的情况下,临时使用电信网络检测建议。
电信网络回退模式适用于同时支持电信网络和位置检测,并且用户在时区设置中启用了使用位置设置时区的设备。当设备重新启动以及禁用飞行模式时,此模式会自动启用。
在 Android 14 及更高版本中,可以通过 LTZP 状态报告 API 触发电信网络回退,也就是说,如果 LTZP 报告其状态为不确定并且其检测位置或时区的功能因其环境而降低,则会触发电信网络回退模式。
当处于电信网络回退模式时,time_zone_detector
服务会使用电信网络建议,就好像位置检测已禁用一样,直到位置算法提出确定性建议。收到确定性建议后,电信网络回退模式将被禁用,并且将专门使用位置建议。
有关电信网络回退模式的配置详情,请参阅时区检测配置。
时区设置
用户可以在 AOSP “设置”应用中启用和配置自动时区检测的设置。
图 2. “设置”中的自动时区检测。
下表介绍了 AOSP “设置”应用中用于时区检测的用户控件。
*在 Android 11 及更低版本中,此设置标记为使用网络提供的时区 |
|||
AOSP “设置”位置 | AOSP “设置”名称 | 范围 | 行为 |
---|---|---|---|
系统 > 日期和时间 | 自动设置时区* | 所有用户 | 切换开关。 当设置为开启时,设备负责检测当前时区。当设置为关闭时,用户可以使用控件手动设置设备的时区。 |
系统 > 日期和时间 | 使用位置信息设置时区 | 当前用户 | 切换开关。 从 Android 12 开始提供。仅当设备支持位置时区检测时,才会显示此切换开关。 有关 Android 14 中引入的变更,请参阅仅支持位置时区检测的设备。 |
位置 | 使用位置信息 | 当前用户 | 切换开关。 允许或禁止大致使用设备的位置。如果设备支持位置时区检测,则此值相关。 |
以下概述了在给定用户选择的设置的情况下,设备在时区检测方面的行为
[日期和时间] 自动设置时区:关闭
- 用户必须手动选择时区。
[日期和时间] 自动设置时区:开启
[位置信息] 使用位置信息:关闭
- 使用电信网络信号检测时区。
[位置信息] 使用位置信息:开启
[日期和时间] 使用位置信息设置时区:开启
- 使用位置信息检测时区。
[日期和时间] 使用位置信息设置时区:关闭
- 使用电信网络信号检测时区。
多用户设备
由于所涉及的多个设置的作用域限定为当前用户,因此当多用户 Android 设备上的当前用户更改时,设备的时区检测行为可能会发生变化。
使用位置信息设置时区切换开关的作用域限定为当前用户,并且不受设备政策的限制,这意味着即使在自动设置时区切换开关关闭时,或者在其他时间和时区控件受到设备政策控制器限制时,用户始终可以更改其值。
仅支持位置时区检测算法的设备
本部分介绍了仅支持位置算法的设备的行为。
Android 14 及更高版本
- 使用位置信息选项不会向 AOSP “设置”应用中的用户显示,并且设备的行为就像使用位置信息选项已启用一样。
- 用户作用域的
SettingsProvider
设置location_time_zone_detection_enabled
的值将被忽略。此值记录用户对其他类型设备的偏好设置。
Android 12 或 Android 13
- 使用位置信息选项在 AOSP “设置”应用中对用户可见,并且用户可以停用该选项。如果该选项被停用,设备将不会自动检测时区。
切换到自动检测和从自动检测切换时的行为
当用户将时区检测从手动切换到自动时,time_zone_detector
可能已经确定了当前时区。如果是这样,当用户启用自动检测时,设备的时区可能会同时更改以匹配 time_zone_detector
服务的意见。
同样,当用户在“设置”中进行更改导致 time_zone_detector
服务的当前算法发生更改时,time_zone_detector
可能已经收到了新算法的建议,因此设备的时间可能会立即更改以匹配 time_zone_detector
服务的意见。
电话时区检测
电信网络时区检测使用电信网络信号来确定当前时区。如需了解详情,请参阅电信网络时区检测。
位置时区检测
位置时区检测在 Android 12 或更高版本中可用。它是一项可选的自动时区检测功能,使设备能够使用其位置来确定当前时区。
Android 12 中引入的 location_time_zone_manager
服务在系统服务器中运行,并且包含负责向 time_zone_detector
服务提交位置算法建议的代码。如需了解详情,请参阅位置时区检测。
功能采用注意事项
本部分介绍了位置时区检测功能的各个方面,以帮助设备制造商确定是否在设备上采用该功能。
比较电信网络和位置检测
下表比较了使用位置信息而不是电信网络信号进行时区检测的优缺点。
电信网络检测 | 位置检测 | |
---|---|---|
准确性 | 因国家/地区而异。 取决于 MCC、NITZ 的正确性和可用性。 |
取决于功能配置或插件组件。 准确性通常因以下因素而异
|
可更新性 | 电信网络检测依赖于可更新的时区数据模块 (com.android.tzdata APEX) 中包含的文件。 | 取决于功能配置或插件组件。 可更新性通常取决于设备是使用服务器时区地图数据还是客户端时区地图数据。 注意:时区地图数据不包含在用于更新 Android 的 TZDB 副本和其他时区信息的时区数据模块中。 设备制造商还必须考虑时区规则和时区地图数据之间的版本一致性。 |
耗电量 | 无耗电量或低耗电量 | 取决于用户位置设置、正在使用的插件以及通常其他应用请求的位置信息。 |
可用性 | 仅限电信网络设备。通常需要可用的 SIM 卡。 | 位置检测取决于可用的位置信息提供程序。 |
用户隐私
用户的首选时区通常由其地理位置决定。位置是敏感数据。用户可能会担心他们的位置信息在时区检测中被共享。与时区检测无关,设备上运行的所有应用都可以在无需 Android 权限的情况下读取设备的当前时区,并且应用可以从此信息中推断出设备位置的大概概念。
更具体地说,时区检测可以通过被动或主动方式工作
- 被动:设备环境中的某些内容告诉设备在该环境中使用的时区。
- 主动:设备必须自行计算时区,并根据用户的隐私设置及其同意,获取设备的位置以执行此操作。然后,它可以与外部服务共享其位置。有关用户隐私和同意的详细信息,请参阅下文的讨论。
被动检测(例如使用电信网络算法)对用户没有额外的隐私影响。
主动检测(例如使用位置算法)涉及确定设备的位置,用户可能不同意这样做,并且位置可能会通过网络发送以确定时区 ID。
Android 的时区检测用户隐私方法使用户能够单独停用预计处于活动状态的算法。此外,AOSP 平台代码不直接处理位置本身:位置检测和将位置映射到时区 ID 的工作留给设备制造商配置的插件组件。
如需详细了解用户隐私功能,请参阅位置时区检测。
配置
设备制造商可以配置 time_zone_detector
服务以更改其行为。本部分介绍了 time_zone_detector
服务的一般行为的配置选项。有关电信网络和时区检测算法的配置详情,请参阅电信网络时区检测和位置时区检测。
基本 AOSP 配置位于frameworks/base/core/res/res/values/config.xml
。
配置键 | AOSP 值 | 说明 |
---|---|---|
config_supportTelephonyTimeZoneFallback |
true |
当 true 时,time_zone_detector 使用电信网络回退模式。这适用于 Android 13 及更高版本。 |
更改设备默认行为
在 AOSP 中,默认情况下启用自动时区检测,并且 auto_time_zone
设置设置为 true
。要默认停用自动时间检测,请将 frameworks/base/packages/SettingsProvider/res/values/defaults.xml
中定义的 def_auto_time_zone
的值设置为 false
。
从另一台设备恢复备份时,框架默认会更新 auto_time_zone
设置的值。如果您想确保不从备份恢复此设置,请在 frameworks/base/packages/SettingsProvider/res/values/blocked_settings.xml
中定义的 restore_blocked_global_settings
数组中包含 auto_time_zone
。
时区调试和测试
本部分提供有关如何调试和测试 time_zone_detector
服务以及所有算法共享的其他组件的行为的信息。
使用 device_config 服务配置设备
device_config
服务是 Android 上使用的一种机制,用于使用通常由专有(非 AOSP)代码从远程服务器提取的值来配置可修改的行为。当使用 device_config
值进行测试时,尤其是在长时间运行的手动测试期间,设备可能会同步标志,这将重置标志并清除为测试设置的值。
在 Android 12 或更高版本中,要暂时阻止标志同步,请使用
adb shell cmd device_config set_sync_disabled_for_tests persistent
要在测试后恢复标志同步,请使用
adb shell cmd device_config set_sync_disabled_for_tests none
恢复标志同步后,重新启动设备。
如需了解更多信息,请使用 $ adb shell cmd device_config help
。
与 time_zone_detector 服务交互
要查看 time_zone_detector
配置和 time_zone_detector
服务的状态,请使用
adb shell cmd time_zone_detector dump
要查看用于调试和测试时区检测的其他命令,请使用
adb shell cmd time_zone_detector help
帮助输出还描述了可用于影响 time_zone_detector
服务行为以进行测试或在生产环境中使用的 device_config
服务属性。有关详情,请参阅使用 device_config 服务配置设备。
要验证时区检测,测试人员必须知道 time_zone_detector
正在使用哪种算法。要了解和影响 time_zone_detector
的当前算法,请使用以下选项之一
- 通过“设置”界面进行直观检查。如需了解详情,请参阅时区设置。
通过 adb 使用命令行
- 要转储
time_zone_detector
状态,请使用adb shell cmd time_zone_detector dump
- 要更改设备设置,请使用其他
time_zone_detector
命令。如需了解详情,请使用adb shell cmd time_zone_detector help
。
- 要转储
以下是 adb shell cmd time_zone_detector dump
命令输出示例,其中以粗体显示了有关当前算法和服务状态的信息
$ adb shell cmd time_zone_detector dump
TimeZoneDetectorStrategy:
mEnvironment.getCurrentUserId()=0
mEnvironment.getConfiguration(currentUserId)=ConfigurationInternal{mUserId=0, mUserConfigAllowed=true, mTelephonyDetectionSupported=true, mGeoDetectionSupported=true, mAutoDetectionEnabled=true, mLocationEnabled=true, mGeoDetectionEnabled=true}
[Capabilities=TimeZoneCapabilitiesAndConfig{mCapabilities=TimeZoneDetectorCapabilities{mUserHandle=UserHandle{0}, mConfigureAutoDetectionEnabledCapability=40, mConfigureGeoDetectionEnabledCapability=40, mSuggestManualTimeZoneCapability=30}, mConfiguration=TimeZoneConfiguration{mBundle=Bundle[{geoDetectionEnabled=true, autoDetectionEnabled=true}]}}]
mEnvironment.isDeviceTimeZoneInitialized()=true
mEnvironment.getDeviceTimeZone()=Europe/London
Time zone change log:
Manual suggestion history:
...
Geolocation suggestion history:
...
Telephony suggestion history:
...
信息可以解释如下
键 | 值 |
---|---|
mUserConfigAllowed |
用户是否被 设备策略控制器 阻止控制日期和时间设置。 |
mTelephonyDetectionSupported |
设备是否支持电话时区检测。 |
mGeoDetectionSupported |
设备是否支持位置时区检测。这是基于配置和至少存在一个 LTZP 的有效状态。 |
mAutoDetectionEnabled |
是否启用自动时区检测。 |
mLocationEnabled |
主位置开关。 |
mGeoDetectionEnabled |
算法开关:false 表示电话算法,true 表示位置算法。 |
建议历史记录信息指示通过“设置”(手动)以及电话和位置算法提出的建议。