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 <chrono>
18 #include <cinttypes>
19 #include <string>
20 #include <thread>
21 #include <unistd.h>
22 #include <sys/time.h>
23
24 #include "init_param.h"
25 #include "net_conn_callback_observer.h"
26 #include "net_conn_client.h"
27 #include "net_specifier.h"
28 #include "ntp_trusted_time.h"
29 #include "parameters.h"
30 #include "time_common.h"
31 #include "time_system_ability.h"
32
33 using namespace std::chrono;
34 using namespace OHOS::NetManagerStandard;
35
36 namespace OHOS {
37 namespace MiscServices {
38 namespace {
39 constexpr int64_t NANO_TO_MILLISECOND = 1000000;
40 constexpr int64_t DAY_TO_MILLISECOND = 86400000;
41 const std::string NTP_SERVER_SYSTEM_PARAMETER = "persist.time.ntpserver";
42 const std::string NTP_SERVER_SPECIFIC_SYSTEM_PARAMETER = "persist.time.ntpserver_specific";
43 const uint32_t NTP_MAX_SIZE = 5;
44 const std::string AUTO_TIME_SYSTEM_PARAMETER = "persist.time.auto_time";
45 const std::string AUTO_TIME_STATUS_ON = "ON";
46 const std::string AUTO_TIME_STATUS_OFF = "OFF";
47 constexpr uint64_t TWO_SECONDS = 2000;
48 constexpr uint64_t ONE_HOUR = 3600000;
49 constexpr int32_t NET_RETRY_TIMES = 3;
50 constexpr uint32_t RETRY_INTERVAL = 1;
51 const std::string DEFAULT_NTP_SERVER = "1.cn.pool.ntp.org";
52 constexpr int32_t RETRY_TIMES = 2;
53 } // namespace
54
55 AutoTimeInfo NtpUpdateTime::autoTimeInfo_{};
56 std::mutex NtpUpdateTime::requestMutex_;
57
NtpUpdateTime()58 NtpUpdateTime::NtpUpdateTime() : timerId_(0), nitzUpdateTimeMilli_(0), nextTriggerTime_(0), lastNITZUpdateTime_(0){};
59
GetInstance()60 NtpUpdateTime& NtpUpdateTime::GetInstance()
61 {
62 static NtpUpdateTime instance;
63 return instance;
64 }
65
Init()66 void NtpUpdateTime::Init()
67 {
68 TIME_HILOGD(TIME_MODULE_SERVICE, "Ntp Update Time start.");
69 std::string ntpServer = system::GetParameter(NTP_SERVER_SYSTEM_PARAMETER, DEFAULT_NTP_SERVER);
70 std::string ntpServerSpec = system::GetParameter(NTP_SERVER_SPECIFIC_SYSTEM_PARAMETER, "");
71 std::string autoTime = system::GetParameter(AUTO_TIME_SYSTEM_PARAMETER, "ON");
72 if ((ntpServer.empty() && ntpServerSpec.empty()) || autoTime.empty()) {
73 TIME_HILOGW(TIME_MODULE_SERVICE, "No found parameter from system parameter.");
74 return;
75 }
76 RegisterSystemParameterListener();
77 autoTimeInfo_.ntpServer = ntpServer;
78 autoTimeInfo_.ntpServerSpec = ntpServerSpec;
79 autoTimeInfo_.status = autoTime;
80 auto callback = [this](uint64_t id) -> int32_t {
81 this->RefreshNetworkTimeByTimer(id);
82 return E_TIME_OK;
83 };
84 TimerPara timerPara{};
85 timerPara.timerType = static_cast<int>(ITimerManager::TimerType::ELAPSED_REALTIME);
86 timerPara.windowLength = 0;
87 timerPara.interval = DAY_TO_MILLISECOND;
88 timerPara.flag = 0;
89 TimeSystemAbility::GetInstance()->CreateTimer(timerPara, callback, timerId_);
90 RefreshNextTriggerTime();
91 TimeSystemAbility::GetInstance()->StartTimer(timerId_, nextTriggerTime_);
92 TIME_HILOGI(TIME_MODULE_SERVICE, "ntp update timerId: %{public}" PRIu64 "triggertime: %{public}" PRId64 "",
93 timerId_, nextTriggerTime_);
94 }
95
MonitorNetwork()96 int32_t NtpUpdateTime::MonitorNetwork()
97 {
98 // observer net connection
99 TIME_HILOGD(TIME_MODULE_SERVICE, "NtpUpdateTime::MonitorNetwork");
100 NetSpecifier netSpecifier;
101 NetAllCapabilities netAllCapabilities;
102 netAllCapabilities.netCaps_.insert(NetManagerStandard::NetCap::NET_CAPABILITY_INTERNET);
103 netSpecifier.netCapabilities_ = netAllCapabilities;
104 sptr<NetSpecifier> specifier = new (std::nothrow) NetSpecifier(netSpecifier);
105 if (specifier == nullptr) {
106 TIME_HILOGE(TIME_MODULE_SERVICE, "new operator error.specifier is nullptr");
107 return NET_CONN_ERR_INPUT_NULL_PTR;
108 }
109 sptr<NetConnCallbackObserver> observer = new (std::nothrow) NetConnCallbackObserver();
110 if (observer == nullptr) {
111 TIME_HILOGE(TIME_MODULE_SERVICE, "new operator error.observer is nullptr");
112 return NET_CONN_ERR_INPUT_NULL_PTR;
113 }
114 int nRet = NetConnClient::GetInstance().RegisterNetConnCallback(specifier, observer, 0);
115 TIME_HILOGI(TIME_MODULE_SERVICE, "RegisterNetConnCallback retcode= %{public}d", nRet);
116
117 if (nRet == E_TIME_OK) {
118 return nRet;
119 }
120 auto retryRegister = [specifier, observer]() {
121 for (int i = 0; i < NET_RETRY_TIMES; i++) {
122 sleep(RETRY_INTERVAL);
123 int nRet = NetConnClient::GetInstance().RegisterNetConnCallback(specifier, observer, 0);
124 TIME_HILOGI(TIME_MODULE_SERVICE, "RegisterNetConnCallback retcode= %{public}d", nRet);
125 if (nRet == E_TIME_OK) {
126 return;
127 }
128 }
129 };
130 std::thread thread(retryRegister);
131 thread.detach();
132 return nRet;
133 }
134
RefreshNetworkTimeByTimer(uint64_t timerId)135 void NtpUpdateTime::RefreshNetworkTimeByTimer(uint64_t timerId)
136 {
137 TIME_HILOGI(TIME_MODULE_SERVICE, "The timer is up");
138 if (!CheckStatus()) {
139 TIME_HILOGI(TIME_MODULE_SERVICE, "Auto Sync Switch Off");
140 return;
141 }
142
143 if (IsValidNITZTime()) {
144 TIME_HILOGI(TIME_MODULE_SERVICE, "NITZ is valid");
145 return;
146 }
147
148 auto setSystemTime = [this]() { this->SetSystemTime(); };
149 std::thread thread(setSystemTime);
150 thread.detach();
151 TIME_HILOGD(TIME_MODULE_SERVICE, "Ntp next triggertime: %{public}" PRId64 "", nextTriggerTime_);
152 }
153
UpdateNITZSetTime()154 void NtpUpdateTime::UpdateNITZSetTime()
155 {
156 auto bootTimeNano = steady_clock::now().time_since_epoch().count();
157 auto bootTimeMilli = bootTimeNano / NANO_TO_MILLISECOND;
158 if (TimeUtils::GetBootTimeMs(lastNITZUpdateTime_) != ERR_OK) {
159 TIME_HILOGE(TIME_MODULE_SERVICE, "get boot time fail.");
160 }
161 TIME_HILOGD(TIME_MODULE_SERVICE, "nitz time changed.");
162 nitzUpdateTimeMilli_ = static_cast<uint64_t>(bootTimeMilli);
163 }
164
SplitNtpAddrs(const std::string & ntpStr)165 std::vector<std::string> NtpUpdateTime::SplitNtpAddrs(const std::string &ntpStr)
166 {
167 std::vector<std::string> ntpList;
168 size_t start = 0;
169 do {
170 if (ntpList.size() == NTP_MAX_SIZE) {
171 break;
172 }
173 size_t end = ntpStr.find(',', start);
174 if (end < start) {
175 break;
176 }
177 std::string temp = ntpStr.substr(start, end - start);
178 if (temp.empty()) {
179 ++start;
180 continue;
181 }
182 if (end == std::string::npos) {
183 ntpList.emplace_back(temp);
184 break;
185 }
186 ntpList.emplace_back(temp);
187 start = end + 1;
188 } while (start < ntpStr.size());
189 return ntpList;
190 }
191
GetNtpTimeInner(uint64_t interval)192 bool NtpUpdateTime::GetNtpTimeInner(uint64_t interval)
193 {
194 // Determine the time interval between two NTP requests sent.
195 int64_t curBootTime = std::chrono::duration_cast<std::chrono::milliseconds>(
196 NtpTrustedTime::GetInstance().GetBootTimeNs().time_since_epoch()).count();
197 uint64_t bootTime = static_cast<uint64_t>(curBootTime);
198 auto lastBootTime = NtpTrustedTime::GetInstance().ElapsedRealtimeMillis();
199 // If the time interval is too small, do not send NTP requests.
200 if ((lastBootTime > 0) && (bootTime - static_cast<uint64_t>(lastBootTime) <= interval)) {
201 TIME_HILOGI(TIME_MODULE_SERVICE,
202 "ntp updated within %{public}" PRId64 ", bootTime: %{public}" PRId64 ", lastBootTime: %{public}" PRId64 "",
203 interval, bootTime, lastBootTime);
204 return true;
205 }
206
207 std::vector<std::string> ntpSpecList = SplitNtpAddrs(autoTimeInfo_.ntpServerSpec);
208 std::vector<std::string> ntpList = SplitNtpAddrs(autoTimeInfo_.ntpServer);
209 ntpSpecList.insert(ntpSpecList.end(), ntpList.begin(), ntpList.end());
210 for (int i = 0; i < RETRY_TIMES; i++) {
211 for (size_t i = 0; i < ntpSpecList.size(); i++) {
212 TIME_HILOGI(TIME_MODULE_SERVICE, "ntpServer is : %{public}s", ntpSpecList[i].c_str());
213 if (NtpTrustedTime::GetInstance().ForceRefresh(ntpSpecList[i])) {
214 return true;
215 }
216 }
217 }
218 return false;
219 }
220
GetRealTimeInner(int64_t & time)221 bool NtpUpdateTime::GetRealTimeInner(int64_t &time)
222 {
223 time = NtpTrustedTime::GetInstance().CurrentTimeMillis();
224 if (time <= 0) {
225 TIME_HILOGE(TIME_MODULE_SERVICE, "current time is invalid: %{public}" PRId64 "", time);
226 return false;
227 }
228 return true;
229 }
230
GetRealTime(int64_t & time)231 bool NtpUpdateTime::GetRealTime(int64_t &time)
232 {
233 std::lock_guard<std::mutex> autoLock(requestMutex_);
234 return GetRealTimeInner(time);
235 }
236
GetNtpTime(int64_t & time)237 bool NtpUpdateTime::GetNtpTime(int64_t &time)
238 {
239 std::lock_guard<std::mutex> autoLock(requestMutex_);
240
241 if (!GetNtpTimeInner(ONE_HOUR)) {
242 TIME_HILOGE(TIME_MODULE_SERVICE, "get ntp time failed.");
243 return false;
244 }
245
246 if (!GetRealTimeInner(time)) {
247 return false;
248 }
249
250 if (autoTimeInfo_.status == AUTO_TIME_STATUS_ON) {
251 TimeSystemAbility::GetInstance()->SetTime(time);
252 }
253 return true;
254 }
255
SetSystemTime()256 void NtpUpdateTime::SetSystemTime()
257 {
258 if (autoTimeInfo_.status != AUTO_TIME_STATUS_ON) {
259 TIME_HILOGI(TIME_MODULE_SERVICE, "auto sync switch off");
260 return;
261 }
262
263 if (!requestMutex_.try_lock()) {
264 TIME_HILOGW(TIME_MODULE_SERVICE, "The NTP request is in progress.");
265 return;
266 }
267
268 if (!GetNtpTimeInner(ONE_HOUR)) {
269 TIME_HILOGE(TIME_MODULE_SERVICE, "get ntp time failed.");
270 requestMutex_.unlock();
271 return;
272 }
273
274 int64_t currentTime = NtpTrustedTime::GetInstance().CurrentTimeMillis();
275 if (currentTime <= 0) {
276 TIME_HILOGE(TIME_MODULE_SERVICE, "current time is invalid: %{public}" PRIu64 "", currentTime);
277 requestMutex_.unlock();
278 return;
279 }
280 int64_t curBootTime = 0;
281 if (TimeUtils::GetBootTimeMs(curBootTime) != ERR_OK) {
282 TIME_HILOGE(TIME_MODULE_SERVICE, "get boot time fail.");
283 requestMutex_.unlock();
284 return;
285 }
286 uint64_t bootTime = static_cast<uint64_t>(curBootTime);
287 if (bootTime - NtpUpdateTime::GetInstance().GetNITZUpdateTime() <= TWO_SECONDS) {
288 TIME_HILOGE(TIME_MODULE_SERVICE, "nitz updated time");
289 requestMutex_.unlock();
290 return;
291 }
292
293 TimeSystemAbility::GetInstance()->SetTime(currentTime);
294 requestMutex_.unlock();
295 }
296
RefreshNextTriggerTime()297 void NtpUpdateTime::RefreshNextTriggerTime()
298 {
299 auto bootTimeNano = steady_clock::now().time_since_epoch().count();
300 auto bootTimeMilli = bootTimeNano / NANO_TO_MILLISECOND;
301 nextTriggerTime_ = static_cast<uint64_t>(bootTimeMilli + DAY_TO_MILLISECOND);
302 }
303
CheckStatus()304 bool NtpUpdateTime::CheckStatus()
305 {
306 return autoTimeInfo_.status == AUTO_TIME_STATUS_ON;
307 }
308
IsValidNITZTime()309 bool NtpUpdateTime::IsValidNITZTime()
310 {
311 if (nitzUpdateTimeMilli_ == 0) {
312 return false;
313 }
314 int64_t bootTimeNano = static_cast<int64_t>(steady_clock::now().time_since_epoch().count());
315 int64_t bootTimeMilli = bootTimeNano / NANO_TO_MILLISECOND;
316 TIME_HILOGI(TIME_MODULE_SERVICE, "nitz update time: %{public}" PRIu64 " currentTime: %{public}" PRId64 "",
317 nitzUpdateTimeMilli_, bootTimeMilli);
318 return (bootTimeMilli - static_cast<int64_t>(nitzUpdateTimeMilli_)) < DAY_TO_MILLISECOND;
319 }
320
StartTimer()321 void NtpUpdateTime::StartTimer()
322 {
323 TimeSystemAbility::GetInstance()->StartTimer(timerId_, nextTriggerTime_);
324 }
325
Stop()326 void NtpUpdateTime::Stop()
327 {
328 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
329 TimeSystemAbility::GetInstance()->DestroyTimer(timerId_, false);
330 }
331
RegisterSystemParameterListener()332 void NtpUpdateTime::RegisterSystemParameterListener()
333 {
334 TIME_HILOGD(TIME_MODULE_SERVICE, "register system parameter modify lister");
335 auto specificNtpResult = SystemWatchParameter(NTP_SERVER_SPECIFIC_SYSTEM_PARAMETER.c_str(),
336 ChangeNtpServerCallback, nullptr);
337 if (specificNtpResult != E_TIME_OK) {
338 TIME_HILOGE(TIME_MODULE_SERVICE, "register specific ntp server lister fail: %{public}d", specificNtpResult);
339 }
340
341 auto netResult = SystemWatchParameter(NTP_SERVER_SYSTEM_PARAMETER.c_str(), ChangeNtpServerCallback, nullptr);
342 if (netResult != E_TIME_OK) {
343 TIME_HILOGE(TIME_MODULE_SERVICE, "register ntp server lister fail: %{public}d", netResult);
344 }
345
346 auto switchResult = SystemWatchParameter(AUTO_TIME_SYSTEM_PARAMETER.c_str(), ChangeAutoTimeCallback, nullptr);
347 if (switchResult != E_TIME_OK) {
348 TIME_HILOGE(TIME_MODULE_SERVICE, "register auto sync switch lister fail: %{public}d", switchResult);
349 }
350 }
351
ChangeNtpServerCallback(const char * key,const char * value,void * context)352 void NtpUpdateTime::ChangeNtpServerCallback(const char *key, const char *value, void *context)
353 {
354 TIME_HILOGI(TIME_MODULE_SERVICE, "Ntp server changed");
355 std::string ntpServer = system::GetParameter(NTP_SERVER_SYSTEM_PARAMETER, DEFAULT_NTP_SERVER);
356 std::string ntpServerSpec = system::GetParameter(NTP_SERVER_SPECIFIC_SYSTEM_PARAMETER, "");
357 if (ntpServer.empty() && ntpServerSpec.empty()) {
358 TIME_HILOGW(TIME_MODULE_SERVICE, "No found ntp server from system parameter.");
359 return;
360 }
361 autoTimeInfo_.ntpServer = ntpServer;
362 autoTimeInfo_.ntpServerSpec = ntpServerSpec;
363 SetSystemTime();
364 }
365
ChangeAutoTimeCallback(const char * key,const char * value,void * context)366 void NtpUpdateTime::ChangeAutoTimeCallback(const char *key, const char *value, void *context)
367 {
368 TIME_HILOGI(TIME_MODULE_SERVICE, "Auto sync switch changed");
369 if (key == nullptr || value == nullptr) {
370 TIME_HILOGE(TIME_MODULE_SERVICE, "key or value is nullptr");
371 return;
372 }
373 if (AUTO_TIME_SYSTEM_PARAMETER.compare(key) != 0) {
374 TIME_HILOGE(TIME_MODULE_SERVICE, "incorrect key:%{public}s", key);
375 return;
376 }
377
378 if (AUTO_TIME_STATUS_ON.compare(value) != 0 && AUTO_TIME_STATUS_OFF.compare(value) != 0) {
379 TIME_HILOGE(TIME_MODULE_SERVICE, "incorrect value:%{public}s", value);
380 return;
381 }
382 autoTimeInfo_.status = std::string(value);
383 SetSystemTime();
384 }
385
GetNITZUpdateTime()386 uint64_t NtpUpdateTime::GetNITZUpdateTime()
387 {
388 return static_cast<uint64_t>(lastNITZUpdateTime_);
389 }
390 } // namespace MiscServices
391 } // namespace OHOS