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 #include "permission_manager.h"
29
30 #include "hook_utils.h"
31
32 namespace OHOS {
33 namespace Location {
34 const long NANOS_PER_MILLI = 1000000L;
35 const int MAX_SA_SCHEDULING_JITTER_MS = 200;
36 static constexpr double MAXIMUM_FUZZY_LOCATION_DISTANCE = 4000.0; // Unit m
37 static constexpr double MINIMUM_FUZZY_LOCATION_DISTANCE = 3000.0; // Unit m
38 static constexpr int GNSS_FIX_CACHED_TIME = 60;
39 static constexpr int NLP_FIX_CACHED_TIME = 45;
40
GetInstance()41 ReportManager* ReportManager::GetInstance()
42 {
43 static ReportManager data;
44 return &data;
45 }
46
ReportManager()47 ReportManager::ReportManager()
48 {
49 clock_gettime(CLOCK_REALTIME, &lastUpdateTime_);
50 offsetRandom_ = CommonUtils::DoubleRandom(0, 1);
51 }
52
~ReportManager()53 ReportManager::~ReportManager() {}
54
OnReportLocation(const std::unique_ptr<Location> & location,std::string abilityName)55 bool ReportManager::OnReportLocation(const std::unique_ptr<Location>& location, std::string abilityName)
56 {
57 auto fusionController = FusionController::GetInstance();
58 if (fusionController == nullptr) {
59 return false;
60 }
61 UpdateCacheLocation(location, abilityName);
62 auto locatorAbility = LocatorAbility::GetInstance();
63 if (locatorAbility == nullptr) {
64 return false;
65 }
66 auto requestMap = locatorAbility->GetRequests();
67 if (requestMap == nullptr) {
68 return false;
69 }
70 auto requestListIter = requestMap->find(abilityName);
71 if (requestListIter == requestMap->end()) {
72 return false;
73 }
74 auto requestList = requestListIter->second;
75 auto deadRequests = std::make_unique<std::list<std::shared_ptr<Request>>>();
76 for (auto iter = requestList.begin(); iter != requestList.end(); iter++) {
77 auto request = *iter;
78 WriteNetWorkReportEvent(abilityName, request, location);
79 if (abilityName == NETWORK_ABILITY) {
80 if (request->GetUuid() == location->GetUuid() || location->GetIsFromMock()) {
81 ProcessRequestForReport(request, deadRequests, location, abilityName);
82 break;
83 }
84 } else if (abilityName == GNSS_ABILITY || abilityName == PASSIVE_ABILITY) {
85 ProcessRequestForReport(request, deadRequests, location, abilityName);
86 }
87 }
88 for (auto iter = deadRequests->begin(); iter != deadRequests->end(); ++iter) {
89 auto request = *iter;
90 if (request == nullptr) {
91 continue;
92 }
93 auto requestManger = RequestManager::GetInstance();
94 if (requestManger != nullptr) {
95 requestManger->UpdateRequestRecord(request, false);
96 }
97 }
98 locatorAbility->ApplyRequests(1);
99 deadRequests->clear();
100 return true;
101 }
102
UpdateLocationByRequest(const uint32_t tokenId,const uint64_t tokenIdEx,std::unique_ptr<Location> & location)103 void ReportManager::UpdateLocationByRequest(const uint32_t tokenId, const uint64_t tokenIdEx,
104 std::unique_ptr<Location>& location)
105 {
106 if (location == nullptr) {
107 return;
108 }
109 if (!PermissionManager::CheckSystemPermission(tokenId, tokenIdEx)) {
110 location->SetIsSystemApp(0);
111 } else {
112 location->SetIsSystemApp(1);
113 }
114 }
115
ProcessRequestForReport(std::shared_ptr<Request> & request,std::unique_ptr<std::list<std::shared_ptr<Request>>> & deadRequests,const std::unique_ptr<Location> & location,std::string abilityName)116 bool ReportManager::ProcessRequestForReport(std::shared_ptr<Request>& request,
117 std::unique_ptr<std::list<std::shared_ptr<Request>>>& deadRequests,
118 const std::unique_ptr<Location>& location, std::string abilityName)
119 {
120 if (location == nullptr ||
121 request == nullptr || request->GetRequestConfig() == nullptr || !request->GetIsRequesting()) {
122 return false;
123 }
124 std::unique_ptr<Location> fuseLocation;
125 std::unique_ptr<Location> finalLocation;
126 if (IsRequestFuse(request)) {
127 auto fusionController = FusionController::GetInstance();
128 if (fusionController == nullptr) {
129 return false;
130 }
131 fuseLocation = fusionController->GetFuseLocation(location, request->GetBestLocation());
132 request->SetBestLocation(fuseLocation);
133 }
134 auto locatorAbility = LocatorAbility::GetInstance();
135 if (locatorAbility == nullptr) {
136 return false;
137 }
138 finalLocation = GetPermittedLocation(request, IsRequestFuse(request) ? fuseLocation : location);
139 if (!ResultCheck(finalLocation, request)) {
140 // add location permission using record
141 int permUsedType = request->GetPermUsedType();
142 locatorAbility->UpdatePermissionUsedRecord(request->GetTokenId(),
143 ACCESS_APPROXIMATELY_LOCATION, permUsedType, 0, 1);
144 return false;
145 }
146 UpdateLocationByRequest(request->GetTokenId(), request->GetTokenIdEx(), finalLocation);
147 finalLocation = ExecuteReportProcess(request, finalLocation, abilityName);
148 if (finalLocation == nullptr) {
149 LBSLOGE(REPORT_MANAGER, "%{public}s no need report location", __func__);
150 return false;
151 }
152 request->SetLastLocation(finalLocation);
153 auto locatorCallback = request->GetLocatorCallBack();
154 if (locatorCallback != nullptr) {
155 // add location permission using record
156 int ret = locatorAbility->UpdatePermissionUsedRecord(request->GetTokenId(),
157 ACCESS_APPROXIMATELY_LOCATION, request->GetPermUsedType(), 1, 0);
158 if (ret != ERRCODE_SUCCESS && locatorAbility->IsHapCaller(request->GetTokenId())) {
159 LBSLOGE(REPORT_MANAGER, "UpdatePermissionUsedRecord failed ret=%{public}d", ret);
160 return false;
161 }
162 LBSLOGI(REPORT_MANAGER, "report location to %{public}d, TimeSinceBoot : %{public}s, SourceType : %{public}d",
163 request->GetTokenId(), std::to_string(finalLocation->GetTimeSinceBoot()).c_str(),
164 finalLocation->GetLocationSourceType());
165 locatorCallback->OnLocationReport(finalLocation);
166 RequestManager::GetInstance()->UpdateLocationError(request);
167 }
168
169 int fixTime = request->GetRequestConfig()->GetFixNumber();
170 if (fixTime > 0) {
171 deadRequests->push_back(request);
172 return false;
173 }
174 return true;
175 }
176
ExecuteReportProcess(std::shared_ptr<Request> & request,std::unique_ptr<Location> & location,std::string abilityName)177 std::unique_ptr<Location> ReportManager::ExecuteReportProcess(std::shared_ptr<Request>& request,
178 std::unique_ptr<Location>& location, std::string abilityName)
179 {
180 LocationSupplicantInfo reportStruct;
181 reportStruct.request = *request;
182 reportStruct.location = *location;
183 reportStruct.abilityName = abilityName;
184 reportStruct.retCode = true;
185 HookUtils::ExecuteHook(
186 LocationProcessStage::LOCATOR_SA_LOCATION_REPORT_PROCESS, (void *)&reportStruct, nullptr);
187 if (!reportStruct.retCode) {
188 return nullptr;
189 }
190 return std::make_unique<Location>(reportStruct.location);
191 }
192
GetPermittedLocation(const std::shared_ptr<Request> & request,const std::unique_ptr<Location> & location)193 std::unique_ptr<Location> ReportManager::GetPermittedLocation(const std::shared_ptr<Request>& request,
194 const std::unique_ptr<Location>& location)
195 {
196 if (location == nullptr) {
197 return nullptr;
198 }
199 std::string bundleName = "";
200 auto tokenId = request->GetTokenId();
201 auto firstTokenId = request->GetFirstTokenId();
202 auto tokenIdEx = request->GetTokenIdEx();
203 auto uid = request->GetUid();
204 if (!CommonUtils::GetBundleNameByUid(uid, bundleName)) {
205 LBSLOGD(REPORT_MANAGER, "Fail to Get bundle name: uid = %{public}d.", uid);
206 }
207 if (IsAppBackground(bundleName, tokenId, tokenIdEx, uid) &&
208 !PermissionManager::CheckBackgroundPermission(tokenId, firstTokenId)) {
209 //app background, no background permission, not ContinuousTasks
210 RequestManager::GetInstance()->ReportLocationError(LOCATING_FAILED_BACKGROUND_PERMISSION_DENIED, request);
211 return nullptr;
212 }
213 if (!PermissionManager::CheckSystemPermission(tokenId, tokenIdEx) &&
214 !CommonUtils::CheckAppForUser(uid)) {
215 return nullptr;
216 }
217 std::unique_ptr<Location> finalLocation = std::make_unique<Location>(*location);
218 // for api8 and previous version, only ACCESS_LOCATION permission granted also report original location info.
219 if (PermissionManager::CheckLocationPermission(tokenId, firstTokenId)) {
220 return finalLocation;
221 }
222 if (PermissionManager::CheckApproximatelyPermission(tokenId, firstTokenId)) {
223 LBSLOGI(REPORT_MANAGER, "%{public}d has ApproximatelyLocation permission", tokenId);
224 finalLocation = ApproximatelyLocation(location);
225 return finalLocation;
226 }
227 LBSLOGE(REPORT_MANAGER, "%{public}d has no location permission failed", tokenId);
228 RequestManager::GetInstance()->ReportLocationError(LOCATING_FAILED_LOCATION_PERMISSION_DENIED, request);
229 return nullptr;
230 }
231
ReportRemoteCallback(sptr<ILocatorCallback> & locatorCallback,int type,int result)232 bool ReportManager::ReportRemoteCallback(sptr<ILocatorCallback>& locatorCallback, int type, int result)
233 {
234 switch (type) {
235 case ILocatorCallback::RECEIVE_LOCATION_STATUS_EVENT: {
236 locatorCallback->OnLocatingStatusChange(result);
237 break;
238 }
239 case ILocatorCallback::RECEIVE_ERROR_INFO_EVENT: {
240 locatorCallback->OnErrorReport(result);
241 break;
242 }
243 default:
244 return false;
245 }
246 return true;
247 }
248
ResultCheck(const std::unique_ptr<Location> & location,const std::shared_ptr<Request> & request)249 bool ReportManager::ResultCheck(const std::unique_ptr<Location>& location,
250 const std::shared_ptr<Request>& request)
251 {
252 if (request == nullptr) {
253 return false;
254 }
255 if (location == nullptr) {
256 return false;
257 }
258 auto locatorAbility = LocatorAbility::GetInstance();
259 if (locatorAbility == nullptr) {
260 return false;
261 }
262 if (locatorAbility->IsProxyPid(request->GetPid())) {
263 LBSLOGE(REPORT_MANAGER, "pid:%{public}d is proxy by freeze, no need to report", request->GetPid());
264 return false;
265 }
266 int permissionLevel = PermissionManager::GetPermissionLevel(request->GetTokenId(), request->GetFirstTokenId());
267 if (request->GetLastLocation() == nullptr || request->GetRequestConfig() == nullptr) {
268 return true;
269 }
270 float maxAcc = request->GetRequestConfig()->GetMaxAccuracy();
271 LBSLOGD(REPORT_MANAGER, "acc ResultCheck : %{public}f - %{public}f", maxAcc, location->GetAccuracy());
272 if ((permissionLevel == PERMISSION_ACCURATE) &&
273 (maxAcc > 0) && (location->GetAccuracy() > maxAcc)) {
274 LBSLOGE(REPORT_MANAGER, "accuracy check fail, do not report location");
275 return false;
276 }
277 if (CommonUtils::DoubleEqual(request->GetLastLocation()->GetLatitude(), MIN_LATITUDE - 1) ||
278 request->GetLastLocation()->GetIsFromMock() != location->GetIsFromMock()) {
279 LBSLOGD(REPORT_MANAGER, "no valid cache location, no need to check");
280 return true;
281 }
282 int minTime = request->GetRequestConfig()->GetTimeInterval();
283 long deltaMs = (location->GetTimeSinceBoot() - request->GetLastLocation()->GetTimeSinceBoot()) / NANOS_PER_MILLI;
284 if (deltaMs < (minTime * MILLI_PER_SEC - MAX_SA_SCHEDULING_JITTER_MS)) {
285 LBSLOGE(REPORT_MANAGER,
286 "%{public}d timeInterval check fail, do not report location, current deltaMs = %{public}ld",
287 request->GetTokenId(), deltaMs);
288 return false;
289 }
290
291 double distanceInterval = request->GetRequestConfig()->GetDistanceInterval();
292 double deltaDis = CommonUtils::CalDistance(location->GetLatitude(), location->GetLongitude(),
293 request->GetLastLocation()->GetLatitude(), request->GetLastLocation()->GetLongitude());
294 if (deltaDis - distanceInterval < 0) {
295 LBSLOGE(REPORT_MANAGER, "%{public}d distanceInterval check fail, do not report location",
296 request->GetTokenId());
297 return false;
298 }
299 return true;
300 }
301
UpdateCacheLocation(const std::unique_ptr<Location> & location,std::string abilityName)302 void ReportManager::UpdateCacheLocation(const std::unique_ptr<Location>& location, std::string abilityName)
303 {
304 if (abilityName == GNSS_ABILITY) {
305 if (HookUtils::CheckGnssLocationValidity(location)) {
306 cacheGnssLocation_ = *location;
307 UpdateLastLocation(location);
308 }
309 } else if (abilityName == NETWORK_ABILITY &&
310 location->GetLocationSourceType() != LocationSourceType::INDOOR_TYPE) {
311 cacheNlpLocation_ = *location;
312 UpdateLastLocation(location);
313 } else {
314 UpdateLastLocation(location);
315 }
316 }
317
UpdateLastLocation(const std::unique_ptr<Location> & location)318 void ReportManager::UpdateLastLocation(const std::unique_ptr<Location>& location)
319 {
320 int currentUserId = 0;
321 if (CommonUtils::GetCurrentUserId(currentUserId)) {
322 std::unique_lock<std::mutex> lock(lastLocationMutex_);
323 lastLocationsMap_[currentUserId] = std::make_shared<Location>(*location);
324 }
325 }
326
GetLastLocation()327 std::unique_ptr<Location> ReportManager::GetLastLocation()
328 {
329 int currentUserId = 0;
330 if (CommonUtils::GetCurrentUserId(currentUserId)) {
331 std::unique_lock<std::mutex> lock(lastLocationMutex_);
332 auto iter = lastLocationsMap_.find(currentUserId);
333 if (iter == lastLocationsMap_.end()) {
334 return nullptr;
335 }
336 std::unique_ptr<Location> lastLocation = std::make_unique<Location>(*(iter->second));
337 if (CommonUtils::DoubleEqual(lastLocation->GetLatitude(), MIN_LATITUDE - 1)) {
338 return nullptr;
339 }
340 return lastLocation;
341 }
342 return nullptr;
343 }
344
GetCacheLocation(const std::shared_ptr<Request> & request)345 std::unique_ptr<Location> ReportManager::GetCacheLocation(const std::shared_ptr<Request>& request)
346 {
347 int64_t curTime = CommonUtils::GetCurrentTimeStamp();
348 std::unique_ptr<Location> cacheLocation = nullptr;
349 if (!CommonUtils::DoubleEqual(cacheGnssLocation_.GetLatitude(), MIN_LATITUDE - 1) &&
350 (curTime - cacheGnssLocation_.GetTimeStamp() / MILLI_PER_SEC) <= GNSS_FIX_CACHED_TIME) {
351 cacheLocation = std::make_unique<Location>(cacheGnssLocation_);
352 } else if (!CommonUtils::DoubleEqual(cacheNlpLocation_.GetLatitude(), MIN_LATITUDE - 1) &&
353 (curTime - cacheNlpLocation_.GetTimeStamp() / MILLI_PER_SEC) <= NLP_FIX_CACHED_TIME) {
354 cacheLocation = std::make_unique<Location>(cacheNlpLocation_);
355 }
356 std::unique_ptr<Location> finalLocation = GetPermittedLocation(request, cacheLocation);
357 if (!ResultCheck(finalLocation, request)) {
358 return nullptr;
359 }
360 UpdateLocationByRequest(request->GetTokenId(), request->GetTokenIdEx(), finalLocation);
361 return finalLocation;
362 }
363
UpdateRandom()364 void ReportManager::UpdateRandom()
365 {
366 auto locatorAbility = LocatorAbility::GetInstance();
367 if (locatorAbility == nullptr) {
368 return;
369 }
370 int num = locatorAbility->GetActiveRequestNum();
371 if (num > 0) {
372 LBSLOGD(REPORT_MANAGER, "Exists %{public}d active request, cannot refresh offset", num);
373 return;
374 }
375 struct timespec now;
376 clock_gettime(CLOCK_REALTIME, &now);
377 if (abs(now.tv_sec - lastUpdateTime_.tv_sec) > LONG_TIME_INTERVAL) {
378 offsetRandom_ = CommonUtils::DoubleRandom(0, 1);
379 }
380 }
381
ApproximatelyLocation(const std::unique_ptr<Location> & location)382 std::unique_ptr<Location> ReportManager::ApproximatelyLocation(const std::unique_ptr<Location>& location)
383 {
384 std::unique_ptr<Location> coarseLocation = std::make_unique<Location>(*location);
385 double startLat = coarseLocation->GetLatitude();
386 double startLon = coarseLocation->GetLongitude();
387 double brg = offsetRandom_ * DIS_FROMLL_PARAMETER * M_PI; // 2PI
388 double dist = offsetRandom_ * (MAXIMUM_FUZZY_LOCATION_DISTANCE -
389 MINIMUM_FUZZY_LOCATION_DISTANCE) + MINIMUM_FUZZY_LOCATION_DISTANCE;
390 double perlat = (DIS_FROMLL_PARAMETER * M_PI * EARTH_RADIUS) / DEGREE_DOUBLE_PI; // the radian value of per degree
391
392 double lat = startLat + (dist * sin(brg)) / perlat;
393 double lon;
394 if (cos(brg) < 0) {
395 lon = startLon - (dist * DEGREE_DOUBLE_PI) / (DIS_FROMLL_PARAMETER * M_PI * EARTH_RADIUS);
396 } else {
397 lon = startLon + (dist * DEGREE_DOUBLE_PI) / (DIS_FROMLL_PARAMETER * M_PI * EARTH_RADIUS);
398 }
399 if (lat < -MAX_LATITUDE) {
400 lat = -MAX_LATITUDE;
401 } else if (lat > MAX_LATITUDE) {
402 lat = MAX_LATITUDE;
403 } else {
404 lat = std::round(lat * std::pow(10, 8)) / std::pow(10, 8); // 8 decimal
405 }
406 if (lon < -MAX_LONGITUDE) {
407 lon = -MAX_LONGITUDE;
408 } else if (lon > MAX_LONGITUDE) {
409 lon = MAX_LONGITUDE;
410 } else {
411 lon = std::round(lon * std::pow(10, 8)) / std::pow(10, 8); // 8 decimal
412 }
413 coarseLocation->SetLatitude(lat);
414 coarseLocation->SetLongitude(lon);
415 coarseLocation->SetAccuracy(DEFAULT_APPROXIMATELY_ACCURACY); // approximately location acc
416 std::vector<std::string> emptyAdds;
417 coarseLocation->SetAdditions(emptyAdds, false);
418 coarseLocation->SetAdditionSize(0);
419 return coarseLocation;
420 }
421
IsRequestFuse(const std::shared_ptr<Request> & request)422 bool ReportManager::IsRequestFuse(const std::shared_ptr<Request>& request)
423 {
424 if (request == nullptr || request->GetRequestConfig() == nullptr) {
425 return false;
426 }
427 if ((request->GetRequestConfig()->GetScenario() == SCENE_UNSET &&
428 request->GetRequestConfig()->GetPriority() == PRIORITY_LOW_POWER) ||
429 request->GetRequestConfig()->GetScenario() == SCENE_NO_POWER ||
430 request->GetRequestConfig()->GetScenario() == SCENE_DAILY_LIFE_SERVICE ||
431 request->GetRequestConfig()->GetScenario() == LOCATION_SCENE_DAILY_LIFE_SERVICE ||
432 request->GetRequestConfig()->GetScenario() == LOCATION_SCENE_LOW_POWER_CONSUMPTION ||
433 request->GetRequestConfig()->GetScenario() == LOCATION_SCENE_NO_POWER_CONSUMPTION) {
434 return false;
435 }
436 return true;
437 }
438
WriteNetWorkReportEvent(std::string abilityName,const std::shared_ptr<Request> & request,const std::unique_ptr<Location> & location)439 void ReportManager::WriteNetWorkReportEvent(std::string abilityName, const std::shared_ptr<Request>& request,
440 const std::unique_ptr<Location>& location)
441 {
442 if (abilityName == NETWORK_ABILITY && request != nullptr) {
443 WriteLocationInnerEvent(RECEIVE_NETWORK_LOCATION, {
444 "PackageName", request->GetPackageName(),
445 "abilityName", abilityName,
446 "requestAddress", request->GetUuid(),
447 "latitude", std::to_string(location->GetLatitude()),
448 "longitude", std::to_string(location->GetLongitude()),
449 "accuracy", std::to_string(location->GetAccuracy())
450 });
451 }
452 }
453
IsAppBackground(std::string bundleName,uint32_t tokenId,uint64_t tokenIdEx,int32_t uid)454 bool ReportManager::IsAppBackground(std::string bundleName, uint32_t tokenId, uint64_t tokenIdEx, int32_t uid)
455 {
456 auto locatorBackgroundProxy = LocatorBackgroundProxy::GetInstance();
457 if (locatorBackgroundProxy == nullptr) {
458 return false;
459 }
460 if (!locatorBackgroundProxy->IsAppBackground(bundleName)) {
461 return false;
462 }
463 if (locatorBackgroundProxy->IsAppHasFormVisible(tokenId, tokenIdEx)) {
464 return false;
465 }
466 if (locatorBackgroundProxy->IsAppInLocationContinuousTasks(uid)) {
467 return false;
468 }
469 return true;
470 }
471 } // namespace OHOS
472 } // namespace Location
473