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
CheckStatus()193 bool NtpUpdateTime::CheckStatus()
194 {
195 return autoTimeInfo_.status == NETWORK_TIME_STATUS_ON;
196 }
197
IsNITZTimeInvalid()198 bool NtpUpdateTime::IsNITZTimeInvalid()
199 {
200 if (nitzUpdateTimeMili_ == 0) {
201 return false;
202 }
203 auto BootTimeNano = steady_clock::now().time_since_epoch().count();
204 auto BootTimeMilli = BootTimeNano / NANO_TO_MILLISECOND;
205 return (BootTimeMilli - static_cast<int64_t>(nitzUpdateTimeMili_)) < DAY_TO_MILLISECOND;
206 }
207
StartTimer()208 void NtpUpdateTime::StartTimer()
209 {
210 TimeSystemAbility::GetInstance()->StartTimer(timerId_, nextTriggerTime_);
211 }
212
Stop()213 void NtpUpdateTime::Stop()
214 {
215 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
216 TimeSystemAbility::GetInstance()->DestroyTimer(timerId_);
217 }
218
GetAutoTimeInfoFromFile(autoTimeInfo & info)219 bool NtpUpdateTime::GetAutoTimeInfoFromFile(autoTimeInfo &info)
220 {
221 Json::Value jsonValue;
222 std::ifstream ifs;
223 ifs.open(AUTOTIME_FILE_PATH);
224 Json::CharReaderBuilder builder;
225 builder["collectComments"] = true;
226 JSONCPP_STRING errs;
227 if (!parseFromStream(builder, ifs, &jsonValue, &errs)) {
228 ifs.close();
229 TIME_HILOGE(TIME_MODULE_SERVICE, "Read file failed %{public}s.", errs.c_str());
230 return false;
231 }
232 info.status = jsonValue["status"].asString();
233 info.NTP_SERVER = jsonValue["ntpServer"].asString();
234 info.lastUpdateTime = jsonValue["lastUpdateTime"].asInt64();
235 TIME_HILOGD(TIME_MODULE_SERVICE, "Read file %{public}s.", info.status.c_str());
236 TIME_HILOGD(TIME_MODULE_SERVICE, "Read file %{public}s.", info.NTP_SERVER.c_str());
237 TIME_HILOGD(TIME_MODULE_SERVICE, "Read file %{public}" PRId64 "", info.lastUpdateTime);
238 ifs.close();
239 return true;
240 }
241
SaveAutoTimeInfoToFile(autoTimeInfo & info)242 bool NtpUpdateTime::SaveAutoTimeInfoToFile(autoTimeInfo &info)
243 {
244 Json::Value jsonValue;
245 std::ofstream ofs;
246 ofs.open(AUTOTIME_FILE_PATH);
247 jsonValue["status"] = info.status;
248 jsonValue["ntpServer"] = info.NTP_SERVER;
249 jsonValue["lastUpdateTime"] = info.lastUpdateTime;
250 Json::StreamWriterBuilder builder;
251 const std::string json_file = Json::writeString(builder, jsonValue);
252 ofs << json_file;
253 ofs.close();
254 TIME_HILOGD(TIME_MODULE_SERVICE, "Write file %{public}s.", info.status.c_str());
255 TIME_HILOGD(TIME_MODULE_SERVICE, "Write file %{public}s.", info.NTP_SERVER.c_str());
256 TIME_HILOGD(TIME_MODULE_SERVICE, "Write file %{public}" PRId64 "", info.lastUpdateTime);
257 return true;
258 }
259 } // MiscServices
260 } // OHOS