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