1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "ntp_update_time.h"
16
17 #include "init_param.h"
18 #include "ntp_trusted_time.h"
19 #include "parameters.h"
20 #include "time_system_ability.h"
21
22 using namespace std::chrono;
23
24 namespace OHOS {
25 namespace MiscServices {
26 namespace {
27 constexpr int64_t NANO_TO_MILLISECOND = 1000000;
28 constexpr int64_t HALF_DAY_TO_MILLISECOND = 43200000;
29 constexpr const char* NTP_SERVER_SYSTEM_PARAMETER = "persist.time.ntpserver";
30 constexpr const char* NTP_SERVER_SPECIFIC_SYSTEM_PARAMETER = "persist.time.ntpserver_specific";
31 constexpr uint32_t NTP_MAX_SIZE = 5;
32 constexpr const char* AUTO_TIME_SYSTEM_PARAMETER = "persist.time.auto_time";
33 constexpr const char* AUTO_TIME_STATUS_ON = "ON";
34 constexpr const char* AUTO_TIME_STATUS_OFF = "OFF";
35 constexpr uint64_t ONE_HOUR = 3600000;
36 constexpr const char* DEFAULT_NTP_SERVER = "1.cn.pool.ntp.org";
37 constexpr int32_t RETRY_TIMES = 2;
38 } // namespace
39
40 AutoTimeInfo NtpUpdateTime::autoTimeInfo_{};
41 std::mutex NtpUpdateTime::requestMutex_;
42
NtpUpdateTime()43 NtpUpdateTime::NtpUpdateTime() : timerId_(0), nitzUpdateTimeMilli_(0), nextTriggerTime_(0), lastNITZUpdateTime_(0){};
44
GetInstance()45 NtpUpdateTime& NtpUpdateTime::GetInstance()
46 {
47 static NtpUpdateTime instance;
48 return instance;
49 }
50
Init()51 void NtpUpdateTime::Init()
52 {
53 TIME_HILOGD(TIME_MODULE_SERVICE, "Ntp Update Time start");
54 std::string ntpServer = system::GetParameter(NTP_SERVER_SYSTEM_PARAMETER, DEFAULT_NTP_SERVER);
55 std::string ntpServerSpec = system::GetParameter(NTP_SERVER_SPECIFIC_SYSTEM_PARAMETER, "");
56 std::string autoTime = system::GetParameter(AUTO_TIME_SYSTEM_PARAMETER, "ON");
57 if ((ntpServer.empty() && ntpServerSpec.empty()) || autoTime.empty()) {
58 TIME_HILOGW(TIME_MODULE_SERVICE, "No found parameter from system parameter");
59 return;
60 }
61 RegisterSystemParameterListener();
62 autoTimeInfo_.ntpServer = ntpServer;
63 autoTimeInfo_.ntpServerSpec = ntpServerSpec;
64 autoTimeInfo_.status = autoTime;
65 auto callback = [this](uint64_t id) -> int32_t {
66 this->RefreshNetworkTimeByTimer(id);
67 return E_TIME_OK;
68 };
69 TimerPara timerPara{};
70 timerPara.timerType = static_cast<int>(ITimerManager::TimerType::ELAPSED_REALTIME);
71 timerPara.windowLength = 0;
72 timerPara.interval = HALF_DAY_TO_MILLISECOND;
73 timerPara.flag = 0;
74 TimeSystemAbility::GetInstance()->CreateTimer(timerPara, callback, timerId_);
75 RefreshNextTriggerTime();
76 TimeSystemAbility::GetInstance()->StartTimer(timerId_, nextTriggerTime_);
77 TIME_HILOGI(TIME_MODULE_SERVICE, "ntp update timerId: %{public}" PRIu64 "triggertime: %{public}" PRId64 "",
78 timerId_, nextTriggerTime_);
79 }
80
RefreshNetworkTimeByTimer(uint64_t timerId)81 void NtpUpdateTime::RefreshNetworkTimeByTimer(uint64_t timerId)
82 {
83 TIME_HILOGI(TIME_MODULE_SERVICE, "The timer is up");
84 if (!CheckStatus()) {
85 TIME_HILOGI(TIME_MODULE_SERVICE, "Auto Sync Switch Off");
86 return;
87 }
88
89 auto setSystemTime = [this]() { this->SetSystemTime(); };
90 std::thread thread(setSystemTime);
91 thread.detach();
92 TIME_HILOGD(TIME_MODULE_SERVICE, "Ntp next triggertime: %{public}" PRId64 "", nextTriggerTime_);
93 }
94
UpdateNITZSetTime()95 void NtpUpdateTime::UpdateNITZSetTime()
96 {
97 auto bootTimeNano = steady_clock::now().time_since_epoch().count();
98 auto bootTimeMilli = bootTimeNano / NANO_TO_MILLISECOND;
99 if (TimeUtils::GetBootTimeMs(lastNITZUpdateTime_) != ERR_OK) {
100 TIME_HILOGE(TIME_MODULE_SERVICE, "get boot time fail");
101 }
102 TIME_HILOGD(TIME_MODULE_SERVICE, "nitz time changed");
103 nitzUpdateTimeMilli_ = static_cast<uint64_t>(bootTimeMilli);
104 }
105
SplitNtpAddrs(const std::string & ntpStr)106 std::vector<std::string> NtpUpdateTime::SplitNtpAddrs(const std::string &ntpStr)
107 {
108 std::vector<std::string> ntpList;
109 size_t start = 0;
110 do {
111 if (ntpList.size() == NTP_MAX_SIZE) {
112 break;
113 }
114 size_t end = ntpStr.find(',', start);
115 if (end < start) {
116 break;
117 }
118 std::string temp = ntpStr.substr(start, end - start);
119 if (temp.empty()) {
120 ++start;
121 continue;
122 }
123 if (end == std::string::npos) {
124 ntpList.emplace_back(temp);
125 break;
126 }
127 ntpList.emplace_back(temp);
128 start = end + 1;
129 } while (start < ntpStr.size());
130 return ntpList;
131 }
132
IsInUpdateInterval()133 bool NtpUpdateTime::IsInUpdateInterval()
134 {
135 // Determine the time interval between two NTP requests sent.
136 int64_t curBootTime = std::chrono::duration_cast<std::chrono::milliseconds>(
137 NtpTrustedTime::GetInstance().GetBootTimeNs().time_since_epoch()).count();
138 uint64_t bootTime = static_cast<uint64_t>(curBootTime);
139 auto lastBootTime = NtpTrustedTime::GetInstance().ElapsedRealtimeMillis();
140 // If the time <= ONE_HOUR, do not send NTP requests.
141 if ((lastBootTime > 0) && (bootTime - static_cast<uint64_t>(lastBootTime) <= ONE_HOUR)) {
142 TIME_HILOGI(TIME_MODULE_SERVICE,
143 "ntp updated bootTime: %{public}" PRId64 ", lastBootTime: %{public}" PRId64 "",
144 bootTime, lastBootTime);
145 return true;
146 }
147 return false;
148 }
149
GetNtpTimeInner()150 bool NtpUpdateTime::GetNtpTimeInner()
151 {
152 if (IsInUpdateInterval()) {
153 return true;
154 }
155
156 std::vector<std::string> ntpSpecList = SplitNtpAddrs(autoTimeInfo_.ntpServerSpec);
157 std::vector<std::string> ntpList = SplitNtpAddrs(autoTimeInfo_.ntpServer);
158 ntpSpecList.insert(ntpSpecList.end(), ntpList.begin(), ntpList.end());
159 for (int i = 0; i < RETRY_TIMES; i++) {
160 for (size_t j = 0; j < ntpSpecList.size(); j++) {
161 TIME_HILOGI(TIME_MODULE_SERVICE, "ntpServer is : %{public}s", ntpSpecList[j].c_str());
162 if (NtpTrustedTime::GetInstance().ForceRefresh(ntpSpecList[j])) {
163 return true;
164 }
165 }
166 }
167 return false;
168 }
169
GetRealTimeInner(int64_t & time)170 bool NtpUpdateTime::GetRealTimeInner(int64_t &time)
171 {
172 time = NtpTrustedTime::GetInstance().CurrentTimeMillis();
173 if (time <= 0) {
174 TIME_HILOGE(TIME_MODULE_SERVICE, "current time is invalid: %{public}" PRId64 "", time);
175 return false;
176 }
177 return true;
178 }
179
GetRealTime(int64_t & time)180 bool NtpUpdateTime::GetRealTime(int64_t &time)
181 {
182 std::lock_guard<std::mutex> autoLock(requestMutex_);
183 return GetRealTimeInner(time);
184 }
185
GetNtpTime(int64_t & time)186 bool NtpUpdateTime::GetNtpTime(int64_t &time)
187 {
188 std::lock_guard<std::mutex> autoLock(requestMutex_);
189
190 if (!GetNtpTimeInner()) {
191 TIME_HILOGE(TIME_MODULE_SERVICE, "get ntp time failed");
192 return false;
193 }
194
195 if (!GetRealTimeInner(time)) {
196 return false;
197 }
198
199 if (autoTimeInfo_.status == AUTO_TIME_STATUS_ON) {
200 TimeSystemAbility::GetInstance()->SetTimeInner(time);
201 }
202 return true;
203 }
204
SetSystemTime()205 void NtpUpdateTime::SetSystemTime()
206 {
207 if (autoTimeInfo_.status != AUTO_TIME_STATUS_ON) {
208 TIME_HILOGI(TIME_MODULE_SERVICE, "auto sync switch off");
209 return;
210 }
211
212 if (!requestMutex_.try_lock()) {
213 TIME_HILOGW(TIME_MODULE_SERVICE, "The NTP request is in progress");
214 return;
215 }
216
217 if (!GetNtpTimeInner()) {
218 TIME_HILOGE(TIME_MODULE_SERVICE, "get ntp time failed");
219 requestMutex_.unlock();
220 return;
221 }
222
223 int64_t currentTime = NtpTrustedTime::GetInstance().CurrentTimeMillis();
224 if (currentTime <= 0) {
225 TIME_HILOGE(TIME_MODULE_SERVICE, "current time is invalid: %{public}" PRIu64 "", currentTime);
226 requestMutex_.unlock();
227 return;
228 }
229 int64_t curBootTime = 0;
230 if (TimeUtils::GetBootTimeMs(curBootTime) != ERR_OK) {
231 TIME_HILOGE(TIME_MODULE_SERVICE, "get boot time fail");
232 requestMutex_.unlock();
233 return;
234 }
235
236 TimeSystemAbility::GetInstance()->SetTimeInner(currentTime);
237 requestMutex_.unlock();
238 }
239
RefreshNextTriggerTime()240 void NtpUpdateTime::RefreshNextTriggerTime()
241 {
242 auto bootTimeNano = steady_clock::now().time_since_epoch().count();
243 auto bootTimeMilli = bootTimeNano / NANO_TO_MILLISECOND;
244 nextTriggerTime_ = static_cast<uint64_t>(bootTimeMilli + HALF_DAY_TO_MILLISECOND);
245 }
246
CheckStatus()247 bool NtpUpdateTime::CheckStatus()
248 {
249 return autoTimeInfo_.status == AUTO_TIME_STATUS_ON;
250 }
251
IsValidNITZTime()252 bool NtpUpdateTime::IsValidNITZTime()
253 {
254 if (nitzUpdateTimeMilli_ == 0) {
255 return false;
256 }
257 int64_t bootTimeNano = static_cast<int64_t>(steady_clock::now().time_since_epoch().count());
258 int64_t bootTimeMilli = bootTimeNano / NANO_TO_MILLISECOND;
259 TIME_HILOGI(TIME_MODULE_SERVICE, "nitz update time: %{public}" PRIu64 " currentTime: %{public}" PRId64 "",
260 nitzUpdateTimeMilli_, bootTimeMilli);
261 return (bootTimeMilli - static_cast<int64_t>(nitzUpdateTimeMilli_)) < HALF_DAY_TO_MILLISECOND;
262 }
263
StartTimer()264 void NtpUpdateTime::StartTimer()
265 {
266 TimeSystemAbility::GetInstance()->StartTimer(timerId_, nextTriggerTime_);
267 }
268
Stop()269 void NtpUpdateTime::Stop()
270 {
271 TIME_HILOGD(TIME_MODULE_SERVICE, "start");
272 TimeSystemAbility::GetInstance()->DestroyTimer(timerId_);
273 }
274
RegisterSystemParameterListener()275 void NtpUpdateTime::RegisterSystemParameterListener()
276 {
277 TIME_HILOGD(TIME_MODULE_SERVICE, "register system parameter modify lister");
278 auto specificNtpResult = SystemWatchParameter(NTP_SERVER_SPECIFIC_SYSTEM_PARAMETER,
279 ChangeNtpServerCallback, nullptr);
280 if (specificNtpResult != E_TIME_OK) {
281 TIME_HILOGE(TIME_MODULE_SERVICE, "register specific ntp server lister fail: %{public}d", specificNtpResult);
282 }
283
284 auto netResult = SystemWatchParameter(NTP_SERVER_SYSTEM_PARAMETER, ChangeNtpServerCallback, nullptr);
285 if (netResult != E_TIME_OK) {
286 TIME_HILOGE(TIME_MODULE_SERVICE, "register ntp server lister fail: %{public}d", netResult);
287 }
288
289 auto switchResult = SystemWatchParameter(AUTO_TIME_SYSTEM_PARAMETER, ChangeAutoTimeCallback, nullptr);
290 if (switchResult != E_TIME_OK) {
291 TIME_HILOGE(TIME_MODULE_SERVICE, "register auto sync switch lister fail: %{public}d", switchResult);
292 }
293 }
294
ChangeNtpServerCallback(const char * key,const char * value,void * context)295 void NtpUpdateTime::ChangeNtpServerCallback(const char *key, const char *value, void *context)
296 {
297 TIME_HILOGI(TIME_MODULE_SERVICE, "Ntp server changed");
298 std::string ntpServer = system::GetParameter(NTP_SERVER_SYSTEM_PARAMETER, DEFAULT_NTP_SERVER);
299 std::string ntpServerSpec = system::GetParameter(NTP_SERVER_SPECIFIC_SYSTEM_PARAMETER, "");
300 if (ntpServer.empty() && ntpServerSpec.empty()) {
301 TIME_HILOGW(TIME_MODULE_SERVICE, "No found ntp server from system parameter");
302 return;
303 }
304 autoTimeInfo_.ntpServer = ntpServer;
305 autoTimeInfo_.ntpServerSpec = ntpServerSpec;
306 SetSystemTime();
307 }
308
ChangeAutoTimeCallback(const char * key,const char * value,void * context)309 void NtpUpdateTime::ChangeAutoTimeCallback(const char *key, const char *value, void *context)
310 {
311 TIME_HILOGI(TIME_MODULE_SERVICE, "Auto sync switch changed");
312 if (key == nullptr || value == nullptr) {
313 TIME_HILOGE(TIME_MODULE_SERVICE, "key or value is nullptr");
314 return;
315 }
316 if (std::string(AUTO_TIME_SYSTEM_PARAMETER).compare(key) != 0) {
317 TIME_HILOGE(TIME_MODULE_SERVICE, "incorrect key:%{public}s", key);
318 return;
319 }
320
321 if (std::string(AUTO_TIME_STATUS_ON).compare(value) != 0 && std::string(AUTO_TIME_STATUS_OFF).compare(value) != 0) {
322 TIME_HILOGE(TIME_MODULE_SERVICE, "incorrect value:%{public}s", value);
323 return;
324 }
325 autoTimeInfo_.status = std::string(value);
326 SetSystemTime();
327 }
328
GetNITZUpdateTime()329 uint64_t NtpUpdateTime::GetNITZUpdateTime()
330 {
331 return static_cast<uint64_t>(lastNITZUpdateTime_);
332 }
333 } // namespace MiscServices
334 } // namespace OHOS