• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 
16 #include "nitz_update.h"
17 
18 #include <securec.h>
19 
20 #include "common_event.h"
21 #include "common_event_manager.h"
22 #include "common_event_support.h"
23 #include "core_manager_inner.h"
24 #include "network_search_manager.h"
25 #include "power_mgr_client.h"
26 #include "setting_utils.h"
27 #include "string_ex.h"
28 #include "telephony_log_wrapper.h"
29 #include "time_service_client.h"
30 #include "zone_util.h"
31 
32 using namespace OHOS::PowerMgr;
33 using namespace OHOS::AppExecFwk;
34 using namespace OHOS::EventFwk;
35 namespace OHOS {
36 namespace Telephony {
37 const int32_t MILLI_TO_BASE = 1000;
38 const int32_t MAX_UPDATE_TIME = 5;
39 const std::string KEY_AUTO_TIME_ZONE = "auto_timezone";
40 const std::string KEY_AUTO_TIME = "auto_time";
41 const std::string KEY_SYSTEM_TIMEZONE = "system_timezone";
42 const std::string KEY_SYSTEM_TIME = "system_time";
43 const uint32_t TIME_SPLIT_NUM = 3;
44 const uint32_t TIMEZONE_SPLIT_NUM = 2;
45 const uint32_t YEAR_LENGTH_TWO = 2;
46 const uint32_t YEAR_LENGTH_FOUR = 4;
47 const uint32_t CST_YEAR = 1900;
48 const uint32_t ONE_HOUR_TO_SECOND = 3600;
49 const uint32_t ONE_SECOND_TO_MILLISECOND = 1000;
50 const uint32_t LOCATION_DAY_OR_SEC = 2;
51 const uint32_t TIME_THRESHOLD = 3; // seconds
52 int64_t NitzUpdate::lastSystemTime_ = 0;
53 int32_t NitzUpdate::offset_ = 0;
54 int64_t NitzUpdate::lastNetworkTime_ = 0;
55 std::string NitzUpdate::timeZone_ = "";
56 
NitzUpdate(std::weak_ptr<NetworkSearchManager> networkSearchManager,int32_t slotId)57 NitzUpdate::NitzUpdate(std::weak_ptr<NetworkSearchManager> networkSearchManager, int32_t slotId)
58     : networkSearchManager_(networkSearchManager), slotId_(slotId)
59 {}
60 
ProcessNitzUpdate(const AppExecFwk::InnerEvent::Pointer & event)61 void NitzUpdate::ProcessNitzUpdate(const AppExecFwk::InnerEvent::Pointer &event)
62 {
63     if (event == nullptr) {
64         TELEPHONY_LOGE("NitzUpdate::ProcessNitzUpdate event is nullptr slotId:%{public}d", slotId_);
65         return;
66     }
67     std::shared_ptr<std::string> strTime = event->GetSharedObject<std::string>();
68     if (strTime->empty()) {
69         TELEPHONY_LOGE("NitzUpdate::ProcessNitzUpdate is nullptr slotId:%{public}d", slotId_);
70         return;
71     }
72 
73     int64_t now = OHOS::MiscServices::TimeServiceClient::GetInstance()->GetBootTimeMs();
74     if ((now / MILLI_TO_BASE - lastSystemTime_) < MAX_UPDATE_TIME) {
75         TELEPHONY_LOGI("NitzUpdate::ProcessNitzUpdate update time slotId:%{public}d", slotId_);
76         return;
77     }
78 
79     TELEPHONY_LOGI(
80         "NitzUpdate::ProcessNitzUpdate get time:%{public}s slotId:%{public}d", strTime.get()->c_str(), slotId_);
81     NetworkTime networkTime;
82     (void)memset_s(&networkTime, sizeof(NetworkTime), 0, sizeof(NetworkTime));
83     if (NitzParse(*strTime, networkTime)) {
84         ProcessTime(networkTime);
85         offset_ = networkTime.offset;
86         ProcessTimeZone();
87     }
88 }
89 
NitzParse(std::string & nitzStr,NetworkTime & networkTime)90 bool NitzUpdate::NitzParse(std::string &nitzStr, NetworkTime &networkTime)
91 {
92     std::string strSep = ",";
93     std::string strDateSubs = "";
94     std::string strTimeSubs = "";
95     std::vector<std::string> strsRet;
96     SplitStr(nitzStr, strSep, strsRet);
97     if (static_cast<uint32_t>(strsRet.size()) < static_cast<uint32_t>(TIMEZONE_SPLIT_NUM)) {
98         TELEPHONY_LOGE("NitzUpdate::NitzParse nitz string error slotId:%{public}d", slotId_);
99         return false;
100     }
101     strDateSubs = strsRet[0];
102     strTimeSubs = strsRet[1];
103 
104     strsRet.clear();
105     strSep = "/";
106     SplitStr(strDateSubs, strSep, strsRet);
107     if (static_cast<uint32_t>(strsRet.size()) != static_cast<uint32_t>(TIME_SPLIT_NUM)) {
108         TELEPHONY_LOGE("NitzUpdate::NitzParse date string error slotId:%{public}d", slotId_);
109         return false;
110     }
111     std::string strYear = strsRet[0];
112     if (strYear.length() != YEAR_LENGTH_TWO && strYear.length() != YEAR_LENGTH_FOUR) {
113         TELEPHONY_LOGE("NitzUpdate::NitzParse year string length error slotId:%{public}d", slotId_);
114         return false;
115     }
116     if (strYear.length() == YEAR_LENGTH_TWO) {
117         strYear = "20" + strYear;
118     }
119     StrToInt(strYear, networkTime.year);
120     StrToInt(strsRet[1], networkTime.month);
121     StrToInt(strsRet[LOCATION_DAY_OR_SEC], networkTime.day);
122 
123     if (!NitzTimeParse(strTimeSubs, networkTime)) {
124         return false;
125     }
126     return true;
127 }
128 
NitzTimeParse(std::string & strTimeSubs,NetworkTime & networkTime)129 bool NitzUpdate::NitzTimeParse(std::string &strTimeSubs, NetworkTime &networkTime)
130 {
131     int32_t flag = 1;
132     std::string strSep = "+";
133     std::string::size_type posPositive = strTimeSubs.find(strSep);
134     strSep = "-";
135     std::string::size_type posNegative = strTimeSubs.find(strSep);
136     if (posPositive != std::string::npos) {
137         strSep = "+";
138     } else if (posNegative != std::string::npos) {
139         strSep = "-";
140         flag = -1;
141     } else {
142         TELEPHONY_LOGE("NitzUpdate::NitzTimeParse time string error %{public}s slotId:%{public}d",
143             strTimeSubs.c_str(), slotId_);
144         return false;
145     }
146 
147     std::vector<std::string> strsRet;
148     SplitStr(strTimeSubs, strSep, strsRet);
149     if (strsRet.size() != TIMEZONE_SPLIT_NUM) {
150         TELEPHONY_LOGE("NitzUpdate::NitzTimeParse time error slotId:%{public}d", slotId_);
151         return false;
152     }
153     strTimeSubs = strsRet[0];
154     StrToInt(strsRet[1], networkTime.offset);
155     networkTime.offset = networkTime.offset * flag;
156 
157     strSep = ":";
158     strsRet.clear();
159     SplitStr(strTimeSubs, strSep, strsRet);
160     if (strsRet.size() != TIME_SPLIT_NUM) {
161         TELEPHONY_LOGE("NitzUpdate::NitzTimeParse time vector error slotId:%{public}d", slotId_);
162         return false;
163     }
164     StrToInt(strsRet[0], networkTime.hour);
165     StrToInt(strsRet[1], networkTime.minute);
166     StrToInt(strsRet[LOCATION_DAY_OR_SEC], networkTime.second);
167 
168     return true;
169 }
170 
ProcessTime(NetworkTime & networkTime)171 void NitzUpdate::ProcessTime(NetworkTime &networkTime)
172 {
173     bool autoTime = IsAutoTime();
174     if (!autoTime) {
175         TELEPHONY_LOGI("NitzUpdate::ProcessTime not auto udpate time slotId:%{public}d", slotId_);
176     }
177     if (networkTime.year < static_cast<int32_t>(CST_YEAR) || networkTime.month < 1) {
178         TELEPHONY_LOGE("NitzUpdate::ProcessTime time error slotId:%{public}d", slotId_);
179         return;
180     }
181 
182     auto &powerMgrClient = PowerMgrClient::GetInstance();
183     auto runningLock = powerMgrClient.CreateRunningLock("runninglock", RunningLockType::RUNNINGLOCK_BACKGROUND);
184     if (runningLock != nullptr) {
185         runningLock->Lock();
186     }
187 
188     struct tm t;
189     (void)memset_s(&t, sizeof(t), 0, sizeof(t));
190     t.tm_year = networkTime.year - CST_YEAR;
191     t.tm_mon = networkTime.month - 1;
192     t.tm_mday = networkTime.day;
193     t.tm_hour = networkTime.hour;
194     t.tm_min = networkTime.minute;
195     t.tm_sec = networkTime.second;
196 
197     if (!IsValidTime(static_cast<int64_t>(timegm(&t)))) {
198         TELEPHONY_LOGE("NitzUpdate::ProcessTime invalid time, slotId:%{public}d", slotId_);
199         return;
200     }
201 
202     SaveTime(static_cast<int64_t>(timegm(&t)));
203     if (runningLock != nullptr) {
204         runningLock->UnLock();
205     }
206 }
207 
IsValidTime(int64_t networkTime)208 bool NitzUpdate::IsValidTime(int64_t networkTime)
209 {
210     int64_t currentSystemTime = OHOS::MiscServices::TimeServiceClient::GetInstance()->GetBootTimeMs();
211     if (currentSystemTime <= 0) {
212         TELEPHONY_LOGE("NitzUpdate::IsValidTime current system time is invalid");
213         return false;
214     }
215     currentSystemTime = currentSystemTime / MILLI_TO_BASE;
216     if (lastSystemTime_ == 0 && lastNetworkTime_ == 0) {
217         lastSystemTime_ = currentSystemTime;
218         lastNetworkTime_ = networkTime;
219         return true;
220     }
221 
222     // The difference between the two NITZ times and the elapsed time should be within the threshold
223     int64_t networkTimeInterval = networkTime - lastNetworkTime_;
224     int64_t systemElapsedTime = currentSystemTime - lastSystemTime_;
225     if (abs(networkTimeInterval - systemElapsedTime) > TIME_THRESHOLD) {
226         TELEPHONY_LOGE(
227             "NitzUpdate::IsValidTime The gap between the network time interval and the system elapsed time interval "
228             "is large and will not be processed, slotId:%{public}d",
229             slotId_);
230         return false;
231     }
232 
233     lastSystemTime_ = currentSystemTime;
234     lastNetworkTime_ = networkTime;
235 
236     return true;
237 }
238 
ProcessTimeZone()239 void NitzUpdate::ProcessTimeZone()
240 {
241     bool autoTimezone = IsAutoTimeZone();
242     if (!autoTimezone) {
243         TELEPHONY_LOGI("NitzUpdate::ProcessTimeZone not auto udpate timezone slotId:%{public}d", slotId_);
244     }
245     std::shared_ptr<NetworkSearchManager> nsm = networkSearchManager_.lock();
246     if (nsm == nullptr) {
247         TELEPHONY_LOGE("failed to get NetworkSearchManager slotId:%{public}d", slotId_);
248         return;
249     }
250     int32_t primarySlotId = INVALID_VALUE;
251     CoreManagerInner::GetInstance().GetPrimarySlotId(primarySlotId);
252     if (primarySlotId == INVALID_VALUE) {
253         TELEPHONY_LOGI("primarySlotId %{public}d is invalid slotId:%{public}d", primarySlotId, slotId_);
254         return;
255     }
256     std::u16string iso;
257     nsm->GetIsoCountryCodeForNetwork(primarySlotId, iso);
258     std::string countryCode = Str16ToStr8(iso);
259     if (countryCode.empty()) {
260         TELEPHONY_LOGE("NitzUpdate::ProcessTimeZone countryCode is null slotId:%{public}d", slotId_);
261         return;
262     }
263 
264     OHOS::Global::I18n::ZoneUtil util;
265     std::string timeZone = util.GetDefaultZone(countryCode.c_str());
266     if (timeZone.empty()) {
267         int32_t offset = ONE_HOUR_TO_SECOND * ONE_SECOND_TO_MILLISECOND * offset_;
268         timeZone = util.GetDefaultZone(countryCode.c_str(), offset);
269     }
270     if (timeZone.empty()) {
271         TELEPHONY_LOGE("failed to get zone slotId:%{public}d", slotId_);
272         return;
273     }
274 
275     SaveTimeZone(timeZone);
276 }
277 
SaveTimeZone(std::string & timeZone)278 void NitzUpdate::SaveTimeZone(std::string &timeZone)
279 {
280     std::string lastTimeZone = OHOS::MiscServices::TimeServiceClient::GetInstance()->GetTimeZone();
281     if (timeZone == lastTimeZone) {
282         TELEPHONY_LOGI("NitzUpdate::SaveTimeZone timezone[%{public}s] is the same as lastTimeZone slotId:%{public}d",
283             timeZone.c_str(), slotId_);
284         return;
285     }
286 
287     timeZone_ = timeZone;
288     bool result = OHOS::MiscServices::TimeServiceClient::GetInstance()->SetTimeZone(timeZone);
289     TELEPHONY_LOGI("NitzUpdate::SaveTimeZone result:%{public}d timezone:%{public}s slotId:%{public}d",
290         result, timeZone.c_str(), slotId_);
291 
292     std::string param = "time-zone";
293     AAFwk::Want want;
294     want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_NITZ_TIMEZONE_CHANGED);
295     want.SetParam(param, timeZone);
296     PublishCommonEvent(want);
297 }
298 
SaveTime(int64_t networkTime)299 void NitzUpdate::SaveTime(int64_t networkTime)
300 {
301     TELEPHONY_LOGI("NitzUpdate::SaveTime networkTime:(%{public}" PRId64 ") slotId:%{public}d", networkTime, slotId_);
302     auto &powerMgrClient = PowerMgrClient::GetInstance();
303     auto runningLock = powerMgrClient.CreateRunningLock("runninglock", RunningLockType::RUNNINGLOCK_BACKGROUND);
304     if (runningLock != nullptr) {
305         runningLock->Lock();
306     }
307 
308     bool result = OHOS::MiscServices::TimeServiceClient::GetInstance()->SetTime(networkTime * MILLI_TO_BASE);
309     TELEPHONY_LOGI("NitzUpdate::SaveTime result:%{public}d slotId:%{public}d", result, slotId_);
310     if (runningLock != nullptr) {
311         runningLock->UnLock();
312     }
313     std::string param = "time";
314     AAFwk::Want want;
315     want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_NITZ_TIME_CHANGED);
316     want.SetParam(param, static_cast<int64_t>(networkTime));
317     PublishCommonEvent(want);
318 }
319 
IsAutoTimeZone()320 bool NitzUpdate::IsAutoTimeZone()
321 {
322     std::shared_ptr<SettingUtils> settingHelper = SettingUtils::GetInstance();
323     if (settingHelper == nullptr) {
324         TELEPHONY_LOGI("settingHelper is null");
325         return false;
326     }
327     Uri uri(SettingUtils::NETWORK_SEARCH_SETTING_AUTO_TIMEZONE_URI);
328     std::string key = SettingUtils::SETTINGS_NETWORK_SEARCH_AUTO_TIMEZONE;
329     std::string value = "";
330     if (!settingHelper->Query(uri, key, value)) {
331         TELEPHONY_LOGI("Query %{public}s fail", key.c_str());
332         return false;
333     }
334     bool autoTimezone = value == "1";
335     TELEPHONY_LOGI("NitzUpdate::IsAutoTimeZone autoTimezone:%{public}d slotId:%{public}d", autoTimezone, slotId_);
336     return autoTimezone;
337 }
338 
IsAutoTime()339 bool NitzUpdate::IsAutoTime()
340 {
341     std::shared_ptr<SettingUtils> settingHelper = SettingUtils::GetInstance();
342     if (settingHelper == nullptr) {
343         TELEPHONY_LOGI("settingHelper is null");
344         return false;
345     }
346     Uri uri(SettingUtils::NETWORK_SEARCH_SETTING_AUTO_TIME_URI);
347     std::string key = SettingUtils::SETTINGS_NETWORK_SEARCH_AUTO_TIME;
348     std::string value = "";
349     if (!settingHelper->Query(uri, key, value)) {
350         TELEPHONY_LOGI("Query %{public}s fail", key.c_str());
351         return false;
352     }
353     bool autoTime = value == "1";
354     TELEPHONY_LOGI("NitzUpdate::IsAutoTime autoTime:%{public}d slotId:%{public}d", autoTime, slotId_);
355     return autoTime;
356 }
357 
PublishCommonEvent(AAFwk::Want & want)358 void NitzUpdate::PublishCommonEvent(AAFwk::Want &want)
359 {
360     CommonEventData data;
361     data.SetWant(want);
362 
363     bool stickty = true;
364     CommonEventPublishInfo publishInfo;
365     publishInfo.SetSticky(stickty);
366     bool publishResult = CommonEventManager::PublishCommonEvent(data, publishInfo, nullptr);
367     if (!publishResult) {
368         TELEPHONY_LOGE("NitzUpdate::PublishCommonEvent result:%{public}d slotId:%{public}d", publishResult, slotId_);
369     }
370 }
371 
AutoTimeChange()372 void NitzUpdate::AutoTimeChange()
373 {
374     bool autoTime = IsAutoTime();
375     if (!autoTime) {
376         return;
377     }
378     TELEPHONY_LOGI("now update autoTime:%{public}d slotId:%{public}d", autoTime, slotId_);
379     int64_t time = OHOS::MiscServices::TimeServiceClient::GetInstance()->GetBootTimeMs();
380     if (lastNetworkTime_ == 0 || lastSystemTime_ == 0 || time < lastSystemTime_) {
381         return;
382     }
383     SaveTime(lastNetworkTime_ + (time - lastSystemTime_));
384 }
385 
AutoTimeZoneChange()386 void NitzUpdate::AutoTimeZoneChange()
387 {
388     bool autoTimezone = IsAutoTimeZone();
389     if (!autoTimezone) {
390         return;
391     }
392     TELEPHONY_LOGI("now update autoTimezone slotId:%{public}d, timeZone_:%{public}s", slotId_, timeZone_.c_str());
393     if (timeZone_.empty()) {
394         return;
395     }
396     SaveTimeZone(timeZone_);
397 }
398 } // namespace Telephony
399 } // namespace OHOS
400