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