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