DCD域内时钟同步策略
背景
车机在正式环境(车上)采用 TBOX 作为唯一时间来源,来保证 DCD 域内所有时间统一。
大部分开发人员不需要也没有 TBOX, 但是部分应用以及网络请求需要相对正确的世界时间。
QNX 内 TimeSyncService 接受外域(TBOX) 的时间,并和 Android / MCU 等模块做时间同步功能。
当前策略
使用(Android) NTP 开关来做正式环境和开发环境的行为控制。
图来源(2.3 问题:时间同步,上电前20秒,QNX和安卓的时间对不上)
📷 [图片: DCD域内时钟同步策略架构图 — 左侧 MCU (Time Task、Unix to UTC、Ext RTC);中间 QNX (Vehicle Core、TimeSyncService、SystemClock);右侧 Android (QacService、TimeSynchronizer);底部 Eth Driver (EMAC) 与 Eth PHY 88Q2220。TimeSyncService 同时与 MCU、Android 双向同步]
-
ENABLE NTP
Android 在开发环境中,会从 NTP 获取正确时间,并反向同步给 QNX TimeSyncService, QNX TimeSyncService 负责同步其他域(MCU)内的时间 。
-
DISABLE NTP
正式环境(车上)中, QNX TimeSyncService 只接受外域的时间,并将该时间同步给其他模块。
Android 只接受
1577836800000L(2020/01/01 08:00:00) 之后的时间。
不同版本时间同步差异
主线
- 使用
AndroidSystemProperty:: ro.build.micar_enable_ntp作为 NTP 开关(开=true, 关=false) (提交) - 更改 Android NTP 开关
时序图
NTP ENABLE
📷 [图片: Q/A 时间同步时序图 (NTP ENABLE 主线) — QNX_TimeSyncService 周期发送时间给 Android_TimeSynchronizer;后者检查 QNX 来源时间有效性(1577836800000L 之前为无效)及时间差变化(同 elapsedRealtimeDiff 内视为相同);时间差与上次相同时 DO NOTHING,不同时检查 3s 内是否收到过不同请求,有效且 3s 内有过则在第 3s 再确认 NTP,否则请求 NTP;请求成功后若与 QNX 时间不同则反向同步给 QNX_TimeSyncService]
PlantUml Code
@startuml
title Q/A时间同步时序图
participant QNX_TimeSyncService
participant Android_TimeSynchronizer
participant NTPServer
note over QNX_TimeSyncService: 周期发送时间
QNX_TimeSyncService->Android_TimeSynchronizer: 发送时间
note over Android_TimeSynchronizer: 检查QNX来源时间有效性以及时间差变化
Android_TimeSynchronizer->Android_TimeSynchronizer: 检查QNX来源时间有效性以及时间差变化
alt 时间差与上次发送的相同
note over Android_TimeSynchronizer: DO NOTHING
else 时间差与上次发送的不同
note over Android_TimeSynchronizer: 检查QNX来源时间有效性以及时间差变化
Android_TimeSynchronizer->Android_TimeSynchronizer: 检查 3s 内是否收到过不同的请求
alt 时间有效且 3s 内收到过不同的请求
note over Android_TimeSynchronizer: 3s 内已经收到过不同的请求,在第3S时刻再确认 NTP
else 时间无效或 3s 内未收到过不同的请求(新请求)
note over Android_TimeSynchronizer: 请求 NTP 时间()
end
end
== Request NTP Phase ==
note over Android_TimeSynchronizer: 请求 NTP 时间()
Android_TimeSynchronizer->NTPServer: 请求 NTP 时间
note over NTPServer: 处理请求
alt 请求失败
note over Android_TimeSynchronizer: DO NOTHING
else 请求成功
NTPServer->Android_TimeSynchronizer: 返回 NTP 时间
note over Android_TimeSynchronizer: 反向同步 NTP 时间
alt NTP 时间与 QNX_TimeSyncService 时间不同
Android_TimeSynchronizer->QNX_TimeSyncService: 发送 NTP 时间
else NTP 时间与 QNX_TimeSyncService 时间相同
note over Android_TimeSynchronizer: DO NOTHING
end
end
@enduml时间有效性规则:认为
1577836800000L(2020/01/01 08:00:00) 之前的时间无效。时间差检查:例如上次收到 20:00、这次收到 20:01,则检查
Math.abs(1min - elapsedRealtimeDiff) < 50MS,若 20:01 在 1min 时刻收到则相同,反之亦然。
NTP DISABLE
参考 E4 时序图(注:原文档此处自引用,实际指向当前文档自身,可能为原文笔误)
相关提交
- Android 过滤外部时间策略更改(30S 滤波改为 3S, 并优先详细第一个来源) ([提交](http://gerrit.auto.mioffice.cn/c/cockpit/core/platform/android/services/CarController/ /30020) | 2023/04/03)
- NTP 开关更改 (
ro.build.micar_debug_build⇒ro.build.micar_enable_ntp) (提交 | 2023/02/22)
E4
- 使用
AndroidSystemProperty:: ro.build.micar_enable_ntp作为 NTP 开关(开=true, 关=false)
时序图
📷 [图片: Q/A 时间同步时序图 (E4 版本) — 与主线类似;当时间无效或时间差与上次相同时 DO NOTHING;时间有效且时间差不同时检查 3s 内是否收到过不同请求,3s 内有过则第 3s 再确认 NTP,新请求则立即请求 NTP;成功后若与 QNX 时间不同则反向同步给 QNX_TimeSyncService]
PlantUml Code
@startuml
title Q/A时间同步时序图
participant QNX_TimeSyncService
participant Android_TimeSynchronizer
participant NTPServer
note over QNX_TimeSyncService: 周期发送时间
QNX_TimeSyncService->Android_TimeSynchronizer: 发送时间
note over Android_TimeSynchronizer: 检查QNX来源时间有效性以及时间差变化
Android_TimeSynchronizer->Android_TimeSynchronizer: 检查QNX来源时间有效性以及时间差变化
alt 时间无效或时间差与上次发送的相同
note over Android_TimeSynchronizer: DO NOTHING
else 时间有效且时间差与上次发送的不同
note over Android_TimeSynchronizer: 检查QNX来源时间有效性以及时间差变化
Android_TimeSynchronizer->Android_TimeSynchronizer: 检查 3s 内是否收到过不同的请求
alt 3s 内收到过不同的请求
note over Android_TimeSynchronizer: 3s 内已经收到过不同的请求,在第3S时刻再确认 NTP
else 3s 内未收到过不同的请求(新请求)
note over Android_TimeSynchronizer: 请求 NTP 时间()
end
end
== Request NTP Phase ==
note over Android_TimeSynchronizer: 请求 NTP 时间()
Android_TimeSynchronizer->NTPServer: 请求 NTP 时间
note over NTPServer: 处理请求
alt 请求失败
note over Android_TimeSynchronizer: DO NOTHING
else 请求成功
NTPServer->Android_TimeSynchronizer: 返回 NTP 时间
note over Android_TimeSynchronizer: 反向同步 NTP 时间
alt NTP 时间与 QNX_TimeSyncService 时间不同
Android_TimeSynchronizer->QNX_TimeSyncService: 发送 NTP 时间
else NTP 时间与 QNX_TimeSyncService 时间相同
note over Android_TimeSynchronizer: DO NOTHING
end
end
@endumlE3
- 使用
AndroidSystemProperty:: ro.build.micar_debug_build作为 NTP 开关(开=true, 关=false)
TODO
当前 TimeSynchronizer 是在 CarController(com.mi.car.controller) 进程内, 是一个 Java 进程,开机后会有一段时间内, Q/A 的时间不同步, 可以更改至 VHAL 内实现部分功能。