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 <ctime>
20 #include <fstream>
21 #include <mutex>
22 #include <string>
23 #include <sys/prctl.h>
24 #include <thread>
25 #include <unistd.h>
26
27 #include "init_param.h"
28 #include "json/json.h"
29 #include "net_conn_callback_observer.h"
30 #include "net_conn_client.h"
31 #include "net_specifier.h"
32 #include "nitz_subscriber.h"
33 #include "ntp_trusted_time.h"
34 #include "parameters.h"
35 #include "simple_timer_info.h"
36 #include "time_common.h"
37 #include "time_system_ability.h"
38 #include "time_zone_info.h"
39
40 using namespace std::chrono;
41 using namespace OHOS::NetManagerStandard;
42
43 namespace OHOS {
44 namespace MiscServices {
45 namespace {
46 constexpr int64_t NANO_TO_MILLISECOND = 1000000;
47 constexpr int64_t DAY_TO_MILLISECOND = 86400000;
48 const std::string AUTOTIME_FILE_PATH = "/data/service/el1/public/time/autotime.json";
49 const std::string NETWORK_TIME_STATUS_ON = "ON";
50 const std::string NETWORK_TIME_STATUS_OFF = "OFF";
51 const std::string NTP_SERVER_SYSTEM_PARAMETER = "persist.time.ntpserver";
52 const int64_t INVALID_TIMES = -1;
53 } // namespace
54
55 AutoTimeInfo NtpUpdateTime::autoTimeInfo_ {};
56
NtpUpdateTime()57 NtpUpdateTime::NtpUpdateTime() : timerId_(0), nitzUpdateTimeMilli_(0), nextTriggerTime_(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 SubscriberNITZTimeChangeCommonEvent();
69 std::string ntpServer = system::GetParameter(NTP_SERVER_SYSTEM_PARAMETER.c_str(), "ntp.aliyun.com");
70 if (ntpServer.empty()) {
71 TIME_HILOGW(TIME_MODULE_SERVICE, "No found ntp server from system parameter.");
72 return;
73 }
74 RegisterNtpServerListener();
75 if (!GetAutoTimeInfoFromFile(autoTimeInfo_)) {
76 autoTimeInfo_.lastUpdateTime = INVALID_TIMES;
77 autoTimeInfo_.NTP_SERVER = ntpServer;
78 autoTimeInfo_.status = NETWORK_TIME_STATUS_ON;
79 if (!SaveAutoTimeInfoToFile(autoTimeInfo_)) {
80 TIME_HILOGE(TIME_MODULE_SERVICE, "end, SaveAutoTimeInfoToFile failed.");
81 return;
82 }
83 if (!GetAutoTimeInfoFromFile(autoTimeInfo_)) {
84 TIME_HILOGE(TIME_MODULE_SERVICE, "end, GetAutoTimeInfoFromFile failed.");
85 return;
86 }
87 }
88
89 std::thread th = std::thread([this]() {
90 pthread_setname_np(pthread_self(), "time_monitor_network");
91 constexpr int RETRY_MAX_TIMES = 100;
92 int retryCount = 0;
93 constexpr int RETRY_TIME_INTERVAL_MILLISECOND = 1 * 1000 * 1000; // retry after 2 second
94 do {
95 if (this->MonitorNetwork() == NETMANAGER_SUCCESS) {
96 break;
97 }
98 retryCount++;
99 usleep(RETRY_TIME_INTERVAL_MILLISECOND);
100 } while (retryCount < RETRY_MAX_TIMES);
101 });
102 th.detach();
103
104 int32_t timerType = ITimerManager::TimerType::ELAPSED_REALTIME;
105 auto callback = [this](uint64_t id) { this->RefreshNetworkTimeByTimer(id); };
106
107 TimerPara timerPara{};
108 timerPara.timerType = timerType;
109 timerPara.windowLength = 0;
110 timerPara.interval = DAY_TO_MILLISECOND;
111 timerPara.flag = 0;
112
113 TimeSystemAbility::GetInstance()->CreateTimer(timerPara, callback, timerId_);
114 TIME_HILOGD(TIME_MODULE_SERVICE, "Ntp update timerId: %{public}" PRId64 "", timerId_);
115 RefreshNextTriggerTime();
116 TIME_HILOGD(TIME_MODULE_SERVICE, "Ntp update triggertime: %{public}" PRId64 "", nextTriggerTime_);
117 TimeSystemAbility::GetInstance()->StartTimer(timerId_, nextTriggerTime_);
118 }
119
MonitorNetwork()120 int32_t NtpUpdateTime::MonitorNetwork()
121 {
122 // observer net connection
123 TIME_HILOGD(TIME_MODULE_SERVICE, "NtpUpdateTime::MonitorNetwork");
124 NetSpecifier netSpecifier;
125 NetAllCapabilities netAllCapabilities;
126 netAllCapabilities.netCaps_.insert(NetManagerStandard::NetCap::NET_CAPABILITY_INTERNET);
127 netSpecifier.netCapabilities_ = netAllCapabilities;
128 sptr<NetSpecifier> specifier = new (std::nothrow) NetSpecifier(netSpecifier);
129 if (specifier == nullptr) {
130 TIME_HILOGD(TIME_MODULE_SERVICE, "new operator error.specifier is nullptr");
131 return NET_CONN_ERR_INPUT_NULL_PTR;
132 }
133 sptr<NetConnCallbackObserver> observer = new (std::nothrow) NetConnCallbackObserver();
134 if (observer == nullptr) {
135 TIME_HILOGD(TIME_MODULE_SERVICE, "new operator error.observer is nullptr");
136 return NET_CONN_ERR_INPUT_NULL_PTR;
137 }
138 int nRet = NetConnClient::GetInstance().RegisterNetConnCallback(specifier, observer, 0);
139 TIME_HILOGD(TIME_MODULE_SERVICE, "RegisterNetConnCallback retcode= %{public}d", nRet);
140
141 return nRet;
142 }
143
SubscriberNITZTimeChangeCommonEvent()144 void NtpUpdateTime::SubscriberNITZTimeChangeCommonEvent()
145 {
146 // Broadcast subscription
147 MatchingSkills matchingSkills;
148 matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_NITZ_TIME_CHANGED);
149 CommonEventSubscribeInfo subscriberInfo(matchingSkills);
150 std::shared_ptr<NITZSubscriber> subscriberPtr = std::make_shared<NITZSubscriber>(subscriberInfo);
151 bool subscribeResult = CommonEventManager::SubscribeCommonEvent(subscriberPtr);
152 if (!subscribeResult) {
153 TIME_HILOGE(TIME_MODULE_SERVICE, "SubscribeCommonEvent failed");
154 }
155 }
156
RefreshNetworkTimeByTimer(uint64_t timerId)157 void NtpUpdateTime::RefreshNetworkTimeByTimer(uint64_t timerId)
158 {
159 if (!(CheckStatus())) {
160 TIME_HILOGD(TIME_MODULE_SERVICE, "Network time status off.");
161 return;
162 }
163 if (IsValidNITZTime()) {
164 TIME_HILOGD(TIME_MODULE_SERVICE, "NITZ Time is valid.");
165 return;
166 }
167 SetSystemTime();
168 SaveAutoTimeInfoToFile(autoTimeInfo_);
169 TIME_HILOGD(TIME_MODULE_SERVICE, "Ntp update triggertime: %{public}" PRId64 "", nextTriggerTime_);
170 }
171
UpdateNITZSetTime()172 void NtpUpdateTime::UpdateNITZSetTime()
173 {
174 auto BootTimeNano = steady_clock::now().time_since_epoch().count();
175 auto BootTimeMilli = BootTimeNano / NANO_TO_MILLISECOND;
176 TIME_HILOGD(TIME_MODULE_SERVICE, "nitz time changed.");
177 nitzUpdateTimeMilli_ = BootTimeMilli;
178 }
179
SetSystemTime()180 void NtpUpdateTime::SetSystemTime()
181 {
182 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
183 if (!NtpTrustedTime::GetInstance().ForceRefresh(autoTimeInfo_.NTP_SERVER)) {
184 TIME_HILOGE(TIME_MODULE_SERVICE, "get ntp time failed.");
185 return;
186 }
187 int64_t currentTime = NtpTrustedTime::GetInstance().CurrentTimeMillis();
188 if (currentTime == INVALID_TIMES) {
189 TIME_HILOGD(TIME_MODULE_SERVICE, "Ntp update time failed");
190 return;
191 }
192 if (currentTime <= 0) {
193 TIME_HILOGD(TIME_MODULE_SERVICE, "current time invalid.");
194 return;
195 }
196 TIME_HILOGD(TIME_MODULE_SERVICE, "Ntp UTC Time: %{public}" PRId64 "", currentTime);
197 TimeSystemAbility::GetInstance()->SetTime(currentTime);
198 autoTimeInfo_.lastUpdateTime = currentTime;
199 TIME_HILOGD(TIME_MODULE_SERVICE, "Ntp update currentTime: %{public}" PRId64 "", currentTime);
200 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
201 }
202
RefreshNextTriggerTime()203 void NtpUpdateTime::RefreshNextTriggerTime()
204 {
205 auto bootTimeNano = steady_clock::now().time_since_epoch().count();
206 auto bootTimeMilli = bootTimeNano / NANO_TO_MILLISECOND;
207 nextTriggerTime_ = static_cast<uint64_t>(bootTimeMilli + DAY_TO_MILLISECOND);
208 }
209
CheckStatus()210 bool NtpUpdateTime::CheckStatus()
211 {
212 return autoTimeInfo_.status == NETWORK_TIME_STATUS_ON;
213 }
214
IsValidNITZTime()215 bool NtpUpdateTime::IsValidNITZTime()
216 {
217 if (nitzUpdateTimeMilli_ == 0) {
218 return false;
219 }
220 auto BootTimeNano = steady_clock::now().time_since_epoch().count();
221 auto BootTimeMilli = BootTimeNano / NANO_TO_MILLISECOND;
222 return (BootTimeMilli - static_cast<int64_t>(nitzUpdateTimeMilli_)) < DAY_TO_MILLISECOND;
223 }
224
StartTimer()225 void NtpUpdateTime::StartTimer()
226 {
227 TimeSystemAbility::GetInstance()->StartTimer(timerId_, nextTriggerTime_);
228 }
229
Stop()230 void NtpUpdateTime::Stop()
231 {
232 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
233 TimeSystemAbility::GetInstance()->DestroyTimer(timerId_);
234 }
235
GetAutoTimeInfoFromFile(AutoTimeInfo & info)236 bool NtpUpdateTime::GetAutoTimeInfoFromFile(AutoTimeInfo &info)
237 {
238 Json::Value jsonValue;
239 std::ifstream ifs;
240 ifs.open(AUTOTIME_FILE_PATH);
241 Json::CharReaderBuilder builder;
242 builder["collectComments"] = true;
243 JSONCPP_STRING errs;
244 if (!parseFromStream(builder, ifs, &jsonValue, &errs)) {
245 ifs.close();
246 TIME_HILOGE(TIME_MODULE_SERVICE, "Read file failed %{public}s.", errs.c_str());
247 return false;
248 }
249 info.status = jsonValue["status"].asString();
250 info.NTP_SERVER = jsonValue["ntpServer"].asString();
251 info.lastUpdateTime = jsonValue["lastUpdateTime"].asInt64();
252 TIME_HILOGD(TIME_MODULE_SERVICE, "Read file %{public}s.", info.status.c_str());
253 TIME_HILOGD(TIME_MODULE_SERVICE, "Read file %{public}s.", info.NTP_SERVER.c_str());
254 TIME_HILOGD(TIME_MODULE_SERVICE, "Read file %{public}" PRId64 "", info.lastUpdateTime);
255 ifs.close();
256 return true;
257 }
258
SaveAutoTimeInfoToFile(const AutoTimeInfo & info)259 bool NtpUpdateTime::SaveAutoTimeInfoToFile(const AutoTimeInfo &info)
260 {
261 Json::Value jsonValue;
262 std::ofstream ofs;
263 ofs.open(AUTOTIME_FILE_PATH);
264 jsonValue["status"] = info.status;
265 jsonValue["ntpServer"] = info.NTP_SERVER;
266 jsonValue["lastUpdateTime"] = info.lastUpdateTime;
267 Json::StreamWriterBuilder builder;
268 const std::string json_file = Json::writeString(builder, jsonValue);
269 ofs << json_file;
270 ofs.close();
271 TIME_HILOGD(TIME_MODULE_SERVICE, "Write file %{public}s.", info.status.c_str());
272 TIME_HILOGD(TIME_MODULE_SERVICE, "Write file %{public}s.", info.NTP_SERVER.c_str());
273 TIME_HILOGD(TIME_MODULE_SERVICE, "Write file %{public}" PRId64 "", info.lastUpdateTime);
274 return true;
275 }
276
RegisterNtpServerListener()277 void NtpUpdateTime::RegisterNtpServerListener()
278 {
279 TIME_HILOGD(TIME_MODULE_SERVICE, "register ntp server lister");
280 if (SystemWatchParameter(NTP_SERVER_SYSTEM_PARAMETER.c_str(), ChangeNtpServerCallback, nullptr) != E_TIME_OK) {
281 TIME_HILOGD(TIME_MODULE_SERVICE, "register ntp server lister fail");
282 }
283 }
284
ChangeNtpServerCallback(const char * key,const char * value,void * context)285 void NtpUpdateTime::ChangeNtpServerCallback(const char *key, const char *value, void *context)
286 {
287 TIME_HILOGD(TIME_MODULE_SERVICE, "set time for ntp server changed");
288 std::string ntpServer = system::GetParameter(NTP_SERVER_SYSTEM_PARAMETER.c_str(), "ntp.aliyun.com");
289 if (ntpServer.empty()) {
290 TIME_HILOGW(TIME_MODULE_SERVICE, "No found ntp server from system parameter.");
291 return;
292 }
293 if (!GetAutoTimeInfoFromFile(autoTimeInfo_)) {
294 autoTimeInfo_.lastUpdateTime = INVALID_TIMES;
295 autoTimeInfo_.status = NETWORK_TIME_STATUS_ON;
296 }
297 autoTimeInfo_.NTP_SERVER = ntpServer;
298 if (!SaveAutoTimeInfoToFile(autoTimeInfo_)) {
299 TIME_HILOGE(TIME_MODULE_SERVICE, "end, SaveAutoTimeInfoToFile failed.");
300 return;
301 }
302 SetSystemTime();
303 }
304 } // namespace MiscServices
305 } // namespace OHOS