• 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 
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