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_stub.h"
21 #include "ability_manager_client.h"
22 #include "geo_address.h"
23 #include "geo_convert_request.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 GeoConvertService::GetInstance());
34 const uint32_t EVENT_SEND_GEOREQUEST = 0x0100;
35 const char* UNLOAD_GEOCONVERT_TASK = "geoconvert_sa_unload";
36 const int GEOCONVERT_CONNECT_TIME_OUT = 1;
37 const uint32_t EVENT_INTERVAL_UNITE = 1000;
38 const int UNLOAD_GEOCONVERT_DELAY_TIME = 5 * EVENT_INTERVAL_UNITE;
GetInstance()39 GeoConvertService* GeoConvertService::GetInstance()
40 {
41 static GeoConvertService data;
42 return &data;
43 }
44
GeoConvertService()45 GeoConvertService::GeoConvertService() : SystemAbility(LOCATION_GEO_CONVERT_SA_ID, true)
46 {
47 geoConvertHandler_ =
48 std::make_shared<GeoConvertHandler>(AppExecFwk::EventRunner::Create(true, AppExecFwk::ThreadMode::FFRT));
49 LBSLOGI(GEO_CONVERT, "GeoConvertService constructed.");
50 }
51
~GeoConvertService()52 GeoConvertService::~GeoConvertService()
53 {
54 if (geoConvertHandler_ != nullptr) {
55 geoConvertHandler_->RemoveTask(UNLOAD_GEOCONVERT_TASK);
56 }
57 conn_ = nullptr;
58 }
59
OnStart()60 void GeoConvertService::OnStart()
61 {
62 if (state_ == ServiceRunningState::STATE_RUNNING) {
63 LBSLOGI(GEO_CONVERT, "GeoConvertService has already started.");
64 return;
65 }
66 if (!Init()) {
67 LBSLOGE(GEO_CONVERT, "failed to init GeoConvertService");
68 OnStop();
69 return;
70 }
71 state_ = ServiceRunningState::STATE_RUNNING;
72 LBSLOGI(GEO_CONVERT, "GeoConvertService::OnStart start service success.");
73 }
74
OnStop()75 void GeoConvertService::OnStop()
76 {
77 state_ = ServiceRunningState::STATE_NOT_START;
78 registerToService_ = false;
79 if (conn_ != nullptr) {
80 AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(conn_);
81 LBSLOGD(GEO_CONVERT, "GeoConvertService::OnStop and disconnect");
82 UnRegisterGeoServiceDeathRecipient();
83 SetServiceConnectState(ServiceConnectState::STATE_DISCONNECT);
84 }
85 LBSLOGI(GEO_CONVERT, "GeoConvertService::OnStop service stopped.");
86 }
87
Init()88 bool GeoConvertService::Init()
89 {
90 if (!registerToService_) {
91 bool ret = Publish(AsObject());
92 if (!ret) {
93 LBSLOGE(GEO_CONVERT, "GeoConvertService::Init Publish failed!");
94 return false;
95 }
96 registerToService_ = true;
97 }
98 return true;
99 }
100
101 class AbilityConnection : public AAFwk::AbilityConnectionStub {
102 public:
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)103 void OnAbilityConnectDone(
104 const AppExecFwk::ElementName& element, const sptr<IRemoteObject>& remoteObject, int resultCode) override
105 {
106 std::string uri = element.GetURI();
107 LBSLOGD(GEO_CONVERT, "Connected uri is %{public}s, result is %{public}d.", uri.c_str(), resultCode);
108 if (resultCode != ERR_OK) {
109 return;
110 }
111 GeoConvertService::GetInstance()->NotifyConnected(remoteObject);
112 }
113
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int)114 void OnAbilityDisconnectDone(const AppExecFwk::ElementName& element, int) override
115 {
116 std::string uri = element.GetURI();
117 LBSLOGD(GEO_CONVERT, "Disconnected uri is %{public}s.", uri.c_str());
118 GeoConvertService::GetInstance()->NotifyDisConnected();
119 }
120 };
121
ConnectService()122 bool GeoConvertService::ConnectService()
123 {
124 LBSLOGD(GEO_CONVERT, "start ConnectService");
125 AAFwk::Want connectionWant;
126 std::string serviceName;
127 bool result = LocationConfigManager::GetInstance()->GetGeocodeServiceName(serviceName);
128 if (!result || serviceName.empty()) {
129 LBSLOGE(GEO_CONVERT, "get service name failed!");
130 return false;
131 }
132 std::string abilityName;
133 bool res = LocationConfigManager::GetInstance()->GetGeocodeAbilityName(abilityName);
134 if (!res || abilityName.empty()) {
135 LBSLOGE(GEO_CONVERT, "get service name failed!");
136 return false;
137 }
138 connectionWant.SetElementName(serviceName, abilityName);
139 conn_ = sptr<AAFwk::IAbilityConnection>(new (std::nothrow) AbilityConnection());
140 if (conn_ == nullptr) {
141 LBSLOGE(GEO_CONVERT, "get connection failed!");
142 return false;
143 }
144 SetServiceConnectState(ServiceConnectState::STATE_CONNECTTING);
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 =
152 connectCondition_.wait_for(uniqueLock,
153 std::chrono::seconds(GEOCONVERT_CONNECT_TIME_OUT), [this]() { return serviceProxy_ != nullptr; });
154 if (!waitStatus) {
155 LBSLOGE(GEO_CONVERT, "Connect cloudService timeout!");
156 SetServiceConnectState(ServiceConnectState::STATE_DISCONNECT);
157 return false;
158 }
159 SetServiceConnectState(ServiceConnectState::STATE_CONNECTTED);
160 RegisterGeoServiceDeathRecipient();
161 return true;
162 }
163
NotifyConnected(const sptr<IRemoteObject> & remoteObject)164 void GeoConvertService::NotifyConnected(const sptr<IRemoteObject>& remoteObject)
165 {
166 std::unique_lock<std::mutex> uniqueLock(mutex_);
167 serviceProxy_ = remoteObject;
168 connectCondition_.notify_all();
169 }
170
NotifyDisConnected()171 void GeoConvertService::NotifyDisConnected()
172 {
173 std::unique_lock<std::mutex> uniqueLock(mutex_);
174 serviceProxy_ = nullptr;
175 connectCondition_.notify_all();
176 }
177
IsGeoConvertAvailable(MessageParcel & reply)178 int GeoConvertService::IsGeoConvertAvailable(MessageParcel &reply)
179 {
180 std::string serviceName;
181 bool result = LocationConfigManager::GetInstance()->GetGeocodeServiceName(serviceName);
182 if (!result || serviceName.empty()) {
183 LBSLOGE(GEO_CONVERT, "get service name failed!");
184 reply.WriteInt32(ERRCODE_SUCCESS);
185 reply.WriteBool(false);
186 return ERRCODE_SUCCESS;
187 }
188 reply.WriteInt32(ERRCODE_SUCCESS);
189 if (!CommonUtils::CheckAppInstalled(serviceName)) { // app is not installed
190 reply.WriteBool(false);
191 } else {
192 reply.WriteBool(true);
193 }
194 return ERRCODE_SUCCESS;
195 }
196
GetAddressByCoordinate(MessageParcel & data,MessageParcel & reply)197 int GeoConvertService::GetAddressByCoordinate(MessageParcel &data, MessageParcel &reply)
198 {
199 if (mockEnabled_) {
200 ReportAddressMock(data, reply);
201 return ERRCODE_SUCCESS;
202 }
203 if (!GetService()) {
204 reply.WriteInt32(ERRCODE_REVERSE_GEOCODING_FAIL);
205 return ERRCODE_REVERSE_GEOCODING_FAIL;
206 }
207 GeoCodeType requestType = GeoCodeType::REQUEST_REVERSE_GEOCODE;
208 auto geoConvertRequest = GeoConvertRequest::Unmarshalling(data, requestType);
209 AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent::
210 Get(EVENT_SEND_GEOREQUEST, geoConvertRequest);
211 if (geoConvertHandler_ != nullptr) {
212 geoConvertHandler_->SendEvent(event);
213 }
214 return ERRCODE_SUCCESS;
215 }
216
ReportAddressMock(MessageParcel & data,MessageParcel & reply)217 void GeoConvertService::ReportAddressMock(MessageParcel &data, MessageParcel &reply)
218 {
219 int arraySize = 0;
220 std::vector<std::shared_ptr<GeoAddress>> array;
221 ReverseGeocodeRequest request;
222 request.latitude = data.ReadDouble();
223 request.longitude = data.ReadDouble();
224 request.maxItems = data.ReadInt32();
225 data.ReadInt32(); // locale size
226 request.locale = Str16ToStr8(data.ReadString16());
227 std::unique_lock<std::mutex> lock(mockInfoMutex_, std::defer_lock);
228 lock.lock();
229 for (size_t i = 0; i < mockInfo_.size(); i++) {
230 std::shared_ptr<GeocodingMockInfo> info = mockInfo_[i];
231 if (!CommonUtils::DoubleEqual(request.latitude, info->GetLocation()->latitude) ||
232 !CommonUtils::DoubleEqual(request.longitude, info->GetLocation()->longitude)) {
233 continue;
234 }
235 arraySize++;
236 array.push_back(info->GetGeoAddressInfo());
237 }
238 lock.unlock();
239 reply.WriteInt32(ERRCODE_SUCCESS);
240 if (arraySize > 0) {
241 reply.WriteInt32(arraySize);
242 for (size_t i = 0; i < array.size(); i++) {
243 array[i]->Marshalling(reply);
244 }
245 } else {
246 reply.WriteInt32(0);
247 }
248 }
249
GetAddressByLocationName(MessageParcel & data,MessageParcel & reply)250 int GeoConvertService::GetAddressByLocationName(MessageParcel &data, MessageParcel &reply)
251 {
252 if (!GetService()) {
253 reply.WriteInt32(ERRCODE_GEOCODING_FAIL);
254 return ERRCODE_GEOCODING_FAIL;
255 }
256 GeoCodeType requestType = GeoCodeType::REQUEST_GEOCODE;
257 auto geoConvertRequest = GeoConvertRequest::Unmarshalling(data, requestType);
258 AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent::
259 Get(EVENT_SEND_GEOREQUEST, geoConvertRequest);
260 if (geoConvertHandler_ != nullptr) {
261 geoConvertHandler_->SendEvent(event);
262 }
263 return ERRCODE_SUCCESS;
264 }
265
GetService()266 bool GeoConvertService::GetService()
267 {
268 if (!IsConnect() && !IsConnecting()) {
269 std::string serviceName;
270 bool result = LocationConfigManager::GetInstance()->GetGeocodeServiceName(serviceName);
271 if (!result || serviceName.empty()) {
272 LBSLOGE(GEO_CONVERT, "get service name failed!");
273 return false;
274 }
275 if (!CommonUtils::CheckAppInstalled(serviceName)) { // app is not installed
276 LBSLOGE(GEO_CONVERT, "service is not available.");
277 return false;
278 } else if (!ConnectService()) {
279 return false;
280 }
281 }
282 return true;
283 }
284
IsConnect()285 bool GeoConvertService::IsConnect()
286 {
287 std::unique_lock<std::mutex> uniqueLock(mutex_);
288 return serviceProxy_ != nullptr &&
289 GetServiceConnectState() == ServiceConnectState::STATE_CONNECTTED;
290 }
291
EnableReverseGeocodingMock()292 bool GeoConvertService::EnableReverseGeocodingMock()
293 {
294 LBSLOGD(GEO_CONVERT, "EnableReverseGeocodingMock");
295 mockEnabled_ = true;
296 return true;
297 }
298
DisableReverseGeocodingMock()299 bool GeoConvertService::DisableReverseGeocodingMock()
300 {
301 LBSLOGD(GEO_CONVERT, "DisableReverseGeocodingMock");
302 mockEnabled_ = false;
303 return true;
304 }
305
SetReverseGeocodingMockInfo(std::vector<std::shared_ptr<GeocodingMockInfo>> & mockInfo)306 LocationErrCode GeoConvertService::SetReverseGeocodingMockInfo(
307 std::vector<std::shared_ptr<GeocodingMockInfo>>& mockInfo)
308 {
309 LBSLOGD(GEO_CONVERT, "SetReverseGeocodingMockInfo");
310 std::unique_lock<std::mutex> lock(mockInfoMutex_, std::defer_lock);
311 lock.lock();
312 mockInfo_.assign(mockInfo.begin(), mockInfo.end());
313 lock.unlock();
314 return ERRCODE_SUCCESS;
315 }
316
CancelIdleState()317 bool GeoConvertService::CancelIdleState()
318 {
319 bool ret = CancelIdle();
320 if (!ret) {
321 LBSLOGE(GEO_CONVERT, "%{public}s cancel idle failed!", __func__);
322 return false;
323 }
324 return true;
325 }
326
UnloadGeoConvertSystemAbility()327 void GeoConvertService::UnloadGeoConvertSystemAbility()
328 {
329 if (geoConvertHandler_ == nullptr) {
330 LBSLOGE(GEO_CONVERT, "%{public}s geoConvertHandler_ is nullptr", __func__);
331 return;
332 }
333 geoConvertHandler_->RemoveTask(UNLOAD_GEOCONVERT_TASK);
334 if (CheckIfGeoConvertConnecting()) {
335 return;
336 }
337 auto task = [this]() {
338 SaLoadWithStatistic::UnInitLocationSa(LOCATION_GEO_CONVERT_SA_ID);
339 GeoConvertService::GetInstance()->DisconnectAbilityConnect();
340 };
341 geoConvertHandler_->PostTask(task, UNLOAD_GEOCONVERT_TASK, UNLOAD_GEOCONVERT_DELAY_TIME);
342 }
343
DisconnectAbilityConnect()344 void GeoConvertService::DisconnectAbilityConnect()
345 {
346 if (conn_ != nullptr) {
347 AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(conn_);
348 SetServiceConnectState(ServiceConnectState::STATE_DISCONNECT);
349 LBSLOGI(GEO_CONVERT, "UnloadGeoConvert OnStop and disconnect");
350 }
351 }
352
CheckIfGeoConvertConnecting()353 bool GeoConvertService::CheckIfGeoConvertConnecting()
354 {
355 return mockEnabled_;
356 }
357
SaDumpInfo(std::string & result)358 void GeoConvertService::SaDumpInfo(std::string& result)
359 {
360 result += "GeoConvert enable status: false";
361 result += "\n";
362 }
363
Dump(int32_t fd,const std::vector<std::u16string> & args)364 int32_t GeoConvertService::Dump(int32_t fd, const std::vector<std::u16string>& args)
365 {
366 std::vector<std::string> vecArgs;
367 std::transform(args.begin(), args.end(), std::back_inserter(vecArgs), [](const std::u16string &arg) {
368 return Str16ToStr8(arg);
369 });
370
371 LocationDumper dumper;
372 std::string result;
373 dumper.GeocodeDump(SaDumpInfo, vecArgs, result);
374 if (!SaveStringToFd(fd, result)) {
375 LBSLOGE(GEO_CONVERT, "Geocode save string to fd failed!");
376 return ERR_OK;
377 }
378 return ERR_OK;
379 }
380
ResetServiceProxy()381 bool GeoConvertService::ResetServiceProxy()
382 {
383 std::unique_lock<std::mutex> uniqueLock(mutex_);
384 serviceProxy_ = nullptr;
385 return true;
386 }
387
RegisterGeoServiceDeathRecipient()388 void GeoConvertService::RegisterGeoServiceDeathRecipient()
389 {
390 if (serviceProxy_ == nullptr) {
391 LBSLOGE(GEO_CONVERT, "%{public}s: geoServiceProxy_ is nullptr", __func__);
392 return;
393 }
394 if (geoServiceRecipient_ != nullptr) {
395 serviceProxy_->AddDeathRecipient(geoServiceRecipient_);
396 }
397 }
398
UnRegisterGeoServiceDeathRecipient()399 void GeoConvertService::UnRegisterGeoServiceDeathRecipient()
400 {
401 std::unique_lock<std::mutex> uniqueLock(mutex_);
402 if (serviceProxy_ == nullptr) {
403 LBSLOGE(GEO_CONVERT, "%{public}s: geoServiceProxy_ is nullptr", __func__);
404 return;
405 }
406 if (geoServiceRecipient_ != nullptr) {
407 serviceProxy_->RemoveDeathRecipient(geoServiceRecipient_);
408 geoServiceRecipient_ = nullptr;
409 }
410 }
411
SendGeocodeRequest(int code,MessageParcel & dataParcel,MessageParcel & replyParcel,MessageOption & option)412 bool GeoConvertService::SendGeocodeRequest(int code, MessageParcel& dataParcel, MessageParcel& replyParcel,
413 MessageOption& option)
414 {
415 std::unique_lock<std::mutex> uniqueLock(mutex_);
416 if (serviceProxy_ == nullptr) {
417 LBSLOGE(GEO_CONVERT, "serviceProxy is nullptr!");
418 return false;
419 }
420 MessageParcel data;
421 data.WriteInterfaceToken(serviceProxy_->GetInterfaceDescriptor());
422 data.Append(dataParcel);
423 int error = serviceProxy_->SendRequest(code, data, replyParcel, option);
424 if (error != ERR_OK) {
425 LBSLOGE(GEO_CONVERT, "SendRequest to cloud service failed. error = %{public}d", error);
426 return false;
427 }
428 return true;
429 }
430
GetServiceConnectState()431 ServiceConnectState GeoConvertService::GetServiceConnectState()
432 {
433 std::unique_lock<std::mutex> uniqueLock(connectStateMutex_);
434 return connectState_;
435 }
436
SetServiceConnectState(ServiceConnectState connectState)437 void GeoConvertService::SetServiceConnectState(ServiceConnectState connectState)
438 {
439 std::unique_lock<std::mutex> uniqueLock(connectStateMutex_);
440 connectState_ = connectState;
441 }
442
IsConnecting()443 bool GeoConvertService::IsConnecting()
444 {
445 std::unique_lock<std::mutex> uniqueLock(connectStateMutex_);
446 return connectState_ == ServiceConnectState::STATE_CONNECTTING;
447 }
448
GeoServiceDeathRecipient()449 GeoServiceDeathRecipient::GeoServiceDeathRecipient()
450 {
451 }
452
~GeoServiceDeathRecipient()453 GeoServiceDeathRecipient::~GeoServiceDeathRecipient()
454 {
455 }
456
OnRemoteDied(const wptr<IRemoteObject> & remote)457 void GeoServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
458 {
459 auto geoConvertService = GeoConvertService::GetInstance();
460 if (geoConvertService != nullptr) {
461 LBSLOGI(GEO_CONVERT, "geo OnRemoteDied");
462 geoConvertService->ResetServiceProxy();
463 geoConvertService->SetServiceConnectState(ServiceConnectState::STATE_DISCONNECT);
464 }
465 }
466
GeoConvertHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner)467 GeoConvertHandler::GeoConvertHandler(const std::shared_ptr<AppExecFwk::EventRunner>& runner) : EventHandler(runner) {}
468
~GeoConvertHandler()469 GeoConvertHandler::~GeoConvertHandler() {}
470
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)471 void GeoConvertHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer& event)
472 {
473 auto geoConvertService = GeoConvertService::GetInstance();
474 if (geoConvertService == nullptr) {
475 LBSLOGE(NETWORK, "ProcessEvent: GeoConvertService is nullptr");
476 return;
477 }
478 uint32_t eventId = event->GetInnerEventId();
479 LBSLOGD(GEO_CONVERT, "ProcessEvent event:%{public}d", eventId);
480 switch (eventId) {
481 case EVENT_SEND_GEOREQUEST: {
482 std::unique_ptr<GeoConvertRequest> geoConvertRequest = event->GetUniqueObject<GeoConvertRequest>();
483 if (geoConvertRequest == nullptr) {
484 return;
485 }
486 MessageParcel dataParcel;
487 MessageParcel replyParcel;
488 MessageOption option;
489 geoConvertRequest->Marshalling(dataParcel);
490 bool ret = geoConvertService->SendGeocodeRequest(static_cast<int>(geoConvertRequest->GetRequestType()),
491 dataParcel, replyParcel, option);
492 if (!ret) {
493 LBSLOGE(GEO_CONVERT, "SendGeocodeRequest failed errcode");
494 return;
495 }
496 break;
497 }
498 default:
499 break;
500 }
501 }
502 } // namespace Location
503 } // namespace OHOS
504 #endif
505