• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #ifdef FEATURE_GEOCODE_SUPPORT
17 #include "geo_convert_service.h"
18 #include <file_ex.h>
19 #include <thread>
20 #include "ability_connect_callback_interface.h"
21 #include "ability_connect_callback_stub.h"
22 #include "ability_manager_client.h"
23 #include "geo_address.h"
24 #include "common_utils.h"
25 #include "location_config_manager.h"
26 #include "location_dumper.h"
27 #include "location_sa_load_manager.h"
28 #include "system_ability_definition.h"
29 
30 namespace OHOS {
31 namespace Location {
32 const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(
33     DelayedSingleton<GeoConvertService>::GetInstance().get());
34 static constexpr int REQUEST_GEOCODE = 1;
35 static constexpr int REQUEST_REVERSE_GEOCODE = 2;
36 constexpr uint32_t WAIT_MS = 100;
37 const int MAX_RETRY_COUNT = 5;
GeoConvertService()38 GeoConvertService::GeoConvertService() : SystemAbility(LOCATION_GEO_CONVERT_SA_ID, true)
39 {
40     LBSLOGI(GEO_CONVERT, "GeoConvertService constructed.");
41 }
42 
~GeoConvertService()43 GeoConvertService::~GeoConvertService()
44 {
45 }
46 
OnStart()47 void GeoConvertService::OnStart()
48 {
49     if (state_ == ServiceRunningState::STATE_RUNNING) {
50         LBSLOGI(GEO_CONVERT, "GeoConvertService has already started.");
51         return;
52     }
53     if (!Init()) {
54         LBSLOGE(GEO_CONVERT, "failed to init GeoConvertService");
55         OnStop();
56         return;
57     }
58     state_ = ServiceRunningState::STATE_RUNNING;
59     LBSLOGI(GEO_CONVERT, "GeoConvertService::OnStart start service success.");
60 }
61 
OnStop()62 void GeoConvertService::OnStop()
63 {
64     state_ = ServiceRunningState::STATE_NOT_START;
65     registerToService_ = false;
66     LBSLOGI(GEO_CONVERT, "GeoConvertService::OnStop service stopped.");
67 }
68 
Init()69 bool GeoConvertService::Init()
70 {
71     if (!registerToService_) {
72         bool ret = Publish(AsObject());
73         if (!ret) {
74             LBSLOGE(GEO_CONVERT, "GeoConvertService::Init Publish failed!");
75             return false;
76         }
77         registerToService_ = true;
78     }
79     return true;
80 }
81 
82 class AbilityConnection : public AAFwk::AbilityConnectionStub {
83 public:
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)84     void OnAbilityConnectDone(
85         const AppExecFwk::ElementName& element, const sptr<IRemoteObject>& remoteObject, int resultCode) override
86     {
87         std::string uri = element.GetURI();
88         LBSLOGD(GEO_CONVERT, "Connected uri is %{public}s, result is %{public}d.", uri.c_str(), resultCode);
89         if (resultCode != ERR_OK) {
90             return;
91         }
92         DelayedSingleton<GeoConvertService>::GetInstance().get()->NotifyConnected(remoteObject);
93     }
94 
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int)95     void OnAbilityDisconnectDone(const AppExecFwk::ElementName& element, int) override
96     {
97         std::string uri = element.GetURI();
98         LBSLOGD(GEO_CONVERT, "Disconnected uri is %{public}s.", uri.c_str());
99         DelayedSingleton<GeoConvertService>::GetInstance().get()->NotifyDisConnected();
100     }
101 };
102 
ReConnectService()103 bool GeoConvertService::ReConnectService()
104 {
105     int retryCount = 0;
106     if (IsConnect()) {
107         LBSLOGI(GEO_CONVERT, "Connect success!");
108         return true;
109     }
110     while (retryCount < MAX_RETRY_COUNT) {
111         retryCount++;
112         bool ret = ConnectService();
113         if (ret) {
114             LBSLOGI(GEO_CONVERT, "Connect success!");
115             return true;
116         }
117         std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_MS));
118     }
119     return false;
120 }
121 
ConnectService()122 bool GeoConvertService::ConnectService()
123 {
124     LBSLOGD(GEO_CONVERT, "start ConnectService");
125     if (!IsConnect()) {
126         AAFwk::Want connectionWant;
127         std::string serviceName;
128         bool result = LocationConfigManager::GetInstance().GetGeocodeServiceName(serviceName);
129         if (!result || serviceName.empty()) {
130             LBSLOGE(GEO_CONVERT, "get service name failed!");
131             return false;
132         }
133         std::string abilityName;
134         bool res = LocationConfigManager::GetInstance().GetGeocodeAbilityName(abilityName);
135         if (!res || abilityName.empty()) {
136             LBSLOGE(GEO_CONVERT, "get service name failed!");
137             return false;
138         }
139         connectionWant.SetElementName(serviceName, abilityName);
140         sptr<AAFwk::IAbilityConnection> conn = new (std::nothrow) AbilityConnection();
141         if (conn == nullptr) {
142             LBSLOGE(GEO_CONVERT, "get connection failed!");
143             return false;
144         }
145         int32_t ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(connectionWant, conn, -1);
146         if (ret != ERR_OK) {
147             LBSLOGE(GEO_CONVERT, "Connect cloud service failed!");
148             return false;
149         }
150         std::unique_lock<std::mutex> uniqueLock(mutex_);
151         auto waitStatus = connectCondition_.wait_for(
152             uniqueLock, std::chrono::seconds(CONNECT_TIME_OUT), [this]() { return serviceProxy_ != nullptr; });
153         if (!waitStatus) {
154             LBSLOGE(GEO_CONVERT, "Connect cloudService timeout!");
155             return false;
156         }
157     }
158     return true;
159 }
160 
NotifyConnected(const sptr<IRemoteObject> & remoteObject)161 void GeoConvertService::NotifyConnected(const sptr<IRemoteObject>& remoteObject)
162 {
163     std::unique_lock<std::mutex> uniqueLock(mutex_);
164     serviceProxy_ = remoteObject;
165     connectCondition_.notify_all();
166 }
167 
NotifyDisConnected()168 void GeoConvertService::NotifyDisConnected()
169 {
170     std::unique_lock<std::mutex> uniqueLock(mutex_);
171     serviceProxy_ = nullptr;
172     connectCondition_.notify_all();
173 }
174 
IsGeoConvertAvailable(MessageParcel & reply)175 int GeoConvertService::IsGeoConvertAvailable(MessageParcel &reply)
176 {
177     std::string serviceName;
178     bool result = LocationConfigManager::GetInstance().GetGeocodeServiceName(serviceName);
179     if (!result || serviceName.empty()) {
180         LBSLOGE(GEO_CONVERT, "get service name failed!");
181         reply.WriteInt32(ERRCODE_SUCCESS);
182         reply.WriteBool(false);
183         return ERRCODE_SUCCESS;
184     }
185     reply.WriteInt32(ERRCODE_SUCCESS);
186     if (!CommonUtils::CheckAppInstalled(serviceName)) { // app is not installed
187         reply.WriteBool(false);
188     } else {
189         reply.WriteBool(true);
190     }
191     return ERRCODE_SUCCESS;
192 }
193 
GetAddressByCoordinate(MessageParcel & data,MessageParcel & reply)194 int GeoConvertService::GetAddressByCoordinate(MessageParcel &data, MessageParcel &reply)
195 {
196     if (mockEnabled_) {
197         ReportAddressMock(data, reply);
198         return ERRCODE_SUCCESS;
199     }
200     if (!GetService()) {
201         reply.WriteInt32(ERRCODE_REVERSE_GEOCODING_FAIL);
202         return ERRCODE_REVERSE_GEOCODING_FAIL;
203     }
204 
205     MessageParcel dataParcel;
206     MessageParcel replyParcel;
207     MessageOption option;
208 
209     if (!WriteInfoToParcel(data, dataParcel, true)) {
210         reply.WriteInt32(ERRCODE_REVERSE_GEOCODING_FAIL);
211         return ERRCODE_REVERSE_GEOCODING_FAIL;
212     }
213     sptr<GeoConvertCallbackHost> callback = new (std::nothrow) GeoConvertCallbackHost();
214     if (callback == nullptr) {
215         LBSLOGE(GEO_CONVERT, "can not get valid callback.");
216         reply.WriteInt32(ERRCODE_REVERSE_GEOCODING_FAIL);
217         return ERRCODE_REVERSE_GEOCODING_FAIL;
218     }
219     dataParcel.WriteRemoteObject(callback->AsObject());
220 
221     if (serviceProxy_ == nullptr) {
222         LBSLOGE(GEO_CONVERT, "serviceProxy is nullptr!");
223         reply.WriteInt32(ERRCODE_REVERSE_GEOCODING_FAIL);
224         return ERRCODE_REVERSE_GEOCODING_FAIL;
225     }
226     int error = serviceProxy_->SendRequest(REQUEST_REVERSE_GEOCODE, dataParcel, replyParcel, option);
227     if (error != ERR_OK) {
228         LBSLOGE(GEO_CONVERT, "SendRequest to cloud service failed.");
229         reply.WriteInt32(ERRCODE_REVERSE_GEOCODING_FAIL);
230         return ERRCODE_REVERSE_GEOCODING_FAIL;
231     }
232     std::list<std::shared_ptr<GeoAddress>> result = callback->GetResult();
233     if (!WriteResultToParcel(result, reply, true)) {
234         return ERRCODE_REVERSE_GEOCODING_FAIL;
235     }
236     return ERRCODE_SUCCESS;
237 }
238 
ReportAddressMock(MessageParcel & data,MessageParcel & reply)239 void GeoConvertService::ReportAddressMock(MessageParcel &data, MessageParcel &reply)
240 {
241     int arraySize = 0;
242     std::vector<std::shared_ptr<GeoAddress>> array;
243     ReverseGeocodeRequest request;
244     request.latitude = data.ReadDouble();
245     request.longitude = data.ReadDouble();
246     request.maxItems = data.ReadInt32();
247     data.ReadInt32(); // locale size
248     request.locale = Str16ToStr8(data.ReadString16());
249     std::unique_lock<std::mutex> lock(mockInfoMutex_, std::defer_lock);
250     lock.lock();
251     for (size_t i = 0; i < mockInfo_.size(); i++) {
252         std::shared_ptr<GeocodingMockInfo> info = mockInfo_[i];
253         if (!CommonUtils::DoubleEqual(request.latitude, info->GetLocation()->latitude) ||
254             !CommonUtils::DoubleEqual(request.longitude, info->GetLocation()->longitude)) {
255             continue;
256         }
257         arraySize++;
258         array.push_back(info->GetGeoAddressInfo());
259     }
260     lock.unlock();
261     reply.WriteInt32(ERRCODE_SUCCESS);
262     if (arraySize > 0) {
263         reply.WriteInt32(arraySize);
264         for (size_t i = 0; i < array.size(); i++) {
265             array[i]->Marshalling(reply);
266         }
267     } else {
268         reply.WriteInt32(0);
269     }
270 }
271 
GetAddressByLocationName(MessageParcel & data,MessageParcel & reply)272 int GeoConvertService::GetAddressByLocationName(MessageParcel &data, MessageParcel &reply)
273 {
274     if (!GetService()) {
275         reply.WriteInt32(ERRCODE_GEOCODING_FAIL);
276         return ERRCODE_GEOCODING_FAIL;
277     }
278 
279     MessageParcel dataParcel;
280     MessageParcel replyParcel;
281     MessageOption option;
282 
283     if (!WriteInfoToParcel(data, dataParcel, false)) {
284         reply.WriteInt32(ERRCODE_GEOCODING_FAIL);
285         return ERRCODE_GEOCODING_FAIL;
286     }
287     sptr<GeoConvertCallbackHost> callback = new (std::nothrow) GeoConvertCallbackHost();
288     if (callback == nullptr) {
289         LBSLOGE(GEO_CONVERT, "can not get valid callback.");
290         reply.WriteInt32(ERRCODE_GEOCODING_FAIL);
291         return ERRCODE_GEOCODING_FAIL;
292     }
293     dataParcel.WriteRemoteObject(callback->AsObject());
294     if (serviceProxy_ == nullptr) {
295         LBSLOGE(GEO_CONVERT, "serviceProxy is nullptr!");
296         reply.WriteInt32(ERRCODE_GEOCODING_FAIL);
297         return ERRCODE_GEOCODING_FAIL;
298     }
299     int error = serviceProxy_->SendRequest(REQUEST_GEOCODE, dataParcel, replyParcel, option);
300     if (error != ERR_OK) {
301         LBSLOGE(GEO_CONVERT, "SendRequest to cloud service failed.");
302         reply.WriteInt32(ERRCODE_GEOCODING_FAIL);
303         return ERRCODE_GEOCODING_FAIL;
304     }
305     std::list<std::shared_ptr<GeoAddress>> result = callback->GetResult();
306     if (!WriteResultToParcel(result, reply, false)) {
307         return ERRCODE_GEOCODING_FAIL;
308     }
309     return ERRCODE_SUCCESS;
310 }
311 
312 /*
313  * get info from data and write to dataParcel.
314  * flag: true for reverse geocoding, false for geocoding.
315  */
WriteInfoToParcel(MessageParcel & data,MessageParcel & dataParcel,bool flag)316 bool GeoConvertService::WriteInfoToParcel(MessageParcel &data, MessageParcel &dataParcel, bool flag)
317 {
318     if (flag) {
319         dataParcel.WriteString16(data.ReadString16()); // locale
320         dataParcel.WriteDouble(data.ReadDouble()); // latitude
321         dataParcel.WriteDouble(data.ReadDouble()); // longitude
322         dataParcel.WriteInt32(data.ReadInt32()); // maxItems
323     } else {
324         dataParcel.WriteString16(data.ReadString16()); // locale
325         dataParcel.WriteString16(data.ReadString16()); // description
326         dataParcel.WriteInt32(data.ReadInt32()); // maxItems
327         dataParcel.WriteDouble(data.ReadDouble()); // minLatitude
328         dataParcel.WriteDouble(data.ReadDouble()); // minLongitude
329         dataParcel.WriteDouble(data.ReadDouble()); // maxLatitude
330         dataParcel.WriteDouble(data.ReadDouble()); // maxLongitude
331     }
332     dataParcel.WriteString16(data.ReadString16()); // bundleName
333     return true;
334 }
335 
336 /*
337  * write result info to reply.
338  * flag: true for reverse geocoding, false for geocoding.
339  */
WriteResultToParcel(const std::list<std::shared_ptr<GeoAddress>> result,MessageParcel & reply,bool flag)340 bool GeoConvertService::WriteResultToParcel(const std::list<std::shared_ptr<GeoAddress>> result,
341     MessageParcel &reply, bool flag)
342 {
343     if (result.size() == 0) {
344         LBSLOGE(GEO_CONVERT, "empty result!");
345         reply.WriteInt32(flag ? ERRCODE_REVERSE_GEOCODING_FAIL : ERRCODE_GEOCODING_FAIL);
346         return false;
347     }
348     reply.WriteInt32(ERRCODE_SUCCESS);
349     reply.WriteInt32(result.size());
350     for (auto iter = result.begin(); iter != result.end(); iter++) {
351         std::shared_ptr<GeoAddress> address = *iter;
352         if (address != nullptr) {
353             address->Marshalling(reply);
354         }
355     }
356     return true;
357 }
358 
GetService()359 bool GeoConvertService::GetService()
360 {
361     if (!IsConnect()) {
362         std::string serviceName;
363         bool result = LocationConfigManager::GetInstance().GetGeocodeServiceName(serviceName);
364         if (!result || serviceName.empty()) {
365             LBSLOGE(GEO_CONVERT, "get service name failed!");
366             return false;
367         }
368         if (!CommonUtils::CheckAppInstalled(serviceName)) { // app is not installed
369             LBSLOGE(GEO_CONVERT, "service is not available.");
370             return false;
371         } else if (!ReConnectService()) {
372             return false;
373         }
374     }
375     return true;
376 }
377 
IsConnect()378 bool GeoConvertService::IsConnect()
379 {
380     std::unique_lock<std::mutex> uniqueLock(mutex_);
381     return serviceProxy_ != nullptr;
382 }
383 
EnableReverseGeocodingMock()384 bool GeoConvertService::EnableReverseGeocodingMock()
385 {
386     LBSLOGD(GEO_CONVERT, "EnableReverseGeocodingMock");
387     mockEnabled_ = true;
388     return true;
389 }
390 
DisableReverseGeocodingMock()391 bool GeoConvertService::DisableReverseGeocodingMock()
392 {
393     LBSLOGD(GEO_CONVERT, "DisableReverseGeocodingMock");
394     mockEnabled_ = false;
395     return true;
396 }
397 
SetReverseGeocodingMockInfo(std::vector<std::shared_ptr<GeocodingMockInfo>> & mockInfo)398 LocationErrCode GeoConvertService::SetReverseGeocodingMockInfo(
399     std::vector<std::shared_ptr<GeocodingMockInfo>>& mockInfo)
400 {
401     LBSLOGD(GEO_CONVERT, "SetReverseGeocodingMockInfo");
402     std::unique_lock<std::mutex> lock(mockInfoMutex_, std::defer_lock);
403     lock.lock();
404     mockInfo_.assign(mockInfo.begin(), mockInfo.end());
405     lock.unlock();
406     return ERRCODE_SUCCESS;
407 }
408 
UnloadGeoConvertSystemAbility()409 void GeoConvertService::UnloadGeoConvertSystemAbility()
410 {
411     auto locationSaLoadManager = DelayedSingleton<LocationSaLoadManager>::GetInstance();
412     if (!CheckIfGeoConvertConnecting() && locationSaLoadManager != nullptr) {
413         locationSaLoadManager->UnloadLocationSa(LOCATION_GEO_CONVERT_SA_ID);
414     }
415 }
416 
CheckIfGeoConvertConnecting()417 bool GeoConvertService::CheckIfGeoConvertConnecting()
418 {
419     return mockEnabled_;
420 }
421 
SaDumpInfo(std::string & result)422 void GeoConvertService::SaDumpInfo(std::string& result)
423 {
424     result += "GeoConvert enable status: false";
425     result += "\n";
426 }
427 
Dump(int32_t fd,const std::vector<std::u16string> & args)428 int32_t GeoConvertService::Dump(int32_t fd, const std::vector<std::u16string>& args)
429 {
430     std::vector<std::string> vecArgs;
431     std::transform(args.begin(), args.end(), std::back_inserter(vecArgs), [](const std::u16string &arg) {
432         return Str16ToStr8(arg);
433     });
434 
435     LocationDumper dumper;
436     std::string result;
437     dumper.GeocodeDump(SaDumpInfo, vecArgs, result);
438     if (!SaveStringToFd(fd, result)) {
439         LBSLOGE(GEO_CONVERT, "Geocode save string to fd failed!");
440         return ERR_OK;
441     }
442     return ERR_OK;
443 }
444 } // namespace Location
445 } // namespace OHOS
446 #endif
447