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