本页介绍了时间和时区检测在 Android 上的工作原理。这包括 Android 如何自动检测时间和时区、设备制造商的配置选项以及测试信息。
时间和时区概述
为了确定用户在状态栏等位置显示的本地时间,Android 会跟踪两个相关但独立的状态:
- 当前的 Unix 纪元时间
- 当前时区
当前 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 中默认配置了两个主要的时间检测源:
- 电话:使用网络身份和时区 (NITZ) 电话信号。
- 网络:使用网络时间协议 (NTP) 时间服务器。
电话和网络源都需要连接到外部网络,而外部网络并不总是可用的。
从 Android 12 开始,Android 还支持以下来源,默认情况下未配置使用:
时间设置
用户可以在 AOSP 设置应用中的系统 > 日期和时间中启用自动时间检测。
图 1.设置中的自动时间检测。
下表描述了 AOSP 设置应用程序中时间检测的用户控件。
*在 Android 11 及更低版本上,此设置标记为使用网络提供的时间 | |||
AOSP 设置位置 | AOSP 设置名称 | 范围 | 行为 |
---|---|---|---|
系统 > 日期和时间 | 自动设置时间* | 所有用户 | 一个切换。 当on时,设备负责检测当前的 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
意图的已安装应用创建工作。
允许的原点值为:
下限时间
Android 12 引入了一个较低的时间限制,用于验证time_detector
服务收到的时间建议。下限时间值是根据构建时间戳设置的。这样做的原理是有效时间不能在设备的系统映像构建之前。如果时间建议早于下限时间,则time_detector
服务会丢弃该建议,因为如果构建时间戳正确,则该建议无效。
对于运行 Android 11 或更低版本的设备, time_detector
服务不会验证传入的 Unix 纪元时间建议。
Android 不强制执行时间上限。
时间调试和测试
本节提供有关如何调试和测试time_detector
服务以及所有来源共享的其他组件的行为的信息。
与 time_detector 服务交互
要查看time_detector
服务的配置和time_detector
服务的状态,请使用:
adb shell cmd time_detector dump
要查看用于调试和测试时区检测的其他命令,请使用:
adb shell cmd time_detector help
帮助输出还描述了 device_config 服务属性,这些属性可用于影响time_detector
在测试或生产中的行为。有关详细信息,请参阅使用 device_config 服务配置设备。
要验证自动时间检测,测试人员必须知道time_detector
服务正在使用哪个来源。以下是adb shell cmd time_zone_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
服务的确定或不确定状态由origin发送的时区建议确定。
通常,建议有两种与time_zone_detector
的可能状态非常匹配的类型:确定和不确定。以下是建议类型的示例:
类型 = “不确定”,zoneIds = []
- 起源不知道时区是什么。
类型 = “确定”,zoneIds = [“欧洲/伦敦”]
- 起源确定该区域是“欧洲/伦敦”。
类型 = “确定”,zoneIds = []
- 来源是确定的,但没有与当前位置关联的区域 ID。
类型 = “某些”,zoneIds = [“美国/丹佛”,“美国/凤凰城”]
- 来源确定答案是两个区域之一,但无法在“美国/丹佛”和“美国/凤凰”之间进行选择。
time_zone_detector
服务根据其来源将建议序列视为不同的序列。根据来源,建议还可能包含指示来源确定性的元数据。
time_zone_detector
服务是有状态的,这意味着它会记录每个来源提出的最新建议。如果先前的建议不再正确,则将新建议发送到time_zone_detector
服务;也就是说,如果一个原点现在有不同的建议,或者它已经失去了检测时区的能力。 time_zone_detector
服务重新评估新的和现有的建议,并在收到建议时更新设备状态。
Android 支持时区检测的两个来源:
- 电话
- 地点
time_zone_detector
服务仅使用单一来源来确定时区。当设备支持位置原点时,当前使用的原点将根据用户配置的时区设置确定。当当前原点变得不确定时区时, time_zone_detector
不会切换到不同的原点。除了当前原点之外,与原点相关的建议可以由time_zone_detector
保存在内存中,但除非当前原点发生变化,否则它们不会被使用。当用户更改自动时区检测的设置并且当前原点更改时,将使用可用于新原点的最新建议。
时区设置
用户可以在 AOSP 设置应用中启用和配置自动时区检测设置。
图 2.设置中的自动时区检测。
下表描述了 AOSP 设置应用程序中时区检测的用户控件。
*在 Android 11 及更低版本上,此设置标记为使用网络提供的时区 | |||
AOSP 设置位置 | AOSP 设置名称 | 范围 | 行为 |
---|---|---|---|
系统 > 日期和时间 | 自动设置时区* | 所有用户 | 一个切换。 打开时,设备负责检测当前时区。关闭时,用户可以手动设置设备的时区。 |
系统 > 日期和时间 | 使用位置设置时区 | 当前用户 | 一个切换。 适用于 Android 12。仅当设备支持位置时区检测时才会显示此切换。 |
地点 | 使用位置 | 当前用户 | 一个切换。 通常允许或阻止使用设备的位置。如果设备支持位置时区检测,则该值是相关的。 |
以下概述了给定用户选择的设置时区检测的设备行为:
[日期和时间] 自动设置时区: OFF
- 用户必须手动选择时区。
[日期和时间] 自动设置时区:开
[位置] 使用位置: OFF
- 电话信号用于检测时区。 (见下面的注释。)
[位置] 使用位置: ON
[日期和时间] 使用位置设置时区:开
- 位置用于检测时区。
[日期和时间] 使用位置设置时区: OFF
- 电话信号用于检测时区。 (见下面的注释。)
多用户设备
由于所涉及的一些设置仅限于当前用户,因此当当前用户在多用户 Android 设备上发生更改时,设备的时区检测行为可能会发生变化。
使用位置设置时区切换的范围仅限于当前用户,不受设备政策的限制,这意味着用户始终可以更改其值,即使设置时区自动切换关闭或其他时间或时区控制受设备策略控制器限制。
切换到自动检测和从自动检测切换时的行为
当用户将时区检测从手动切换到自动时, 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
服务以及所有来源共享的其他组件的行为的信息。
使用 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
帮助输出还描述了device_config
服务属性,这些属性可用于影响time_zone_detector
服务在测试或生产中的行为。有关详细信息,请参阅使用 device_config 服务配置设备。
要验证时区检测,测试人员必须知道time_zone_detector
使用的是哪个来源。要了解和影响time_zone_detector
的当前来源,请使用以下选项之一:
- 通过设置 UI 进行目视检查。有关详细信息,请参阅时区设置。
通过 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”表示位置原点。 |
建议历史信息指示已通过设置(手动)以及电话和位置来源提出了哪些建议。