• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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