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_PASSIVE_SUPPORT
17 #include "passive_ability.h"
18
19 #include <file_ex.h>
20
21 #include "singleton.h"
22 #include "string_ex.h"
23 #include "system_ability.h"
24 #include "system_ability_definition.h"
25
26 #include "common_utils.h"
27 #include "location.h"
28 #include "location_dumper.h"
29 #include "location_log.h"
30 #include "location_sa_load_manager.h"
31 #include "work_record.h"
32 #include "locationhub_ipc_interface_code.h"
33
34 namespace OHOS {
35 namespace Location {
36 const uint32_t EVENT_INTERVAL_UNITE = 1000;
37 const uint32_t RETRY_INTERVAL_OF_UNLOAD_SA = 4 * 60 * EVENT_INTERVAL_UNITE;
38 const std::string UNLOAD_PASSIVE_TASK = "passive_sa_unload";
39 const bool REGISTER_RESULT = PassiveAbility::MakeAndRegisterAbility(
40 PassiveAbility::GetInstance());
41
GetInstance()42 PassiveAbility* PassiveAbility::GetInstance()
43 {
44 static PassiveAbility data;
45 return &data;
46 }
47
PassiveAbility()48 PassiveAbility::PassiveAbility() : SystemAbility(LOCATION_NOPOWER_LOCATING_SA_ID, true)
49 {
50 SetAbility(PASSIVE_ABILITY);
51 passiveHandler_ =
52 std::make_shared<PassiveHandler>(AppExecFwk::EventRunner::Create(true, AppExecFwk::ThreadMode::FFRT));
53 LBSLOGI(PASSIVE, "ability constructed.");
54 }
55
~PassiveAbility()56 PassiveAbility::~PassiveAbility() {}
57
OnStart()58 void PassiveAbility::OnStart()
59 {
60 if (state_ == ServiceRunningState::STATE_RUNNING) {
61 LBSLOGI(PASSIVE, "ability has already started.");
62 return;
63 }
64 if (!Init()) {
65 LBSLOGE(PASSIVE, "failed to init ability");
66 OnStop();
67 return;
68 }
69 state_ = ServiceRunningState::STATE_RUNNING;
70 LBSLOGI(PASSIVE, "OnStart start ability success.");
71 }
72
OnStop()73 void PassiveAbility::OnStop()
74 {
75 state_ = ServiceRunningState::STATE_NOT_START;
76 registerToAbility_ = false;
77 LBSLOGI(PASSIVE, "OnStop ability stopped.");
78 }
79
Init()80 bool PassiveAbility::Init()
81 {
82 if (!registerToAbility_) {
83 bool ret = Publish(AsObject());
84 if (!ret) {
85 LBSLOGE(PASSIVE, "Init Publish failed!");
86 return false;
87 }
88 registerToAbility_ = true;
89 }
90 return true;
91 }
92
SendLocationRequest(WorkRecord & workrecord)93 LocationErrCode PassiveAbility::SendLocationRequest(WorkRecord &workrecord)
94 {
95 LocationRequest(workrecord);
96 return ERRCODE_SUCCESS;
97 }
98
SetEnable(bool state)99 LocationErrCode PassiveAbility::SetEnable(bool state)
100 {
101 return ERRCODE_SUCCESS;
102 }
103
CancelIdleState()104 bool PassiveAbility::CancelIdleState()
105 {
106 SystemAbilityState state = GetAbilityState();
107 if (state != SystemAbilityState::IDLE) {
108 return true;
109 }
110 bool ret = CancelIdle();
111 if (!ret) {
112 LBSLOGE(PASSIVE, "%{public}s cancel idle failed!", __func__);
113 return false;
114 }
115 return true;
116 }
117
UnloadPassiveSystemAbility()118 void PassiveAbility::UnloadPassiveSystemAbility()
119 {
120 if (passiveHandler_ == nullptr) {
121 LBSLOGE(PASSIVE, "%{public}s passiveHandler is nullptr", __func__);
122 return;
123 }
124 passiveHandler_->RemoveTask(UNLOAD_PASSIVE_TASK);
125 auto task = [this]() {
126 if (CheckIfPassiveConnecting()) {
127 return;
128 }
129 SaLoadWithStatistic::UnInitLocationSa(LOCATION_NOPOWER_LOCATING_SA_ID);
130 };
131 if (passiveHandler_ != nullptr) {
132 passiveHandler_->PostTask(task, UNLOAD_PASSIVE_TASK, RETRY_INTERVAL_OF_UNLOAD_SA);
133 }
134 }
135
CheckIfPassiveConnecting()136 bool PassiveAbility::CheckIfPassiveConnecting()
137 {
138 return IsMockEnabled() || !GetLocationMock().empty();
139 }
140
RequestRecord(WorkRecord & workRecord,bool isAdded)141 void PassiveAbility::RequestRecord(WorkRecord &workRecord, bool isAdded)
142 {
143 LBSLOGD(PASSIVE, "enter RequestRecord");
144 }
145
EnableMock()146 LocationErrCode PassiveAbility::EnableMock()
147 {
148 if (!EnableLocationMock()) {
149 return LOCATION_ERRCODE_NOT_SUPPORTED;
150 }
151 return ERRCODE_SUCCESS;
152 }
153
DisableMock()154 LocationErrCode PassiveAbility::DisableMock()
155 {
156 if (!DisableLocationMock()) {
157 return LOCATION_ERRCODE_NOT_SUPPORTED;
158 }
159 return ERRCODE_SUCCESS;
160 }
161
IsMockEnabled()162 bool PassiveAbility::IsMockEnabled()
163 {
164 return IsLocationMocked();
165 }
166
SetMocked(const int timeInterval,const std::vector<std::shared_ptr<Location>> & location)167 LocationErrCode PassiveAbility::SetMocked(const int timeInterval,
168 const std::vector<std::shared_ptr<Location>> &location)
169 {
170 if (!SetMockedLocations(timeInterval, location)) {
171 return LOCATION_ERRCODE_NOT_SUPPORTED;
172 }
173 return ERRCODE_SUCCESS;
174 }
175
SendReportMockLocationEvent()176 void PassiveAbility::SendReportMockLocationEvent()
177 {
178 ClearLocationMock();
179 }
180
SaDumpInfo(std::string & result)181 void PassiveAbility::SaDumpInfo(std::string& result)
182 {
183 result += "Passive Location enable status: true";
184 result += "\n";
185 }
186
Dump(int32_t fd,const std::vector<std::u16string> & args)187 int32_t PassiveAbility::Dump(int32_t fd, const std::vector<std::u16string>& args)
188 {
189 std::vector<std::string> vecArgs;
190 std::transform(args.begin(), args.end(), std::back_inserter(vecArgs), [](const std::u16string &arg) {
191 return Str16ToStr8(arg);
192 });
193
194 LocationDumper dumper;
195 std::string result;
196 dumper.PassiveDump(SaDumpInfo, vecArgs, result);
197 if (!SaveStringToFd(fd, result)) {
198 LBSLOGE(PASSIVE, "Passive save string to fd failed!");
199 return ERR_OK;
200 }
201 return ERR_OK;
202 }
203
SendMessage(uint32_t code,MessageParcel & data,MessageParcel & reply)204 void PassiveAbility::SendMessage(uint32_t code, MessageParcel &data, MessageParcel &reply)
205 {
206 if (passiveHandler_ == nullptr) {
207 reply.WriteInt32(ERRCODE_SERVICE_UNAVAILABLE);
208 return;
209 }
210 switch (code) {
211 case static_cast<uint32_t>(PassiveInterfaceCode::SET_MOCKED_LOCATIONS): {
212 if (!IsMockEnabled()) {
213 reply.WriteInt32(LOCATION_ERRCODE_NOT_SUPPORTED);
214 break;
215 }
216 int timeInterval = data.ReadInt32();
217 int locationSize = data.ReadInt32();
218 timeInterval = timeInterval < 0 ? 1 : timeInterval;
219 locationSize = locationSize > INPUT_ARRAY_LEN_MAX ? INPUT_ARRAY_LEN_MAX :
220 locationSize;
221 std::shared_ptr<std::vector<std::shared_ptr<Location>>> vcLoc =
222 std::make_shared<std::vector<std::shared_ptr<Location>>>();
223 for (int i = 0; i < locationSize; i++) {
224 vcLoc->push_back(Location::UnmarshallingShared(data));
225 }
226 AppExecFwk::InnerEvent::Pointer event =
227 AppExecFwk::InnerEvent::Get(code, vcLoc, timeInterval);
228 if (passiveHandler_->SendEvent(event)) {
229 reply.WriteInt32(ERRCODE_SUCCESS);
230 } else {
231 reply.WriteInt32(ERRCODE_SERVICE_UNAVAILABLE);
232 }
233 break;
234 }
235 default:
236 break;
237 }
238 }
239
PassiveHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner)240 PassiveHandler::PassiveHandler(const std::shared_ptr<AppExecFwk::EventRunner>& runner) : EventHandler(runner) {}
241
~PassiveHandler()242 PassiveHandler::~PassiveHandler() {}
243
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)244 void PassiveHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer& event)
245 {
246 auto passiveAbility = PassiveAbility::GetInstance();
247 uint32_t eventId = event->GetInnerEventId();
248 LBSLOGD(PASSIVE, "ProcessEvent event:%{public}d", eventId);
249 switch (eventId) {
250 case static_cast<uint32_t>(PassiveInterfaceCode::SET_MOCKED_LOCATIONS): {
251 int timeInterval = event->GetParam();
252 auto vcLoc = event->GetSharedObject<std::vector<std::shared_ptr<Location>>>();
253 if (vcLoc == nullptr) {
254 break;
255 }
256 std::vector<std::shared_ptr<Location>> mockLocations;
257 for (auto it = vcLoc->begin(); it != vcLoc->end(); ++it) {
258 mockLocations.push_back(*it);
259 }
260 if (passiveAbility != nullptr) {
261 passiveAbility->SetMocked(timeInterval, mockLocations);
262 }
263 break;
264 }
265 default:
266 break;
267 }
268 passiveAbility->UnloadPassiveSystemAbility();
269 }
270 } // namespace Location
271 } // namespace OHOS
272 #endif // FEATURE_PASSIVE_SUPPORT
273