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 "report_manager.h"
17
18 #include <cmath>
19 #include "privacy_kit.h"
20 #include "common_utils.h"
21 #include "fusion_controller.h"
22 #include "i_locator_callback.h"
23 #include "location_log.h"
24 #include "locator_ability.h"
25 #include "locator_background_proxy.h"
26 #include "location_log_event_ids.h"
27 #include "common_hisysevent.h"
28
29 #ifdef BGTASKMGR_SUPPORT
30 #include "background_mode.h"
31 #include "background_task_mgr_helper.h"
32 #endif
33
34 namespace OHOS {
35 namespace Location {
36 const long NANOS_PER_MILLI = 1000000L;
37 const int MAX_SA_SCHEDULING_JITTER_MS = 200;
38 static constexpr double MAXIMUM_FUZZY_LOCATION_DISTANCE = 4000.0; // Unit m
39 static constexpr double MINIMUM_FUZZY_LOCATION_DISTANCE = 3000.0; // Unit m
40 static constexpr int GNSS_FIX_CACHED_TIME = 60;
41 static constexpr int NLP_FIX_CACHED_TIME = 45;
ReportManager()42 ReportManager::ReportManager()
43 {
44 clock_gettime(CLOCK_REALTIME, &lastUpdateTime_);
45 offsetRandom_ = CommonUtils::DoubleRandom(0, 1);
46 }
47
~ReportManager()48 ReportManager::~ReportManager() {}
49
OnReportLocation(const std::unique_ptr<Location> & location,std::string abilityName)50 bool ReportManager::OnReportLocation(const std::unique_ptr<Location>& location, std::string abilityName)
51 {
52 auto fusionController = DelayedSingleton<FusionController>::GetInstance();
53 if (fusionController == nullptr) {
54 return false;
55 }
56 fusionController->FuseResult(abilityName, location);
57 UpdateCacheLocation(location, abilityName);
58 auto locatorAbility = DelayedSingleton<LocatorAbility>::GetInstance();
59 if (locatorAbility == nullptr) {
60 return false;
61 }
62 auto requestMap = locatorAbility->GetRequests();
63 if (requestMap == nullptr) {
64 return false;
65 }
66 auto requestListIter = requestMap->find(abilityName);
67 if (requestListIter == requestMap->end()) {
68 return false;
69 }
70 auto requestList = requestListIter->second;
71 auto deadRequests = std::make_unique<std::list<std::shared_ptr<Request>>>();
72 auto fuseLocation = fusionController->GetFuseLocation(abilityName, location);
73 for (auto iter = requestList.begin(); iter != requestList.end(); iter++) {
74 auto request = *iter;
75 WriteNetWorkReportEvent(abilityName, request, location);
76 bool ret = true;
77 if (IsRequestFuse(request)) {
78 ret = ProcessRequestForReport(request, deadRequests, fuseLocation);
79 } else {
80 ret = ProcessRequestForReport(request, deadRequests, location);
81 }
82 if (!ret) {
83 continue;
84 }
85 }
86 for (auto iter = deadRequests->begin(); iter != deadRequests->end(); ++iter) {
87 auto request = *iter;
88 if (request == nullptr) {
89 continue;
90 }
91 auto requestManger = DelayedSingleton<RequestManager>::GetInstance();
92 if (requestManger != nullptr) {
93 requestManger->UpdateRequestRecord(request, false);
94 }
95 }
96 locatorAbility->ApplyRequests(1);
97 deadRequests->clear();
98 return true;
99 }
100
UpdateLocationByRequest(const uint32_t tokenId,const uint32_t tokenIdEx,std::unique_ptr<Location> & location)101 void ReportManager::UpdateLocationByRequest(const uint32_t tokenId, const uint32_t tokenIdEx,
102 std::unique_ptr<Location>& location)
103 {
104 if (location == nullptr) {
105 LBSLOGI(REPORT_MANAGER, "location == nullptr");
106 return;
107 }
108 if (!CommonUtils::CheckSystemPermission(tokenId, tokenIdEx)) {
109 location->SetSourceType(0);
110 } else {
111 location->SetSourceType(1);
112 }
113 }
114
ProcessRequestForReport(std::shared_ptr<Request> & request,std::unique_ptr<std::list<std::shared_ptr<Request>>> & deadRequests,const std::unique_ptr<Location> & location)115 bool ReportManager::ProcessRequestForReport(std::shared_ptr<Request>& request,
116 std::unique_ptr<std::list<std::shared_ptr<Request>>>& deadRequests, const std::unique_ptr<Location>& location)
117 {
118 if (request == nullptr || request->GetRequestConfig() == nullptr ||
119 !request->GetIsRequesting()) {
120 return false;
121 }
122 std::unique_ptr<Location> finalLocation = GetPermittedLocation(request->GetUid(),
123 request->GetTokenId(), request->GetFirstTokenId(), location);
124 if (!ResultCheck(finalLocation, request)) {
125 // add location permission using record
126 PrivacyKit::AddPermissionUsedRecord(request->GetTokenId(), ACCESS_APPROXIMATELY_LOCATION, 0, 1);
127 return false;
128 }
129 UpdateLocationByRequest(request->GetTokenId(), request->GetTokenIdEx(), finalLocation);
130 request->SetLastLocation(finalLocation);
131 auto locatorCallback = request->GetLocatorCallBack();
132 if (locatorCallback != nullptr) {
133 LBSLOGI(REPORT_MANAGER, "report location to %{public}s, TimeSinceBoot : %{public}s",
134 request->GetPackageName().c_str(), std::to_string(finalLocation->GetTimeSinceBoot()).c_str());
135 locatorCallback->OnLocationReport(finalLocation);
136 // add location permission using record
137 PrivacyKit::AddPermissionUsedRecord(request->GetTokenId(), ACCESS_APPROXIMATELY_LOCATION, 1, 0);
138 }
139
140 int fixTime = request->GetRequestConfig()->GetFixNumber();
141 if (fixTime > 0) {
142 deadRequests->push_back(request);
143 return false;
144 }
145 return true;
146 }
147
GetPermittedLocation(pid_t uid,uint32_t tokenId,uint32_t firstTokenId,const std::unique_ptr<Location> & location)148 std::unique_ptr<Location> ReportManager::GetPermittedLocation(pid_t uid, uint32_t tokenId, uint32_t firstTokenId,
149 const std::unique_ptr<Location>& location)
150 {
151 if (location == nullptr) {
152 return nullptr;
153 }
154 std::string bundleName = "";
155 if (!CommonUtils::GetBundleNameByUid(uid, bundleName)) {
156 LBSLOGD(REPORT_MANAGER, "Fail to Get bundle name: uid = %{public}d.", uid);
157 }
158 if (DelayedSingleton<LocatorBackgroundProxy>::GetInstance().get()->IsAppBackground(bundleName) &&
159 !IsAppInLocationContinuousTasks(uid) &&
160 !CommonUtils::CheckBackgroundPermission(tokenId, firstTokenId)) {
161 //app background, no background permission, not ContinuousTasks
162 return nullptr;
163 }
164 if (!CommonUtils::CheckLocationPermission(tokenId, firstTokenId) &&
165 !CommonUtils::CheckApproximatelyPermission(tokenId, firstTokenId)) {
166 return nullptr;
167 }
168 std::unique_ptr<Location> finalLocation = std::make_unique<Location>(*location);
169 // for api8 and previous version, only ACCESS_LOCATION permission granted also report original location info.
170 if (!CommonUtils::CheckLocationPermission(tokenId, firstTokenId) &&
171 CommonUtils::CheckApproximatelyPermission(tokenId, firstTokenId)) {
172 finalLocation = ApproximatelyLocation(location);
173 }
174 return finalLocation;
175 }
176
ReportRemoteCallback(sptr<ILocatorCallback> & locatorCallback,int type,int result)177 bool ReportManager::ReportRemoteCallback(sptr<ILocatorCallback>& locatorCallback, int type, int result)
178 {
179 switch (type) {
180 case ILocatorCallback::RECEIVE_LOCATION_STATUS_EVENT: {
181 locatorCallback->OnLocatingStatusChange(result);
182 break;
183 }
184 case ILocatorCallback::RECEIVE_ERROR_INFO_EVENT: {
185 locatorCallback->OnErrorReport(result);
186 break;
187 }
188 default:
189 return false;
190 }
191 return true;
192 }
193
ResultCheck(const std::unique_ptr<Location> & location,const std::shared_ptr<Request> & request)194 bool ReportManager::ResultCheck(const std::unique_ptr<Location>& location,
195 const std::shared_ptr<Request>& request)
196 {
197 if (request == nullptr) {
198 return false;
199 }
200 if (location == nullptr) {
201 return false;
202 }
203 auto locatorAbility = DelayedSingleton<LocatorAbility>::GetInstance();
204 if (locatorAbility == nullptr) {
205 return false;
206 }
207 if (locatorAbility->IsProxyUid(request->GetUid())) {
208 LBSLOGE(REPORT_MANAGER, "uid:%{public}d is proxy by freeze, no need to report", request->GetUid());
209 return false;
210 }
211 int permissionLevel = CommonUtils::GetPermissionLevel(request->GetTokenId(), request->GetFirstTokenId());
212 if (request->GetLastLocation() == nullptr || request->GetRequestConfig() == nullptr) {
213 return true;
214 }
215 float maxAcc = request->GetRequestConfig()->GetMaxAccuracy();
216 LBSLOGD(REPORT_MANAGER, "acc ResultCheck : %{public}f - %{public}f", maxAcc, location->GetAccuracy());
217 if ((permissionLevel == PERMISSION_ACCURATE) &&
218 (maxAcc > 0) && (location->GetAccuracy() > maxAcc)) {
219 LBSLOGE(REPORT_MANAGER, "accuracy check fail, do not report location");
220 return false;
221 }
222 if (CommonUtils::DoubleEqual(request->GetLastLocation()->GetLatitude(), MIN_LATITUDE - 1)) {
223 LBSLOGD(REPORT_MANAGER, "no valid cache location, no need to check");
224 return true;
225 }
226 int minTime = request->GetRequestConfig()->GetTimeInterval();
227 long deltaMs = (location->GetTimeSinceBoot() - request->GetLastLocation()->GetTimeSinceBoot()) / NANOS_PER_MILLI;
228 LBSLOGD(REPORT_MANAGER, "timeInterval ResultCheck : %{public}s %{public}d - %{public}ld",
229 request->GetPackageName().c_str(), minTime, deltaMs);
230 if (deltaMs < (minTime * SEC_TO_MILLI_SEC - MAX_SA_SCHEDULING_JITTER_MS)) {
231 LBSLOGE(REPORT_MANAGER, "timeInterval check fail, do not report location, current deltaMs = %{public}ld",
232 deltaMs);
233 return false;
234 }
235
236 double distanceInterval = request->GetRequestConfig()->GetDistanceInterval();
237 double deltaDis = CommonUtils::CalDistance(location->GetLatitude(), location->GetLongitude(),
238 request->GetLastLocation()->GetLatitude(), request->GetLastLocation()->GetLongitude());
239 LBSLOGD(REPORT_MANAGER, "distanceInterval ResultCheck : %{public}lf - %{public}f", deltaDis, distanceInterval);
240 if (deltaDis - distanceInterval < 0) {
241 LBSLOGE(REPORT_MANAGER, "distanceInterval check fail, do not report location");
242 return false;
243 }
244 return true;
245 }
246
UpdateCacheLocation(const std::unique_ptr<Location> & location,std::string abilityName)247 void ReportManager::UpdateCacheLocation(const std::unique_ptr<Location>& location, std::string abilityName)
248 {
249 lastLocation_ = *location;
250 if (abilityName == GNSS_ABILITY) {
251 cacheGnssLocation_ = *location;
252 } else if (abilityName == NETWORK_ABILITY) {
253 cacheNlpLocation_ = *location;
254 }
255 }
256
GetLastLocation()257 std::unique_ptr<Location> ReportManager::GetLastLocation()
258 {
259 auto lastLocation = std::make_unique<Location>(lastLocation_);
260 if (CommonUtils::DoubleEqual(lastLocation->GetLatitude(), MIN_LATITUDE - 1)) {
261 LBSLOGE(REPORT_MANAGER, "%{public}s no valid cache location", __func__);
262 return nullptr;
263 }
264 return lastLocation;
265 }
266
GetCacheLocation(const std::shared_ptr<Request> & request)267 std::unique_ptr<Location> ReportManager::GetCacheLocation(const std::shared_ptr<Request>& request)
268 {
269 int64_t curTime = CommonUtils::GetCurrentTimeStamp();
270 std::unique_ptr<Location> cacheLocation = nullptr;
271 if (!CommonUtils::DoubleEqual(cacheGnssLocation_.GetLatitude(), MIN_LATITUDE - 1) &&
272 (curTime - cacheGnssLocation_.GetTimeStamp() / SEC_TO_MILLI_SEC) <= GNSS_FIX_CACHED_TIME) {
273 cacheLocation = std::make_unique<Location>(cacheGnssLocation_);
274 } else if (!CommonUtils::DoubleEqual(cacheNlpLocation_.GetLatitude(), MIN_LATITUDE - 1) &&
275 (curTime - cacheNlpLocation_.GetTimeStamp() / SEC_TO_MILLI_SEC) <= NLP_FIX_CACHED_TIME) {
276 cacheLocation = std::make_unique<Location>(cacheNlpLocation_);
277 }
278 std::unique_ptr<Location> finalLocation = GetPermittedLocation(request->GetUid(),
279 request->GetTokenId(), request->GetFirstTokenId(), cacheLocation);
280 if (!ResultCheck(finalLocation, request)) {
281 return nullptr;
282 }
283 UpdateLocationByRequest(request->GetTokenId(), request->GetTokenIdEx(), finalLocation);
284 return finalLocation;
285 }
286
UpdateRandom()287 void ReportManager::UpdateRandom()
288 {
289 auto locatorAbility = DelayedSingleton<LocatorAbility>::GetInstance();
290 if (locatorAbility == nullptr) {
291 return;
292 }
293 int num = locatorAbility->GetActiveRequestNum();
294 if (num > 0) {
295 LBSLOGD(REPORT_MANAGER, "Exists %{public}d active request, cannot refresh offset", num);
296 return;
297 }
298 struct timespec now;
299 clock_gettime(CLOCK_REALTIME, &now);
300 if (abs(now.tv_sec - lastUpdateTime_.tv_sec) > LONG_TIME_INTERVAL) {
301 offsetRandom_ = CommonUtils::DoubleRandom(0, 1);
302 }
303 }
304
ApproximatelyLocation(const std::unique_ptr<Location> & location)305 std::unique_ptr<Location> ReportManager::ApproximatelyLocation(const std::unique_ptr<Location>& location)
306 {
307 std::unique_ptr<Location> coarseLocation = std::make_unique<Location>(*location);
308 double startLat = coarseLocation->GetLatitude();
309 double startLon = coarseLocation->GetLongitude();
310 double brg = offsetRandom_ * DIS_FROMLL_PARAMETER * M_PI; // 2PI
311 double dist = offsetRandom_ * (MAXIMUM_FUZZY_LOCATION_DISTANCE -
312 MINIMUM_FUZZY_LOCATION_DISTANCE) + MINIMUM_FUZZY_LOCATION_DISTANCE;
313 double perlat = (DIS_FROMLL_PARAMETER * M_PI * EARTH_RADIUS) / DEGREE_DOUBLE_PI; // the radian value of per degree
314
315 double lat = startLat + (dist * sin(brg)) / perlat;
316 double lon;
317 if (cos(brg) < 0) {
318 lon = startLon - (dist * DEGREE_DOUBLE_PI) / (DIS_FROMLL_PARAMETER * M_PI * EARTH_RADIUS);
319 } else {
320 lon = startLon + (dist * DEGREE_DOUBLE_PI) / (DIS_FROMLL_PARAMETER * M_PI * EARTH_RADIUS);
321 }
322 if (lat < -MAX_LATITUDE) {
323 lat = -MAX_LATITUDE;
324 } else if (lat > MAX_LATITUDE) {
325 lat = MAX_LATITUDE;
326 } else {
327 lat = std::round(lat * std::pow(10, 8)) / std::pow(10, 8); // 8 decimal
328 }
329 if (lon < -MAX_LONGITUDE) {
330 lon = -MAX_LONGITUDE;
331 } else if (lon > MAX_LONGITUDE) {
332 lon = MAX_LONGITUDE;
333 } else {
334 lon = std::round(lon * std::pow(10, 8)) / std::pow(10, 8); // 8 decimal
335 }
336 coarseLocation->SetLatitude(lat);
337 coarseLocation->SetLongitude(lon);
338 coarseLocation->SetAccuracy(DEFAULT_APPROXIMATELY_ACCURACY); // approximately location acc
339 coarseLocation->SetAdditions("");
340 coarseLocation->SetAdditionSize(0);
341 return coarseLocation;
342 }
343
IsRequestFuse(const std::shared_ptr<Request> & request)344 bool ReportManager::IsRequestFuse(const std::shared_ptr<Request>& request)
345 {
346 if (request == nullptr || request->GetRequestConfig() == nullptr) {
347 return false;
348 }
349 if (request->GetRequestConfig()->GetScenario() == SCENE_UNSET &&
350 request->GetRequestConfig()->GetPriority() == PRIORITY_FAST_FIRST_FIX) {
351 return true;
352 }
353 return false;
354 }
355
WriteNetWorkReportEvent(std::string abilityName,const std::shared_ptr<Request> & request,const std::unique_ptr<Location> & location)356 void ReportManager::WriteNetWorkReportEvent(std::string abilityName, const std::shared_ptr<Request>& request,
357 const std::unique_ptr<Location>& location)
358 {
359 if (abilityName == NETWORK_ABILITY && request != nullptr) {
360 WriteLocationInnerEvent(RECEIVE_NETWORK_LOCATION, {
361 "PackageName", request->GetPackageName(),
362 "abilityName", abilityName,
363 "requestAddress", request->GetUuid(),
364 "latitude", std::to_string(location->GetLatitude()),
365 "longitude", std::to_string(location->GetLongitude()),
366 "accuracy", std::to_string(location->GetAccuracy())
367 });
368 }
369 }
370
IsAppInLocationContinuousTasks(pid_t uid)371 bool ReportManager::IsAppInLocationContinuousTasks(pid_t uid)
372 {
373 #ifdef BGTASKMGR_SUPPORT
374 std::vector<std::shared_ptr<BackgroundTaskMgr::ContinuousTaskCallbackInfo>> continuousTasks;
375 ErrCode result = BackgroundTaskMgr::BackgroundTaskMgrHelper::GetContinuousTaskApps(continuousTasks);
376 if (result != ERR_OK) {
377 return false;
378 }
379 for (auto iter = continuousTasks.begin(); iter != continuousTasks.end(); iter++) {
380 auto continuousTask = *iter;
381 if (continuousTask->GetCreatorUid() == uid &&
382 continuousTask->GetTypeId() == BackgroundTaskMgr::BackgroundMode::Type::LOCATION) {
383 return true;
384 }
385 }
386 #endif
387 return false;
388 }
389 } // namespace OHOS
390 } // namespace Location
391