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