1 /*
2 * Copyright (C) 2022 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 #include "country_code_manager.h"
16 #ifdef TEL_CELLULAR_DATA_ENABLE
17 #include "cellular_data_client.h"
18 #endif
19 #ifdef TEL_CORE_SERVICE_ENABLE
20 #include "core_service_client.h"
21 #endif
22 #ifdef I18N_ENABLE
23 #include "locale_config.h"
24 #endif
25 #include "parameter.h"
26
27 #include "common_event_manager.h"
28 #include "common_event_support.h"
29 #include "common_utils.h"
30 #include "constant_definition.h"
31 #include "country_code.h"
32 #include "location_log.h"
33 #include "locator_impl.h"
34
35 namespace OHOS {
36 namespace Location {
CountryCodeManager()37 CountryCodeManager::CountryCodeManager()
38 {
39 lastCountryByLocation_ = std::make_shared<CountryCode>();
40 lastCountry_ = std::make_shared<CountryCode>();
41 countryCodeCallback_ = std::make_unique<std::map<pid_t, sptr<ICountryCodeCallback>>>();
42 simSubscriber_ = nullptr;
43 networkSubscriber_ = nullptr;
44 SubscribeLocaleConfigEvent();
45 }
46
~CountryCodeManager()47 CountryCodeManager::~CountryCodeManager()
48 {
49 }
50
NotifyAllListener()51 void CountryCodeManager::NotifyAllListener()
52 {
53 std::unique_lock lock(countryCodeCallbackMutex_);
54 if (lastCountry_ == nullptr || countryCodeCallback_ == nullptr) {
55 LBSLOGE(COUNTRY_CODE, "NotifyAllListener cancel, para is invalid");
56 return;
57 }
58 auto country = std::make_shared<CountryCode>(*lastCountry_);
59 for (auto iter = countryCodeCallback_->begin(); iter != countryCodeCallback_->end(); iter++) {
60 sptr<ICountryCodeCallback> callback = (iter->second);
61 if (callback) {
62 callback->OnCountryCodeChange(country);
63 }
64 }
65 }
66
RegisterCountryCodeCallback(const sptr<IRemoteObject> & callback,pid_t uid)67 void CountryCodeManager::RegisterCountryCodeCallback(const sptr<IRemoteObject>& callback, pid_t uid)
68 {
69 std::unique_lock<std::mutex> lock(countryCodeCallbackMutex_, std::defer_lock);
70 lock.lock();
71 if (callback == nullptr || countryCodeCallback_ == nullptr) {
72 LBSLOGE(COUNTRY_CODE, "callback is invalid");
73 lock.unlock();
74 return;
75 }
76
77 sptr<ICountryCodeCallback> countryCodeCallback = iface_cast<ICountryCodeCallback>(callback);
78 if (countryCodeCallback == nullptr) {
79 LBSLOGE(COUNTRY_CODE, "iface_cast ICountryCodeCallback failed!");
80 lock.unlock();
81 return;
82 }
83 countryCodeCallback_->erase(uid);
84 countryCodeCallback_->insert(std::make_pair(uid, countryCodeCallback));
85 LBSLOGD(COUNTRY_CODE, "after uid:%{public}d register, countryCodeCallback_ size:%{public}s",
86 uid, std::to_string(countryCodeCallback_->size()).c_str());
87 if (countryCodeCallback_->size() != 1) {
88 lock.unlock();
89 return;
90 }
91 lock.unlock();
92 SubscribeSimEvent();
93 SubscribeNetworkStatusEvent();
94 }
95
UnregisterCountryCodeCallback(const sptr<IRemoteObject> & callback)96 void CountryCodeManager::UnregisterCountryCodeCallback(const sptr<IRemoteObject>& callback)
97 {
98 std::unique_lock<std::mutex> lock(countryCodeCallbackMutex_, std::defer_lock);
99 lock.lock();
100 if (callback == nullptr || countryCodeCallback_ == nullptr) {
101 LBSLOGE(COUNTRY_CODE, "unregister an invalid callback");
102 lock.unlock();
103 return;
104 }
105 sptr<ICountryCodeCallback> countryCodeCallback = iface_cast<ICountryCodeCallback>(callback);
106 if (countryCodeCallback == nullptr) {
107 LBSLOGE(COUNTRY_CODE, "iface_cast ICountryCodeCallback failed!");
108 lock.unlock();
109 return;
110 }
111
112 pid_t uid = -1;
113 for (auto iter = countryCodeCallback_->begin(); iter != countryCodeCallback_->end(); iter++) {
114 sptr<IRemoteObject> remoteObject = (iter->second)->AsObject();
115 if (remoteObject == callback) {
116 uid = iter->first;
117 break;
118 }
119 }
120 countryCodeCallback_->erase(uid);
121 LBSLOGD(COUNTRY_CODE, "after uid:%{public}d unregister, countryCodeCallback_ size:%{public}s",
122 uid, std::to_string(countryCodeCallback_->size()).c_str());
123 if (countryCodeCallback_->size() != 0) {
124 lock.unlock();
125 return;
126 }
127 lock.unlock();
128 UnsubscribeSimEvent();
129 UnsubscribeNetworkStatusEvent();
130 }
131
IsCountryCodeRegistered()132 bool CountryCodeManager::IsCountryCodeRegistered()
133 {
134 std::unique_lock lock(countryCodeCallbackMutex_);
135 return countryCodeCallback_->size() != 0;
136 }
137
GetCountryCodeByLastLocation()138 std::string CountryCodeManager::GetCountryCodeByLastLocation()
139 {
140 std::string code = "";
141 if (lastCountryByLocation_ == nullptr) {
142 LBSLOGE(COUNTRY_CODE, "lastCountryByLocation_ is nullptr");
143 return code;
144 }
145 if (lastCountryByLocation_->GetCountryCodeStr().empty()) {
146 auto locatorImpl = LocatorImpl::GetInstance();
147 if (locatorImpl) {
148 std::unique_ptr<Location> lastLocation = std::make_unique<Location>();
149 LocationErrCode errorCode = locatorImpl->GetCachedLocationV9(lastLocation);
150 if (errorCode != ERRCODE_SUCCESS) {
151 return code;
152 }
153 code = GetCountryCodeByLocation(lastLocation);
154 lastCountryByLocation_->SetCountryCodeStr(code);
155 }
156 }
157 return lastCountryByLocation_->GetCountryCodeStr();
158 }
159
UpdateCountryCode(std::string countryCode,int type)160 void CountryCodeManager::UpdateCountryCode(std::string countryCode, int type)
161 {
162 if (lastCountry_ == nullptr) {
163 LBSLOGE(COUNTRY_CODE, "lastCountry_ is nullptr");
164 return;
165 }
166 if (lastCountry_->IsMoreReliable(type)) {
167 LBSLOGI(COUNTRY_CODE, "lastCountry_ is more reliable,there is no need to update the data");
168 return;
169 }
170 lastCountry_->SetCountryCodeStr(countryCode);
171 lastCountry_->SetCountryCodeType(type);
172 }
173
UpdateCountryCodeByLocation(std::string countryCode,int type)174 bool CountryCodeManager::UpdateCountryCodeByLocation(std::string countryCode, int type)
175 {
176 if (lastCountryByLocation_ == nullptr) {
177 LBSLOGE(COUNTRY_CODE, "lastCountryByLocation_ is nullptr");
178 return false;
179 }
180 if (lastCountryByLocation_->GetCountryCodeStr() == countryCode) {
181 LBSLOGE(COUNTRY_CODE, "countryCode is same");
182 return false;
183 }
184
185 lastCountryByLocation_->SetCountryCodeStr(countryCode);
186 lastCountryByLocation_->SetCountryCodeType(type);
187 return true;
188 }
189
GetCountryCodeByLocation(const std::unique_ptr<Location> & location)190 std::string CountryCodeManager::GetCountryCodeByLocation(const std::unique_ptr<Location>& location)
191 {
192 if (location == nullptr) {
193 LBSLOGE(COUNTRY_CODE, "GetCountryCodeByLocation location is nullptr");
194 return "";
195 }
196 auto locatorImpl = LocatorImpl::GetInstance();
197 if (locatorImpl == nullptr) {
198 LBSLOGE(COUNTRY_CODE, "locatorImpl is nullptr");
199 return "";
200 }
201 MessageParcel dataParcel;
202 std::list<std::shared_ptr<GeoAddress>> replyList;
203 if (!dataParcel.WriteInterfaceToken(LocatorProxy::GetDescriptor())) {
204 LBSLOGE(COUNTRY_CODE, "write interfaceToken fail!");
205 return "";
206 }
207 dataParcel.WriteString16(Str8ToStr16("en")); // locale
208 dataParcel.WriteDouble(location->GetLatitude()); // latitude
209 dataParcel.WriteDouble(location->GetLongitude()); // longitude
210 dataParcel.WriteInt32(1); // maxItems
211
212 bool isAvailable = false;
213 LocationErrCode errorCode = locatorImpl->IsGeoServiceAvailableV9(isAvailable);
214 if (errorCode != ERRCODE_SUCCESS || !isAvailable) {
215 LBSLOGE(COUNTRY_CODE, "geocode service is not available.");
216 return "";
217 }
218 errorCode = locatorImpl->GetAddressByCoordinateV9(dataParcel, replyList);
219 if (replyList.empty() || errorCode != ERRCODE_SUCCESS) {
220 LBSLOGE(COUNTRY_CODE, "geocode fail.");
221 return "";
222 }
223 return replyList.front()->countryCode_;
224 }
225
GetIsoCountryCode()226 std::shared_ptr<CountryCode> CountryCodeManager::GetIsoCountryCode()
227 {
228 LBSLOGD(COUNTRY_CODE, "CountryCodeManager::GetIsoCountryCode");
229 int type = COUNTRY_CODE_FROM_LOCALE;
230 std::string countryCodeStr8;
231 #if defined(TEL_CORE_SERVICE_ENABLE) && defined(TEL_CELLULAR_DATA_ENABLE)
232 int slotId = Telephony::CellularDataClient::GetInstance().GetDefaultCellularDataSlotId();
233 std::u16string countryCodeForNetwork;
234 DelayedRefSingleton<Telephony::CoreServiceClient>::GetInstance().GetIsoCountryCodeForNetwork(
235 slotId, countryCodeForNetwork);
236 countryCodeStr8 = Str16ToStr8(countryCodeForNetwork);
237 type = COUNTRY_CODE_FROM_NETWORK;
238 #endif
239 if (countryCodeStr8.empty()) {
240 countryCodeStr8 = GetCountryCodeByLastLocation();
241 type = COUNTRY_CODE_FROM_LOCATION;
242 }
243 #if defined(TEL_CORE_SERVICE_ENABLE) && defined(TEL_CELLULAR_DATA_ENABLE)
244 if (countryCodeStr8.empty()) {
245 std::u16string countryCodeForSim;
246 DelayedRefSingleton<Telephony::CoreServiceClient>::GetInstance().GetISOCountryCodeForSim(
247 slotId, countryCodeForSim);
248 countryCodeStr8 = Str16ToStr8(countryCodeForSim);
249 type = COUNTRY_CODE_FROM_SIM;
250 }
251 #endif
252 #ifdef I18N_ENABLE
253 if (countryCodeStr8.empty()) {
254 countryCodeStr8 = Global::I18n::LocaleConfig::GetSystemRegion();
255 type = COUNTRY_CODE_FROM_LOCALE;
256 }
257 #endif
258 // transfer to uppercase
259 transform(countryCodeStr8.begin(), countryCodeStr8.end(), countryCodeStr8.begin(), ::toupper);
260 CountryCode country;
261 country.SetCountryCodeStr(countryCodeStr8);
262 country.SetCountryCodeType(type);
263 if (lastCountry_ && !country.IsSame(*lastCountry_) && !lastCountry_->IsMoreReliable(type)) {
264 UpdateCountryCode(countryCodeStr8, type);
265 NotifyAllListener();
266 }
267 return lastCountry_;
268 }
269
SubscribeSimEvent()270 bool CountryCodeManager::SubscribeSimEvent()
271 {
272 LBSLOGD(COUNTRY_CODE, "SubscribeSimEvent");
273 OHOS::EventFwk::MatchingSkills matchingSkills;
274 matchingSkills.AddEvent(SIM_STATE_CHANGE_ACTION);
275 OHOS::EventFwk::CommonEventSubscribeInfo subscriberInfo(matchingSkills);
276 std::unique_lock<std::mutex> lock(simSubscriberMutex_, std::defer_lock);
277 lock.lock();
278 if (simSubscriber_ == nullptr) {
279 simSubscriber_ = std::make_shared<SimSubscriber>(subscriberInfo);
280 }
281 lock.unlock();
282 bool result = OHOS::EventFwk::CommonEventManager::SubscribeCommonEvent(simSubscriber_);
283 if (!result) {
284 LBSLOGE(COUNTRY_CODE, "SubscribeSimEvent failed.");
285 }
286 return result;
287 }
288
SubscribeNetworkStatusEvent()289 bool CountryCodeManager::SubscribeNetworkStatusEvent()
290 {
291 LBSLOGD(COUNTRY_CODE, "SubscribeNetworkStatusEvent");
292 OHOS::EventFwk::MatchingSkills matchingSkills;
293 matchingSkills.AddEvent(SEARCH_NET_WORK_STATE_CHANGE_ACTION);
294 OHOS::EventFwk::CommonEventSubscribeInfo subscriberInfo(matchingSkills);
295 std::unique_lock<std::mutex> lock(networkSubscriberMutex_, std::defer_lock);
296 lock.lock();
297 if (networkSubscriber_ == nullptr) {
298 networkSubscriber_ = std::make_shared<NetworkSubscriber>(subscriberInfo);
299 }
300 lock.unlock();
301 bool result = OHOS::EventFwk::CommonEventManager::SubscribeCommonEvent(networkSubscriber_);
302 if (!result) {
303 LBSLOGE(COUNTRY_CODE, "SubscribeNetworkStatusEvent failed.");
304 }
305 return result;
306 }
307
SubscribeLocaleConfigEvent()308 bool CountryCodeManager::SubscribeLocaleConfigEvent()
309 {
310 auto eventCallback = [](const char *key, const char *value, void *context) {
311 LBSLOGD(COUNTRY_CODE, "LOCALE_KEY changed");
312 auto manager = DelayedSingleton<CountryCodeManager>::GetInstance();
313 if (manager == nullptr) {
314 LBSLOGE(COUNTRY_CODE, "SubscribeLocaleConfigEvent CountryCodeManager is nullptr");
315 return;
316 }
317 manager->GetIsoCountryCode();
318 };
319
320 int ret = WatchParameter(LOCALE_KEY.c_str(), eventCallback, nullptr);
321 if (ret != SUCCESS) {
322 LBSLOGD(COUNTRY_CODE, "WatchParameter fail");
323 return false;
324 }
325 return true;
326 }
327
UnsubscribeSimEvent()328 bool CountryCodeManager::UnsubscribeSimEvent()
329 {
330 LBSLOGD(COUNTRY_CODE, "UnsubscribeSimEvent");
331 if (simSubscriber_) {
332 return OHOS::EventFwk::CommonEventManager::UnSubscribeCommonEvent(simSubscriber_);
333 }
334 return false;
335 }
336
UnsubscribeNetworkStatusEvent()337 bool CountryCodeManager::UnsubscribeNetworkStatusEvent()
338 {
339 LBSLOGD(COUNTRY_CODE, "UnsubscribeNetworkStatusEvent");
340 if (networkSubscriber_) {
341 OHOS::EventFwk::CommonEventManager::UnSubscribeCommonEvent(networkSubscriber_);
342 }
343 return false;
344 }
345
OnLocationReport(const std::unique_ptr<Location> & location)346 void CountryCodeManager::LocatorCallback::OnLocationReport(const std::unique_ptr<Location>& location)
347 {
348 auto manager = DelayedSingleton<CountryCodeManager>::GetInstance();
349 if (manager == nullptr) {
350 LBSLOGE(COUNTRY_CODE, "OnLocationReport CountryCodeManager is nullptr");
351 return;
352 }
353 if (location == nullptr) {
354 LBSLOGE(COUNTRY_CODE, "OnLocationReport location is nullptr");
355 return;
356 }
357 std::string code = manager->GetCountryCodeByLocation(location);
358 CountryCode country;
359 country.SetCountryCodeStr(code);
360 country.SetCountryCodeType(COUNTRY_CODE_FROM_LOCATION);
361 LBSLOGI(COUNTRY_CODE, "OnLocationReport");
362 if (manager->UpdateCountryCodeByLocation(code, COUNTRY_CODE_FROM_LOCATION)) {
363 LBSLOGI(COUNTRY_CODE, "OnLocationReport,countryCode is change");
364 manager->GetIsoCountryCode();
365 }
366 }
367
OnLocatingStatusChange(const int status)368 void CountryCodeManager::LocatorCallback::OnLocatingStatusChange(const int status)
369 {
370 }
371
OnErrorReport(const int errorCode)372 void CountryCodeManager::LocatorCallback::OnErrorReport(const int errorCode)
373 {
374 }
375
NetworkSubscriber(const OHOS::EventFwk::CommonEventSubscribeInfo & info)376 CountryCodeManager::NetworkSubscriber::NetworkSubscriber(
377 const OHOS::EventFwk::CommonEventSubscribeInfo &info)
378 : CommonEventSubscriber(info)
379 {
380 LBSLOGD(COUNTRY_CODE, "create NetworkSubscriber");
381 }
382
OnReceiveEvent(const OHOS::EventFwk::CommonEventData & event)383 void CountryCodeManager::NetworkSubscriber::OnReceiveEvent(const OHOS::EventFwk::CommonEventData& event)
384 {
385 auto manager = DelayedSingleton<CountryCodeManager>::GetInstance();
386 if (manager == nullptr) {
387 LBSLOGE(COUNTRY_CODE, "CountryCodeManager is nullptr");
388 return;
389 }
390 LBSLOGI(COUNTRY_CODE, "NetworkSubscriber::OnReceiveEvent");
391 manager->GetIsoCountryCode();
392 }
393
SimSubscriber(const OHOS::EventFwk::CommonEventSubscribeInfo & info)394 CountryCodeManager::SimSubscriber::SimSubscriber(
395 const OHOS::EventFwk::CommonEventSubscribeInfo &info)
396 : CommonEventSubscriber(info)
397 {
398 LBSLOGD(COUNTRY_CODE, "create SimSubscriber");
399 }
400
OnReceiveEvent(const OHOS::EventFwk::CommonEventData & event)401 void CountryCodeManager::SimSubscriber::OnReceiveEvent(const OHOS::EventFwk::CommonEventData& event)
402 {
403 auto manager = DelayedSingleton<CountryCodeManager>::GetInstance();
404 if (manager == nullptr) {
405 LBSLOGE(COUNTRY_CODE, "CountryCodeManager is nullptr");
406 return;
407 }
408 LBSLOGI(COUNTRY_CODE, "SimSubscriber::OnReceiveEvent");
409 manager->GetIsoCountryCode();
410 }
411
ReSubscribeEvent()412 void CountryCodeManager::ReSubscribeEvent()
413 {
414 std::unique_lock<std::mutex> lock(countryCodeCallbackMutex_, std::defer_lock);
415 lock.lock();
416 if (countryCodeCallback_->size() <= 0) {
417 LBSLOGD(COUNTRY_CODE, "no valid callback registed, no need to subscribe");
418 lock.unlock();
419 return;
420 }
421 lock.unlock();
422 SubscribeSimEvent();
423 SubscribeNetworkStatusEvent();
424 }
425
ReUnsubscribeEvent()426 void CountryCodeManager::ReUnsubscribeEvent()
427 {
428 std::unique_lock<std::mutex> lock(countryCodeCallbackMutex_, std::defer_lock);
429 lock.lock();
430 if (countryCodeCallback_->size() <= 0) {
431 LBSLOGE(COUNTRY_CODE, "no valid callback registed, no need to unsubscribe");
432 lock.unlock();
433 return;
434 }
435 lock.unlock();
436 UnsubscribeSimEvent();
437 UnsubscribeNetworkStatusEvent();
438 }
439 } // namespace Location
440 } // namespace OHOS
441