• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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