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