• 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 "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