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 "subability_common.h"
17 
18 #include "if_system_ability_manager.h"
19 #include "iservice_registry.h"
20 #include "string_ex.h"
21 #include "system_ability_definition.h"
22 
23 #include "common_utils.h"
24 #include "locationhub_ipc_interface_code.h"
25 
26 #include "work_record_statistic.h"
27 #include "app_identity.h"
28 
29 namespace OHOS {
30 namespace Location {
SubAbility()31 SubAbility::SubAbility()
32 {
33     label_ = { LOG_CORE, LOCATION_LOG_DOMAIN, "unknown" };
34     newRecord_ = std::make_unique<WorkRecord>();
35     lastRecord_ = std::make_unique<WorkRecord>();
36 }
37 
~SubAbility()38 SubAbility::~SubAbility()
39 {
40     newRecord_ = nullptr;
41     lastRecord_ = nullptr;
42 }
43 
SetAbility(std::string name)44 void SubAbility::SetAbility(std::string name)
45 {
46     name_ = name;
47     label_ = CommonUtils::GetLabel(name);
48     capability_ = CommonUtils::GetCapability(name);
49 }
50 
StopAllLocationRequests()51 void SubAbility::StopAllLocationRequests()
52 {
53     // When the switch is turned off, all current requests are stopped
54     std::unique_ptr<WorkRecord> emptyRecord = std::make_unique<WorkRecord>();
55     HandleLocalRequest(*emptyRecord);
56     lastRecord_->Clear();
57 }
58 
RestartAllLocationRequests()59 void SubAbility::RestartAllLocationRequests()
60 {
61     // When the switch is turned on, all SA requests will be refreshed
62     lastRecord_->Clear();
63     HandleRefrashRequirements();
64 }
65 
LocationRequest(WorkRecord & workRecord)66 void SubAbility::LocationRequest(WorkRecord &workRecord)
67 {
68     interval_ = workRecord.GetTimeInterval(0);
69     newRecord_->Clear();
70     newRecord_->Set(workRecord);
71     HandleRefrashRequirements();
72 }
73 
HandleRefrashRequirements()74 void SubAbility::HandleRefrashRequirements()
75 {
76     LBSLOGD(label_, "refrash requirements");
77 
78     // send local request
79     HandleLocalRequest(*newRecord_);
80     lastRecord_->Clear();
81     lastRecord_->Set(*newRecord_);
82     auto workRecordStatistic = WorkRecordStatistic::GetInstance();
83     if (!workRecordStatistic->Update(name_, GetRequestNum())) {
84         LBSLOGE(label_, "workRecordStatistic::Update failed");
85     }
86 }
87 
GetRequestNum()88 int SubAbility::GetRequestNum()
89 {
90     if (newRecord_ == nullptr) {
91         return 0;
92     }
93     return newRecord_->Size();
94 }
95 
HandleLocalRequest(WorkRecord & record)96 void SubAbility::HandleLocalRequest(WorkRecord &record)
97 {
98     HandleRemoveRecord(record);
99     HandleAddRecord(record);
100 }
101 
HandleRemoveRecord(WorkRecord & newRecord)102 void SubAbility::HandleRemoveRecord(WorkRecord &newRecord)
103 {
104     for (int i = 0; i < lastRecord_->Size(); i++) {
105         int uid = lastRecord_->GetUid(i);
106         bool isFind = newRecord.Find(uid, lastRecord_->GetName(i), lastRecord_->GetUuid(i));
107         LBSLOGD(label_, "remove record isFind:%{public}d, uid:%{public}d, lastRecord:%{public}s, newRecord:%{public}s",
108             isFind, uid, lastRecord_->ToString().c_str(), newRecord.ToString().c_str());
109         if (!isFind) {
110             std::unique_ptr<WorkRecord> workRecord = std::make_unique<WorkRecord>();
111             workRecord->Add(*lastRecord_, i);
112             workRecord->SetDeviceId(newRecord.GetDeviceId());
113             RequestRecord(*workRecord, false);
114         }
115     }
116 }
117 
HandleAddRecord(WorkRecord & newRecord)118 void SubAbility::HandleAddRecord(WorkRecord &newRecord)
119 {
120     for (int i = 0; i < newRecord.Size(); i++) {
121         int uid = newRecord.GetUid(i);
122         bool isFind = lastRecord_->Find(uid, newRecord.GetName(i), lastRecord_->GetUuid(i));
123         LBSLOGD(label_, "add record isFind:%{public}d, uid:%{public}d, lastRecord:%{public}s, newRecord:%{public}s",
124             isFind, uid, lastRecord_->ToString().c_str(), newRecord.ToString().c_str());
125         if (!isFind) {
126             std::unique_ptr<WorkRecord> workRecord = std::make_unique<WorkRecord>();
127             workRecord->Add(newRecord, i);
128             workRecord->SetDeviceId(newRecord.GetDeviceId());
129             RequestRecord(*workRecord, true);
130         }
131     }
132 }
133 
Enable(bool state,const sptr<IRemoteObject> ability)134 void SubAbility::Enable(bool state, const sptr<IRemoteObject> ability)
135 {
136     sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
137     if (sam == nullptr) {
138         LBSLOGE(label_, "Enable can not get SystemAbilityManager");
139         return;
140     }
141 
142     int saId = CommonUtils::AbilityConvertToId(name_);
143     if (state) {
144         if (sam->CheckSystemAbility(saId) == nullptr) {
145             sam->AddSystemAbility(saId, ability, ISystemAbilityManager::SAExtraProp(true, 1, capability_, u""));
146             LBSLOGI(label_, "enable %{public}s ability", name_.c_str());
147         }
148     } else {
149         if (sam->CheckSystemAbility(saId) != nullptr) {
150             sam->RemoveSystemAbility(saId);
151             LBSLOGI(label_, "disable %{public}s ability", name_.c_str());
152         }
153     }
154 }
155 
EnableLocationMock()156 bool SubAbility::EnableLocationMock()
157 {
158     LBSLOGI(label_, "EnableLocationMock current state is %{public}d", mockEnabled_);
159     mockEnabled_ = true;
160     return true;
161 }
162 
DisableLocationMock()163 bool SubAbility::DisableLocationMock()
164 {
165     LBSLOGI(label_, "DisableLocationMock current state is %{public}d", mockEnabled_);
166     mockEnabled_ = false;
167     return true;
168 }
169 
SetMockedLocations(const int timeInterval,const std::vector<std::shared_ptr<Location>> & location)170 bool SubAbility::SetMockedLocations(const int timeInterval, const std::vector<std::shared_ptr<Location>> &location)
171 {
172     if (!mockEnabled_) {
173         LBSLOGE(label_, "SetMockedLocations current state is %{public}d, need enbale it", mockEnabled_);
174         return false;
175     }
176     CacheLocationMock(location);
177     mockTimeInterval_ = timeInterval;
178     SendReportMockLocationEvent();
179     return true;
180 }
181 
CacheLocationMock(const std::vector<std::shared_ptr<Location>> & location)182 void SubAbility::CacheLocationMock(const std::vector<std::shared_ptr<Location>> &location)
183 {
184     int locationSize = static_cast<int>(location.size());
185     ClearLocationMock();
186     std::unique_lock lock(mutex_);
187     for (int i = 0; i < locationSize; i++) {
188         mockLoc_.push_back(std::make_shared<Location>(*location.at(i)));
189     }
190 }
191 
IsLocationMocked()192 bool SubAbility::IsLocationMocked()
193 {
194     return mockEnabled_;
195 }
196 
GetTimeIntervalMock()197 int SubAbility::GetTimeIntervalMock()
198 {
199     return mockTimeInterval_;
200 }
201 
GetLocationMock()202 std::vector<std::shared_ptr<Location>> SubAbility::GetLocationMock()
203 {
204     std::unique_lock lock(mutex_);
205     return mockLoc_;
206 }
207 
ClearLocationMock()208 void SubAbility::ClearLocationMock()
209 {
210     std::unique_lock lock(mutex_);
211     mockLoc_.clear();
212 }
213 
ReportLocationInfo(const std::string & systemAbility,const std::shared_ptr<Location> location)214 void SubAbility::ReportLocationInfo(
215     const std::string& systemAbility, const std::shared_ptr<Location> location)
216 {
217     MessageParcel data;
218     MessageParcel reply;
219     MessageOption option;
220     data.WriteInterfaceToken(u"location.ILocator");
221     data.WriteString(systemAbility);
222     location->Marshalling(data);
223     sptr<IRemoteObject> objectLocator =
224         CommonUtils::GetRemoteObject(LOCATION_LOCATOR_SA_ID, CommonUtils::InitDeviceId());
225     if (objectLocator == nullptr) {
226         LBSLOGE(label_, "%{public}s get locator sa failed", __func__);
227         return;
228     }
229     objectLocator->SendRequest(static_cast<int>(LocatorInterfaceCode::REPORT_LOCATION), data, reply, option);
230 }
231 
GetPackageNameByUuid(std::string uuid)232 std::string SubAbility::GetPackageNameByUuid(std::string uuid)
233 {
234     if (lastRecord_ != nullptr) {
235         return lastRecord_->GetPackageNameByUuid(uuid);
236     }
237     return "";
238 }
239 } // namespace Location
240 } // namespace OHOS
241