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