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