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 "telephony_types.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 NANO_TO_MILLI = 1000000;
44 const int32_t MAX_UPDATE_TIME = 5;
45 const int32_t TIME_STRING_SPLIT_NUM = 2;
46 const uint32_t TIME_SPLIT_NUM = 3;
47 const uint32_t TIMEZONE_SPLIT_NUM = 2;
48 const uint32_t YEAR_LENGTH_TWO = 2;
49 const uint32_t YEAR_LENGTH_FOUR = 4;
50 const uint32_t CST_YEAR = 1900;
51 constexpr int32_t QUARTER_TO_MILLISECOND = 15 * 60 * 1000;
52 const uint32_t LOCATION_DAY_OR_SEC = 2;
53 const int32_t SIM_SLOT_ID_0 = 0;
54 const int32_t SIM_SLOT_ID_1 = 1;
55 const std::string AUTO_TIME_OFF = "0";
56 const std::string AUTO_TIME_ZONE_OFF = "0";
57 const std::string PARAM_TIME_ZONE = "time-zone";
58 constexpr const char* AUTO_TIME_SYSTEM_PARAMETER = "persist.time.auto_time";
59 constexpr const char* AUTO_TIME_STATUS_ON = "ON";
60 int64_t NitzUpdate::lastSystemTime_ = 0;
61 int32_t NitzUpdate::offset_ = 0;
62 int64_t NitzUpdate::lastNetworkTime_ = 0;
63 int64_t NitzUpdate::lastOffsetTime_ = 0;
64 std::string NitzUpdate::timeZone_;
65
NitzUpdate(const std::weak_ptr<NetworkSearchManager> & networkSearchManager,int32_t slotId)66 NitzUpdate::NitzUpdate(const std::weak_ptr<NetworkSearchManager> &networkSearchManager, int32_t slotId)
67 : networkSearchManager_(networkSearchManager), slotId_(slotId)
68 {}
69
ProcessNitzUpdate(const AppExecFwk::InnerEvent::Pointer & event)70 void NitzUpdate::ProcessNitzUpdate(const AppExecFwk::InnerEvent::Pointer &event)
71 {
72 if (event == nullptr) {
73 TELEPHONY_LOGE("NitzUpdate::ProcessNitzUpdate event is nullptr slotId:%{public}d", slotId_);
74 return;
75 }
76 std::shared_ptr<std::string> strTime = event->GetSharedObject<std::string>();
77 if (strTime == nullptr || strTime->empty()) {
78 TELEPHONY_LOGE("NitzUpdate::ProcessNitzUpdate is nullptr slotId:%{public}d", slotId_);
79 return;
80 }
81
82 int64_t now = OHOS::MiscServices::TimeServiceClient::GetInstance()->GetBootTimeMs();
83 if ((now / MILLI_TO_BASE - lastSystemTime_) < MAX_UPDATE_TIME) {
84 TELEPHONY_LOGI("NitzUpdate::ProcessNitzUpdate update time slotId:%{public}d", slotId_);
85 return;
86 }
87
88 TELEPHONY_LOGI(
89 "NitzUpdate::ProcessNitzUpdate get time:%{public}s slotId:%{public}d", strTime.get()->c_str(), slotId_);
90 NetworkTime networkTime = {0};
91 if (NitzParse(*strTime, networkTime)) {
92 ProcessTime(networkTime);
93 if (TELEPHONY_EXT_WRAPPER.updateTimeZoneOffsetExt_ != nullptr) {
94 NitzData nitzData = {0};
95 nitzData.currentMillis = OHOS::MiscServices::TimeServiceClient::GetInstance()->GetWallTimeMs();
96 nitzData.isDST = nitzData_.isDST;
97 nitzData.totalOffset = nitzData_.totalOffset;
98 TELEPHONY_EXT_WRAPPER.updateTimeZoneOffsetExt_(slotId_, nitzData);
99 } else {
100 offset_ = networkTime.offset;
101 ProcessTimeZone();
102 }
103 }
104 }
105
NitzParse(std::string & nitzStr,NetworkTime & networkTime)106 bool NitzUpdate::NitzParse(std::string &nitzStr, NetworkTime &networkTime)
107 {
108 std::string split = ";";
109 std::vector<std::string> str;
110 SplitStr(nitzStr, split, str);
111 int32_t size = static_cast<int32_t>(str.size());
112 if (size != TIME_STRING_SPLIT_NUM) {
113 return false;
114 }
115 std::string nitzInfo = str[0];
116 std::istringstream time(str[1]);
117 time >> nitzRecvTime_;
118 std::string strSep = ",";
119 std::vector<std::string> strsRet;
120 SplitStr(nitzInfo, strSep, strsRet);
121 if (static_cast<uint32_t>(strsRet.size()) < static_cast<uint32_t>(TIMEZONE_SPLIT_NUM)) {
122 TELEPHONY_LOGE("NitzUpdate::NitzParse nitz string error slotId:%{public}d", slotId_);
123 return false;
124 }
125 std::string strDateSubs = strsRet[0];
126 std::string strTimeSubs = strsRet[1];
127 std::string strDstSubs = strsRet[2];
128 strsRet.clear();
129 strSep = "/";
130 SplitStr(strDateSubs, strSep, strsRet);
131 if (static_cast<uint32_t>(strsRet.size()) != static_cast<uint32_t>(TIME_SPLIT_NUM)) {
132 TELEPHONY_LOGE("NitzUpdate::NitzParse date string error slotId:%{public}d", slotId_);
133 return false;
134 }
135 std::string strYear = strsRet[0];
136 if (strYear.length() != YEAR_LENGTH_TWO && strYear.length() != YEAR_LENGTH_FOUR) {
137 TELEPHONY_LOGE("NitzUpdate::NitzParse year string length error slotId:%{public}d", slotId_);
138 return false;
139 }
140 if (strYear.length() == YEAR_LENGTH_TWO) {
141 strYear = "20" + strYear;
142 }
143 StrToInt(strYear, networkTime.year);
144 StrToInt(strsRet[1], networkTime.month);
145 StrToInt(strsRet[LOCATION_DAY_OR_SEC], networkTime.day);
146 if (!NitzTimeParse(strTimeSubs, networkTime)) {
147 return false;
148 }
149 StrToInt(strDstSubs, networkTime.dst);
150 nitzData_.isDST = (networkTime.dst > 0) ? 1 : 0;
151 return true;
152 }
153
NitzTimeParse(std::string & strTimeSubs,NetworkTime & networkTime)154 bool NitzUpdate::NitzTimeParse(std::string &strTimeSubs, NetworkTime &networkTime)
155 {
156 int32_t flag = 1;
157 std::string strSep = "+";
158 std::string::size_type posPositive = strTimeSubs.find(strSep);
159 strSep = "-";
160 std::string::size_type posNegative = strTimeSubs.find(strSep);
161 if (posPositive != std::string::npos) {
162 strSep = "+";
163 } else if (posNegative != std::string::npos) {
164 strSep = "-";
165 flag = -1;
166 } else {
167 TELEPHONY_LOGE("NitzUpdate::NitzParse timezone string error %{public}s slotId:%{public}d",
168 strTimeSubs.c_str(), slotId_);
169 return false;
170 }
171
172 std::vector<std::string> strsRet;
173 SplitStr(strTimeSubs, strSep, strsRet);
174 if (strsRet.size() != TIMEZONE_SPLIT_NUM) {
175 TELEPHONY_LOGE("NitzUpdate::NitzParse timezone error slotId:%{public}d", slotId_);
176 return false;
177 }
178 strTimeSubs = strsRet[0];
179 StrToInt(strsRet[1], networkTime.offset);
180 networkTime.offset = networkTime.offset * flag;
181 nitzData_.totalOffset = networkTime.offset * QUARTER_TO_MILLISECOND;
182
183 strSep = ":";
184 strsRet.clear();
185 SplitStr(strTimeSubs, strSep, strsRet);
186 if (strsRet.size() != TIME_SPLIT_NUM) {
187 TELEPHONY_LOGE("NitzUpdate::NitzParse timezone vector error slotId:%{public}d", slotId_);
188 return false;
189 }
190 StrToInt(strsRet[0], networkTime.hour);
191 StrToInt(strsRet[1], networkTime.minute);
192 StrToInt(strsRet[LOCATION_DAY_OR_SEC], networkTime.second);
193
194 return true;
195 }
196
ProcessTime(NetworkTime & networkTime)197 void NitzUpdate::ProcessTime(NetworkTime &networkTime)
198 {
199 if (networkTime.year < static_cast<int32_t>(CST_YEAR) || networkTime.month < 1) {
200 TELEPHONY_LOGE("NitzUpdate::ProcessTime time error slotId:%{public}d", slotId_);
201 return;
202 }
203 #ifdef ABILITY_POWER_SUPPORT
204 auto &powerMgrClient = PowerMgrClient::GetInstance();
205 auto runningLock = powerMgrClient.CreateRunningLock("runninglock", RunningLockType::RUNNINGLOCK_BACKGROUND_PHONE);
206 if (runningLock != nullptr) {
207 runningLock->Lock();
208 }
209 #endif
210 struct tm t;
211 (void)memset_s(&t, sizeof(t), 0, sizeof(t));
212 t.tm_year = networkTime.year - static_cast<int32_t>(CST_YEAR);
213 t.tm_mon = networkTime.month - 1;
214 t.tm_mday = networkTime.day;
215 t.tm_hour = networkTime.hour;
216 t.tm_min = networkTime.minute;
217 t.tm_sec = networkTime.second;
218 int64_t nitzTime = static_cast<int64_t>(timegm(&t));
219 int64_t currentTime = OHOS::MiscServices::TimeServiceClient::GetInstance()->GetBootTimeNs();
220 int64_t offset = (currentTime - nitzRecvTime_) / NANO_TO_MILLI;
221 if (offset < 0 || offset >= INT64_MAX) {
222 TELEPHONY_LOGE("NitzUpdate::ProcessTime offset invalid, slotId:%{public}d", slotId_);
223 return;
224 }
225 TELEPHONY_LOGI("slotId:%{public}d, currentTime:%{public}lld, offset:%{public}lld, nitzTime:%{public}lld",
226 slotId_, static_cast<long long>(currentTime), static_cast<long long>(offset), static_cast<long long>(nitzTime));
227 bool autoTime = IsAutoTime();
228 if (!autoTime) {
229 TELEPHONY_LOGI("NitzUpdate::ProcessTime not auto udpate time slotId:%{public}d", slotId_);
230 return;
231 }
232 SaveTime(nitzTime, offset);
233 #ifdef ABILITY_POWER_SUPPORT
234 if (runningLock != nullptr) {
235 runningLock->UnLock();
236 }
237 #endif
238 }
239
ProcessTimeZone()240 void NitzUpdate::ProcessTimeZone()
241 {
242 std::shared_ptr<NetworkSearchManager> nsm = networkSearchManager_.lock();
243 if (nsm == nullptr) {
244 TELEPHONY_LOGE("failed to get NetworkSearchManager slotId:%{public}d", slotId_);
245 return;
246 }
247 int32_t primarySlotId = INVALID_VALUE;
248 CoreManagerInner::GetInstance().GetPrimarySlotId(primarySlotId);
249 if (primarySlotId == INVALID_VALUE) {
250 TELEPHONY_LOGI("primarySlotId %{public}d is invalid slotId:%{public}d", primarySlotId, slotId_);
251 return;
252 }
253 std::u16string iso;
254 if (nsm->GetIsoCountryCodeForNetwork(primarySlotId, iso) != TELEPHONY_ERR_SUCCESS) {
255 TELEPHONY_LOGE("failed to get CountryCode slotId:%{public}d", primarySlotId);
256 return;
257 }
258 if (iso.empty()) {
259 int32_t otherSlotId = (primarySlotId == SIM_SLOT_ID_0) ? SIM_SLOT_ID_1 : SIM_SLOT_ID_0;
260 TELEPHONY_LOGI("primarySlotId = %{public}d, otherSlotId = %{public}d", primarySlotId, otherSlotId);
261 nsm->GetIsoCountryCodeForNetwork(otherSlotId, iso);
262 if (!iso.empty()) {
263 primarySlotId = otherSlotId;
264 }
265 }
266 std::string countryCode = Str16ToStr8(iso);
267 if (TELEPHONY_EXT_WRAPPER.updateCountryCodeExt_ != nullptr) {
268 TELEPHONY_EXT_WRAPPER.updateCountryCodeExt_(primarySlotId, countryCode.c_str());
269 } else {
270 UpdateCountryCode(countryCode);
271 }
272 }
273
UpdateCountryCode(std::string & countryCode)274 void NitzUpdate::UpdateCountryCode(std::string &countryCode)
275 {
276 if (countryCode.empty()) {
277 TELEPHONY_LOGE("NitzUpdate::UpdateCountryCode countryCode is null slotId:%{public}d", slotId_);
278 return;
279 }
280 if (!IsAutoTimeZone()) {
281 TELEPHONY_LOGI("NitzUpdate::UpdateCountryCode not auto udpate timezone slotId:%{public}d", slotId_);
282 return;
283 }
284 nitzData_.currentMillis = OHOS::MiscServices::TimeServiceClient::GetInstance()->GetWallTimeMs();
285 Global::I18n::ZoneUtil util;
286 Global::I18n::CountryResult crt = util.LookupTimezoneByCountryAndNITZ(countryCode, nitzData_);
287 SaveTimeZone(crt.timezoneId);
288 }
289
SaveTimeZone(std::string & timeZone)290 void NitzUpdate::SaveTimeZone(std::string &timeZone)
291 {
292 std::string lastTimeZone = OHOS::MiscServices::TimeServiceClient::GetInstance()->GetTimeZone();
293 if (timeZone == lastTimeZone) {
294 TELEPHONY_LOGI("NitzUpdate::SaveTimeZone timezone[%{public}s] is the same as lastTimeZone slotId:%{public}d",
295 timeZone.c_str(), slotId_);
296 return;
297 }
298
299 timeZone_ = timeZone;
300 bool result = OHOS::MiscServices::TimeServiceClient::GetInstance()->SetTimeZone(timeZone);
301 TELEPHONY_LOGI("NitzUpdate::ProcessTimeZone result:%{public}d timezone:%{public}s slotId:%{public}d", result,
302 timeZone.c_str(), slotId_);
303
304 std::string param = PARAM_TIME_ZONE;
305 AAFwk::Want want;
306 want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_NITZ_TIMEZONE_CHANGED);
307 want.SetParam(param, timeZone);
308 PublishCommonEvent(want);
309 }
310
SaveTime(int64_t networkTime,int64_t offset)311 void NitzUpdate::SaveTime(int64_t networkTime, int64_t offset)
312 {
313 TELEPHONY_LOGI("SaveTime networkTime:(%{public}" PRId64 ") slotId:%{public}d, offset:(%{public}" PRId64 ")",
314 networkTime, slotId_, offset);
315 #ifdef ABILITY_POWER_SUPPORT
316 auto &powerMgrClient = PowerMgrClient::GetInstance();
317 auto runningLock = powerMgrClient.CreateRunningLock("runninglock", RunningLockType::RUNNINGLOCK_BACKGROUND_PHONE);
318 if (runningLock != nullptr) {
319 runningLock->Lock();
320 }
321 #endif
322 int64_t ntpTime = 0;
323 auto ret = OHOS::MiscServices::TimeServiceClient::GetInstance()->GetRealTimeMs(ntpTime);
324 if (ret != ERR_OK || ntpTime == 0) {
325 bool result = OHOS::MiscServices::TimeServiceClient::GetInstance()->SetTime(
326 networkTime * MILLI_TO_BASE + offset);
327 TELEPHONY_LOGI("NitzUpdate::ProcessTime result:%{public}d slotId:%{public}d", result, slotId_);
328 std::string param = "time";
329 AAFwk::Want want;
330 want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_NITZ_TIME_CHANGED);
331 want.SetParam(param, static_cast<int64_t>(networkTime));
332 PublishCommonEvent(want);
333 } else {
334 TELEPHONY_LOGI("NitzUpdate::ProcessTime ntp time valid! slotId:%{public}d", slotId_);
335 }
336 #ifdef ABILITY_POWER_SUPPORT
337 if (runningLock != nullptr) {
338 runningLock->UnLock();
339 }
340 #endif
341 }
342
IsAutoTimeZone()343 bool NitzUpdate::IsAutoTimeZone()
344 {
345 std::shared_ptr<SettingUtils> settingHelper = SettingUtils::GetInstance();
346 if (settingHelper == nullptr) {
347 TELEPHONY_LOGI("settingHelper is null");
348 return false;
349 }
350 Uri uri(SettingUtils::NETWORK_SEARCH_SETTING_AUTO_TIMEZONE_URI);
351 std::string key = SettingUtils::SETTINGS_NETWORK_SEARCH_AUTO_TIMEZONE;
352 std::string value;
353 if (settingHelper->Query(uri, key, value) != TELEPHONY_SUCCESS) {
354 TELEPHONY_LOGI("Query %{public}s fail", key.c_str());
355 return false;
356 }
357 bool autoTimezone = true;
358 if (value == AUTO_TIME_ZONE_OFF) {
359 autoTimezone = false;
360 }
361 TELEPHONY_LOGI("NitzUpdate::IsAutoTimeZone autoTimezone:%{public}d slotId:%{public}d", autoTimezone, slotId_);
362 return autoTimezone;
363 }
364
IsAutoTime()365 bool NitzUpdate::IsAutoTime()
366 {
367 std::shared_ptr<SettingUtils> settingHelper = SettingUtils::GetInstance();
368 if (settingHelper == nullptr) {
369 TELEPHONY_LOGI("settingHelper is null");
370 return false;
371 }
372 Uri uri(SettingUtils::NETWORK_SEARCH_SETTING_AUTO_TIME_URI);
373 std::string key = SettingUtils::SETTINGS_NETWORK_SEARCH_AUTO_TIME;
374 std::string value = "";
375 if (settingHelper->Query(uri, key, value) != TELEPHONY_SUCCESS) {
376 TELEPHONY_LOGI("Query %{public}s fail", key.c_str());
377 if (system::GetParameter(AUTO_TIME_SYSTEM_PARAMETER, "ON") == AUTO_TIME_STATUS_ON) {
378 return true;
379 }
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_), lastOffsetTime_);
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