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