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