• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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