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