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