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