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