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_NETWORK_SUPPORT
17 #include "network_ability.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 "ipc_skeleton.h"
24 #include "iservice_registry.h"
25 #include "system_ability_definition.h"
26 #include "want_agent_helper.h"
27
28 #include "common_utils.h"
29 #include "location_config_manager.h"
30 #include "location_dumper.h"
31 #include "location_log.h"
32 #include "location_sa_load_manager.h"
33 #include "network_callback_host.h"
34 #include "locationhub_ipc_interface_code.h"
35
36 namespace OHOS {
37 namespace Location {
38 const uint32_t EVENT_REPORT_LOCATION = 0x0100;
39 const uint32_t EVENT_INTERVAL_UNITE = 1000;
40 constexpr uint32_t WAIT_MS = 100;
41 const int MAX_RETRY_COUNT = 5;
42 const bool REGISTER_RESULT = NetworkAbility::MakeAndRegisterAbility(
43 DelayedSingleton<NetworkAbility>::GetInstance().get());
44
NetworkAbility()45 NetworkAbility::NetworkAbility() : SystemAbility(LOCATION_NETWORK_LOCATING_SA_ID, true)
46 {
47 SetAbility(NETWORK_ABILITY);
48 networkHandler_ = std::make_shared<NetworkHandler>(AppExecFwk::EventRunner::Create(true));
49 LBSLOGI(NETWORK, "ability constructed.");
50 }
51
~NetworkAbility()52 NetworkAbility::~NetworkAbility() {}
53
OnStart()54 void NetworkAbility::OnStart()
55 {
56 if (state_ == ServiceRunningState::STATE_RUNNING) {
57 LBSLOGI(NETWORK, "ability has already started.");
58 return;
59 }
60 if (!Init()) {
61 LBSLOGE(NETWORK, "failed to init ability");
62 OnStop();
63 return;
64 }
65 state_ = ServiceRunningState::STATE_RUNNING;
66 LBSLOGI(NETWORK, "OnStart start ability success.");
67 }
68
OnStop()69 void NetworkAbility::OnStop()
70 {
71 state_ = ServiceRunningState::STATE_NOT_START;
72 registerToAbility_ = false;
73 LBSLOGI(NETWORK, "OnStop ability stopped.");
74 }
75
Init()76 bool NetworkAbility::Init()
77 {
78 if (!registerToAbility_) {
79 if (!Publish(AsObject())) {
80 LBSLOGE(NETWORK, "Init Publish failed!");
81 return false;
82 }
83 registerToAbility_ = true;
84 }
85 return true;
86 }
87
88 class AbilityConnection : public AAFwk::AbilityConnectionStub {
89 public:
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)90 void OnAbilityConnectDone(
91 const AppExecFwk::ElementName& element, const sptr<IRemoteObject>& remoteObject, int resultCode) override
92 {
93 std::string uri = element.GetURI();
94 LBSLOGD(NETWORK, "Connected uri is %{public}s, result is %{public}d.", uri.c_str(), resultCode);
95 if (resultCode != ERR_OK) {
96 return;
97 }
98 DelayedSingleton<NetworkAbility>::GetInstance().get()->NotifyConnected(remoteObject);
99 }
100
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int)101 void OnAbilityDisconnectDone(const AppExecFwk::ElementName& element, int) override
102 {
103 std::string uri = element.GetURI();
104 LBSLOGD(NETWORK, "Disconnected uri is %{public}s.", uri.c_str());
105 DelayedSingleton<NetworkAbility>::GetInstance().get()->NotifyDisConnected();
106 }
107 };
108
ConnectNlpService()109 bool NetworkAbility::ConnectNlpService()
110 {
111 LBSLOGD(NETWORK, "start ConnectNlpService");
112 std::unique_lock<std::mutex> uniqueLock(mutex_);
113 if (!nlpServiceReady_) {
114 AAFwk::Want connectionWant;
115 std::string serviceName;
116 bool result = LocationConfigManager::GetInstance().GetNlpServiceName(serviceName);
117 if (!result || serviceName.empty()) {
118 LBSLOGE(NETWORK, "get service name failed!");
119 return false;
120 }
121 std::string abilityName;
122 bool res = LocationConfigManager::GetInstance().GetNlpAbilityName(abilityName);
123 if (!res || abilityName.empty()) {
124 LBSLOGE(NETWORK, "get service name failed!");
125 return false;
126 }
127 connectionWant.SetElementName(serviceName, abilityName);
128 sptr<AAFwk::IAbilityConnection> conn = new (std::nothrow) AbilityConnection();
129 if (conn == nullptr) {
130 LBSLOGE(NETWORK, "get connection failed!");
131 return false;
132 }
133 int32_t ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(connectionWant, conn, -1);
134 if (ret != ERR_OK) {
135 LBSLOGE(NETWORK, "Connect cloud service failed!");
136 return false;
137 }
138
139 auto waitStatus = connectCondition_.wait_for(
140 uniqueLock, std::chrono::seconds(CONNECT_TIME_OUT), [this]() { return nlpServiceReady_; });
141 if (!waitStatus) {
142 LBSLOGE(NETWORK, "Connect cloudService timeout!");
143 return false;
144 }
145 }
146 return true;
147 }
148
ReConnectNlpService()149 bool NetworkAbility::ReConnectNlpService()
150 {
151 int retryCount = 0;
152 if (nlpServiceReady_) {
153 LBSLOGI(NETWORK, "Connect success!");
154 return true;
155 }
156 while (retryCount < MAX_RETRY_COUNT) {
157 retryCount++;
158 bool ret = ConnectNlpService();
159 if (ret) {
160 LBSLOGI(NETWORK, "Connect success!");
161 return true;
162 }
163 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_MS));
164 }
165 return false;
166 }
167
NotifyConnected(const sptr<IRemoteObject> & remoteObject)168 void NetworkAbility::NotifyConnected(const sptr<IRemoteObject>& remoteObject)
169 {
170 std::unique_lock<std::mutex> uniqueLock(mutex_);
171 nlpServiceReady_ = true;
172 nlpServiceProxy_ = remoteObject;
173 connectCondition_.notify_all();
174 }
175
NotifyDisConnected()176 void NetworkAbility::NotifyDisConnected()
177 {
178 std::unique_lock<std::mutex> uniqueLock(mutex_);
179 nlpServiceReady_ = false;
180 nlpServiceProxy_ = nullptr;
181 connectCondition_.notify_all();
182 }
183
SendLocationRequest(WorkRecord & workrecord)184 LocationErrCode NetworkAbility::SendLocationRequest(WorkRecord &workrecord)
185 {
186 LocationRequest(workrecord);
187 return ERRCODE_SUCCESS;
188 }
189
SetEnable(bool state)190 LocationErrCode NetworkAbility::SetEnable(bool state)
191 {
192 if (state) {
193 Enable(true, AsObject());
194 return ERRCODE_SUCCESS;
195 }
196 if (!CheckIfNetworkConnecting()) {
197 Enable(false, AsObject());
198 }
199 return ERRCODE_SUCCESS;
200 }
201
UnloadNetworkSystemAbility()202 void NetworkAbility::UnloadNetworkSystemAbility()
203 {
204 auto locationSaLoadManager = DelayedSingleton<LocationSaLoadManager>::GetInstance();
205 if (locationSaLoadManager == nullptr) {
206 return;
207 }
208
209 if (!CheckIfNetworkConnecting()) {
210 locationSaLoadManager->UnloadLocationSa(LOCATION_NETWORK_LOCATING_SA_ID);
211 }
212 }
213
CheckIfNetworkConnecting()214 bool NetworkAbility::CheckIfNetworkConnecting()
215 {
216 return IsMockEnabled() || !GetLocationMock().empty() || GetRequestNum() != 0;
217 }
218
SelfRequest(bool state)219 LocationErrCode NetworkAbility::SelfRequest(bool state)
220 {
221 LBSLOGI(NETWORK, "SelfRequest %{public}d", state);
222 HandleSelfRequest(IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), state);
223 return ERRCODE_SUCCESS;
224 }
225
RequestRecord(WorkRecord & workRecord,bool isAdded)226 void NetworkAbility::RequestRecord(WorkRecord &workRecord, bool isAdded)
227 {
228 if (!nlpServiceReady_) {
229 std::string serviceName;
230 bool result = LocationConfigManager::GetInstance().GetNlpServiceName(serviceName);
231 if (!result || serviceName.empty()) {
232 LBSLOGE(NETWORK, "get service name failed!");
233 return;
234 }
235 if (!CommonUtils::CheckAppInstalled(serviceName)) { // app is not installed
236 LBSLOGE(NETWORK, "nlp service is not available.");
237 return;
238 } else if (!ReConnectNlpService()) {
239 LBSLOGE(NETWORK, "nlp service is not ready.");
240 return;
241 }
242 }
243 std::unique_lock<std::mutex> uniqueLock(mutex_);
244 if (nlpServiceProxy_ == nullptr) {
245 LBSLOGE(NETWORK, "nlpProxy is nullptr.");
246 return;
247 }
248 MessageParcel data;
249 MessageParcel reply;
250 MessageOption option;
251 if (isAdded) {
252 LBSLOGD(NETWORK, "start network location");
253 sptr<NetworkCallbackHost> callback = new (std::nothrow) NetworkCallbackHost();
254 if (callback == nullptr) {
255 LBSLOGE(NETWORK, "can not get valid callback.");
256 return;
257 }
258 data.WriteString16(Str8ToStr16(workRecord.GetUuid(0)));
259 data.WriteInt64(workRecord.GetTimeInterval(0) * SEC_TO_MILLI_SEC);
260 data.WriteInt32(LocationRequestType::PRIORITY_TYPE_BALANCED_POWER_ACCURACY);
261 data.WriteRemoteObject(callback->AsObject());
262 data.WriteString16(Str8ToStr16(workRecord.GetName(0))); // bundleName
263 int error = nlpServiceProxy_->SendRequest(REQUEST_NETWORK_LOCATION, data, reply, option);
264 if (error != ERR_OK) {
265 LBSLOGE(NETWORK, "SendRequest to cloud service failed.");
266 return;
267 }
268 } else {
269 LBSLOGD(NETWORK, "stop network location");
270 data.WriteString16(Str8ToStr16(workRecord.GetUuid(0)));
271 data.WriteString16(Str8ToStr16(workRecord.GetName(0))); // bundleName
272 int error = nlpServiceProxy_->SendRequest(REMOVE_NETWORK_LOCATION, data, reply, option);
273 if (error != ERR_OK) {
274 LBSLOGE(NETWORK, "SendRequest to cloud service failed.");
275 return;
276 }
277 }
278 }
279
EnableMock()280 LocationErrCode NetworkAbility::EnableMock()
281 {
282 if (!EnableLocationMock()) {
283 return ERRCODE_NOT_SUPPORTED;
284 }
285 return ERRCODE_SUCCESS;
286 }
287
DisableMock()288 LocationErrCode NetworkAbility::DisableMock()
289 {
290 if (!DisableLocationMock()) {
291 return ERRCODE_NOT_SUPPORTED;
292 }
293 return ERRCODE_SUCCESS;
294 }
295
IsMockEnabled()296 bool NetworkAbility::IsMockEnabled()
297 {
298 return IsLocationMocked();
299 }
300
SetMocked(const int timeInterval,const std::vector<std::shared_ptr<Location>> & location)301 LocationErrCode NetworkAbility::SetMocked(const int timeInterval,
302 const std::vector<std::shared_ptr<Location>> &location)
303 {
304 if (!SetMockedLocations(timeInterval, location)) {
305 return ERRCODE_NOT_SUPPORTED;
306 }
307 return ERRCODE_SUCCESS;
308 }
309
ProcessReportLocationMock()310 void NetworkAbility::ProcessReportLocationMock()
311 {
312 std::vector<std::shared_ptr<Location>> mockLocationArray = GetLocationMock();
313 if (mockLocationIndex_ < mockLocationArray.size()) {
314 ReportMockedLocation(mockLocationArray[mockLocationIndex_++]);
315 if (networkHandler_ != nullptr) {
316 networkHandler_->SendHighPriorityEvent(EVENT_REPORT_LOCATION,
317 0, GetTimeIntervalMock() * EVENT_INTERVAL_UNITE);
318 }
319 } else {
320 ClearLocationMock();
321 mockLocationIndex_ = 0;
322 }
323 }
324
SendReportMockLocationEvent()325 void NetworkAbility::SendReportMockLocationEvent()
326 {
327 if (networkHandler_ == nullptr) {
328 return;
329 }
330 networkHandler_->SendHighPriorityEvent(EVENT_REPORT_LOCATION, 0, 0);
331 }
332
ReportMockedLocation(const std::shared_ptr<Location> location)333 int32_t NetworkAbility::ReportMockedLocation(const std::shared_ptr<Location> location)
334 {
335 if ((IsLocationMocked() && !location->GetIsFromMock()) ||
336 (!IsLocationMocked() && location->GetIsFromMock())) {
337 LBSLOGE(NETWORK, "location mock is enabled, do not report gnss location!");
338 return ERR_OK;
339 }
340 ReportLocationInfo(NETWORK_ABILITY, location);
341 #ifdef FEATURE_PASSIVE_SUPPORT
342 ReportLocationInfo(PASSIVE_ABILITY, location);
343 #endif
344 return ERR_OK;
345 }
346
SaDumpInfo(std::string & result)347 void NetworkAbility::SaDumpInfo(std::string& result)
348 {
349 result += "Network Location enable status: false";
350 result += "\n";
351 }
352
Dump(int32_t fd,const std::vector<std::u16string> & args)353 int32_t NetworkAbility::Dump(int32_t fd, const std::vector<std::u16string>& args)
354 {
355 std::vector<std::string> vecArgs;
356 std::transform(args.begin(), args.end(), std::back_inserter(vecArgs), [](const std::u16string &arg) {
357 return Str16ToStr8(arg);
358 });
359
360 LocationDumper dumper;
361 std::string result;
362 dumper.NetWorkDump(SaDumpInfo, vecArgs, result);
363 if (!SaveStringToFd(fd, result)) {
364 LBSLOGE(NETWORK, "Network save string to fd failed!");
365 return ERR_OK;
366 }
367 return ERR_OK;
368 }
369
SendMessage(uint32_t code,MessageParcel & data,MessageParcel & reply)370 void NetworkAbility::SendMessage(uint32_t code, MessageParcel &data, MessageParcel &reply)
371 {
372 if (networkHandler_ == nullptr) {
373 reply.WriteInt32(ERRCODE_SERVICE_UNAVAILABLE);
374 return;
375 }
376 switch (code) {
377 case static_cast<uint32_t>(NetworkInterfaceCode::SEND_LOCATION_REQUEST): {
378 std::unique_ptr<WorkRecord> workrecord = WorkRecord::Unmarshalling(data);
379 AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent::Get(code, workrecord);
380 if (networkHandler_->SendEvent(event)) {
381 reply.WriteInt32(ERRCODE_SUCCESS);
382 } else {
383 reply.WriteInt32(ERRCODE_SERVICE_UNAVAILABLE);
384 }
385 break;
386 }
387 case static_cast<uint32_t>(NetworkInterfaceCode::SET_MOCKED_LOCATIONS): {
388 if (!IsMockEnabled()) {
389 reply.WriteInt32(ERRCODE_NOT_SUPPORTED);
390 break;
391 }
392 int timeInterval = data.ReadInt32();
393 int locationSize = data.ReadInt32();
394 timeInterval = timeInterval < 0 ? 1 : timeInterval;
395 locationSize = locationSize > INPUT_ARRAY_LEN_MAX ? INPUT_ARRAY_LEN_MAX :
396 locationSize;
397 std::shared_ptr<std::vector<std::shared_ptr<Location>>> vcLoc =
398 std::make_shared<std::vector<std::shared_ptr<Location>>>();
399 for (int i = 0; i < locationSize; i++) {
400 vcLoc->push_back(Location::UnmarshallingShared(data));
401 }
402 AppExecFwk::InnerEvent::Pointer event =
403 AppExecFwk::InnerEvent::Get(code, vcLoc, timeInterval);
404 if (networkHandler_->SendEvent(event)) {
405 reply.WriteInt32(ERRCODE_SUCCESS);
406 } else {
407 reply.WriteInt32(ERRCODE_SERVICE_UNAVAILABLE);
408 }
409 break;
410 }
411 case static_cast<uint32_t>(NetworkInterfaceCode::SELF_REQUEST): {
412 int64_t param = data.ReadBool() ? 1 : 0;
413 networkHandler_->SendEvent(code, param, 0) ? reply.WriteInt32(ERRCODE_SUCCESS) :
414 reply.WriteInt32(ERRCODE_SERVICE_UNAVAILABLE);
415 break;
416 }
417 default:
418 break;
419 }
420 }
421
NetworkHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner)422 NetworkHandler::NetworkHandler(const std::shared_ptr<AppExecFwk::EventRunner>& runner) : EventHandler(runner) {}
423
~NetworkHandler()424 NetworkHandler::~NetworkHandler() {}
425
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)426 void NetworkHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer& event)
427 {
428 auto networkAbility = DelayedSingleton<NetworkAbility>::GetInstance();
429 if (networkAbility == nullptr) {
430 LBSLOGE(NETWORK, "ProcessEvent: NetworkAbility is nullptr");
431 return;
432 }
433 uint32_t eventId = event->GetInnerEventId();
434 LBSLOGI(NETWORK, "ProcessEvent event:%{public}d", eventId);
435 switch (eventId) {
436 case EVENT_REPORT_LOCATION: {
437 networkAbility->ProcessReportLocationMock();
438 break;
439 }
440 case static_cast<uint32_t>(NetworkInterfaceCode::SEND_LOCATION_REQUEST): {
441 std::unique_ptr<WorkRecord> workrecord = event->GetUniqueObject<WorkRecord>();
442 if (workrecord != nullptr) {
443 networkAbility->LocationRequest(*workrecord);
444 }
445 break;
446 }
447 case static_cast<uint32_t>(NetworkInterfaceCode::SET_MOCKED_LOCATIONS): {
448 int timeInterval = event->GetParam();
449 auto vcLoc = event->GetSharedObject<std::vector<std::shared_ptr<Location>>>();
450 if (vcLoc != nullptr) {
451 std::vector<std::shared_ptr<Location>> mockLocations;
452 for (auto it = vcLoc->begin(); it != vcLoc->end(); ++it) {
453 mockLocations.push_back(*it);
454 }
455 networkAbility->SetMocked(timeInterval, mockLocations);
456 }
457 break;
458 }
459 case static_cast<uint32_t>(NetworkInterfaceCode::SELF_REQUEST): {
460 bool state = event->GetParam();
461 networkAbility->SelfRequest(state);
462 // no need unload sa, return
463 return;
464 }
465 default:
466 break;
467 }
468 networkAbility->UnloadNetworkSystemAbility();
469 }
470 } // namespace Location
471 } // namespace OHOS
472 #endif // FEATURE_NETWORK_SUPPORT
473