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