• 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 
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 
27 namespace OHOS {
28 namespace Location {
29 const long NANOS_PER_MILLI = 1000000L;
30 const int SECOND_TO_MILLISECOND = 1000;
31 const int MAX_SA_SCHEDULING_JITTER_MS = 200;
32 static constexpr double MAXIMUM_FUZZY_LOCATION_DISTANCE = 4000.0; // Unit m
33 static constexpr double MINIMUM_FUZZY_LOCATION_DISTANCE = 3000.0; // Unit m
ReportManager()34 ReportManager::ReportManager()
35 {
36     clock_gettime(CLOCK_REALTIME, &lastUpdateTime_);
37     offsetRandom_ = CommonUtils::DoubleRandom(0, 1);
38 }
39 
~ReportManager()40 ReportManager::~ReportManager() {}
41 
OnReportLocation(const std::unique_ptr<Location> & location,std::string abilityName)42 bool ReportManager::OnReportLocation(const std::unique_ptr<Location>& location, std::string abilityName)
43 {
44     LBSLOGI(REPORT_MANAGER, "receive location : %{public}s", abilityName.c_str());
45     auto fusionController = DelayedSingleton<FusionController>::GetInstance();
46     if (fusionController == nullptr) {
47         return false;
48     }
49     fusionController->FuseResult(abilityName, location);
50     SetLastLocation(location);
51     LBSLOGI(REPORT_MANAGER, "after SetLastLocation");
52     auto locatorAbility = DelayedSingleton<LocatorAbility>::GetInstance();
53     if (locatorAbility == nullptr) {
54         return false;
55     }
56     auto requestMap = locatorAbility->GetRequests();
57     if (requestMap == nullptr) {
58         return false;
59     }
60     auto requestListIter = requestMap->find(abilityName);
61     if (requestListIter == requestMap->end()) {
62         return false;
63     }
64 
65     auto requestList = requestListIter->second;
66     auto deadRequests = std::make_unique<std::list<std::shared_ptr<Request>>>();
67     for (auto iter = requestList.begin(); iter != requestList.end(); iter++) {
68         auto request = *iter;
69         if (!ProcessRequestForReport(request, deadRequests, location)) {
70             continue;
71         }
72     }
73 
74     for (auto iter = deadRequests->begin(); iter != deadRequests->end(); ++iter) {
75         auto request = *iter;
76         if (request == nullptr) {
77             continue;
78         }
79         auto requestManger = DelayedSingleton<RequestManager>::GetInstance();
80         if (requestManger != nullptr) {
81             requestManger->UpdateRequestRecord(request, false);
82         }
83     }
84     locatorAbility->ApplyRequests();
85     deadRequests->clear();
86     return true;
87 }
88 
ProcessRequestForReport(std::shared_ptr<Request> & request,std::unique_ptr<std::list<std::shared_ptr<Request>>> & deadRequests,const std::unique_ptr<Location> & location)89 bool ReportManager::ProcessRequestForReport(std::shared_ptr<Request>& request,
90     std::unique_ptr<std::list<std::shared_ptr<Request>>>& deadRequests, const std::unique_ptr<Location>& location)
91 {
92     if (request == nullptr || request->GetRequestConfig() == nullptr ||
93         !request->GetIsRequesting()) {
94         return false;
95     }
96     std::unique_ptr<Location> finalLocation = GetPermittedLocation(request->GetUid(),
97         request->GetTokenId(), request->GetFirstTokenId(), location);
98     if (!ResultCheck(finalLocation, request)) {
99         return false;
100     }
101     request->SetLastLocation(finalLocation);
102     auto locatorCallback = request->GetLocatorCallBack();
103     if (locatorCallback != nullptr) {
104         locatorCallback->OnLocationReport(finalLocation);
105     }
106 
107     int fixTime = request->GetRequestConfig()->GetFixNumber();
108     if (fixTime > 0) {
109         deadRequests->push_back(request);
110         return false;
111     }
112     return true;
113 }
114 
GetPermittedLocation(pid_t uid,uint32_t tokenId,uint32_t firstTokenId,const std::unique_ptr<Location> & location)115 std::unique_ptr<Location> ReportManager::GetPermittedLocation(pid_t uid, uint32_t tokenId, uint32_t firstTokenId,
116     const std::unique_ptr<Location>& location)
117 {
118     if (location == nullptr) {
119         return nullptr;
120     }
121     std::string bundleName = "";
122     if (!CommonUtils::GetBundleNameByUid(uid, bundleName)) {
123         LBSLOGE(REPORT_MANAGER, "Fail to Get bundle name: uid = %{public}d.", uid);
124     }
125     std::unique_ptr<Location> finalLocation = std::make_unique<Location>(*location);
126     // for api8 and previous version, only ACCESS_LOCATION permission granted also report original location info.
127     if (!CommonUtils::CheckLocationPermission(tokenId, firstTokenId) &&
128         CommonUtils::CheckApproximatelyPermission(tokenId, firstTokenId)) {
129         finalLocation = ApproximatelyLocation(location);
130     } else if ((!CommonUtils::CheckLocationPermission(tokenId, firstTokenId) &&
131         !CommonUtils::CheckApproximatelyPermission(tokenId, firstTokenId)) ||
132         (DelayedSingleton<LocatorBackgroundProxy>::GetInstance().get()->IsAppBackground(bundleName) &&
133         !CommonUtils::CheckBackgroundPermission(tokenId, firstTokenId))) {
134         return nullptr;
135     }
136     return finalLocation;
137 }
138 
ReportRemoteCallback(sptr<ILocatorCallback> & locatorCallback,int type,int result)139 bool ReportManager::ReportRemoteCallback(sptr<ILocatorCallback>& locatorCallback, int type, int result)
140 {
141     switch (type) {
142         case ILocatorCallback::RECEIVE_LOCATION_STATUS_EVENT: {
143             locatorCallback->OnLocatingStatusChange(result);
144             break;
145         }
146         case ILocatorCallback::RECEIVE_ERROR_INFO_EVENT: {
147             locatorCallback->OnErrorReport(result);
148             break;
149         }
150         default:
151             return false;
152     }
153     return true;
154 }
155 
ResultCheck(const std::unique_ptr<Location> & location,const std::shared_ptr<Request> & request)156 bool ReportManager::ResultCheck(const std::unique_ptr<Location>& location,
157     const std::shared_ptr<Request>& request)
158 {
159     if (request == nullptr) {
160         return false;
161     }
162     if (location == nullptr) {
163         LBSLOGE(REPORT_MANAGER, "%{public}s has no access permission", request->GetPackageName().c_str());
164         return false;
165     }
166     auto locatorAbility = DelayedSingleton<LocatorAbility>::GetInstance();
167     if (locatorAbility == nullptr) {
168         return false;
169     }
170     if (locatorAbility->IsProxyUid(request->GetUid())) {
171         LBSLOGE(REPORT_MANAGER, "uid:%{public}d is proxy by freeze, no need to report", request->GetUid());
172         return false;
173     }
174     int permissionLevel = CommonUtils::GetPermissionLevel(request->GetTokenId(), request->GetFirstTokenId());
175     if (request->GetLastLocation() == nullptr || request->GetRequestConfig() == nullptr) {
176         return true;
177     }
178     float maxAcc = request->GetRequestConfig()->GetMaxAccuracy();
179     LBSLOGD(REPORT_MANAGER, "acc ResultCheck :  %{public}f - %{public}f", maxAcc, location->GetAccuracy());
180     if ((permissionLevel == PERMISSION_ACCURATE) &&
181         (maxAcc > 0) && (location->GetAccuracy() > maxAcc)) {
182         LBSLOGE(REPORT_MANAGER, "accuracy check fail, do not report location");
183         return false;
184     }
185     if (CommonUtils::DoubleEqual(request->GetLastLocation()->GetLatitude(), MIN_LATITUDE - 1)) {
186         LBSLOGE(REPORT_MANAGER, "no valid cache location, no need to check");
187         return true;
188     }
189     int minTime = request->GetRequestConfig()->GetTimeInterval();
190     long deltaMs = (location->GetTimeSinceBoot() - request->GetLastLocation()->GetTimeSinceBoot()) / NANOS_PER_MILLI;
191     LBSLOGD(REPORT_MANAGER, "timeInterval ResultCheck : %{public}s %{public}d - %{public}ld",
192         request->GetPackageName().c_str(), minTime, deltaMs);
193     if (deltaMs < (minTime * SECOND_TO_MILLISECOND - MAX_SA_SCHEDULING_JITTER_MS)) {
194         LBSLOGE(REPORT_MANAGER, "timeInterval check fail, do not report location");
195         return false;
196     }
197 
198     double distanceInterval = request->GetRequestConfig()->GetDistanceInterval();
199     double deltaDis = CommonUtils::CalDistance(location->GetLatitude(), location->GetLongitude(),
200         request->GetLastLocation()->GetLatitude(), request->GetLastLocation()->GetLongitude());
201     LBSLOGD(REPORT_MANAGER, "distanceInterval ResultCheck :  %{public}lf - %{public}f", deltaDis, distanceInterval);
202     if (deltaDis - distanceInterval < 0) {
203         LBSLOGE(REPORT_MANAGER, "distanceInterval check fail, do not report location");
204         return false;
205     }
206     return true;
207 }
208 
SetLastLocation(const std::unique_ptr<Location> & location)209 void ReportManager::SetLastLocation(const std::unique_ptr<Location>& location)
210 {
211     lastLocation_.SetLatitude(location->GetLatitude());
212     lastLocation_.SetLongitude(location->GetLongitude());
213     lastLocation_.SetAltitude(location->GetAltitude());
214     lastLocation_.SetAccuracy(location->GetAccuracy());
215     lastLocation_.SetSpeed(location->GetSpeed());
216     lastLocation_.SetDirection(location->GetDirection());
217     lastLocation_.SetTimeStamp(location->GetTimeStamp());
218     lastLocation_.SetTimeSinceBoot(location->GetTimeSinceBoot());
219 }
220 
GetLastLocation()221 std::unique_ptr<Location> ReportManager::GetLastLocation()
222 {
223     auto lastLocation = std::make_unique<Location>(lastLocation_);
224     if (CommonUtils::DoubleEqual(lastLocation->GetLatitude(), MIN_LATITUDE - 1)) {
225         LBSLOGE(REPORT_MANAGER, "no valid cache location");
226         return nullptr;
227     }
228     return lastLocation;
229 }
230 
UpdateRandom()231 void ReportManager::UpdateRandom()
232 {
233     auto locatorAbility = DelayedSingleton<LocatorAbility>::GetInstance();
234     if (locatorAbility == nullptr) {
235         return;
236     }
237     int num = locatorAbility->GetActiveRequestNum();
238     if (num > 0) {
239         LBSLOGE(REPORT_MANAGER, "Exists %{public}d active request, cannot refresh offset", num);
240         return;
241     }
242     struct timespec now;
243     clock_gettime(CLOCK_REALTIME, &now);
244     if (abs(now.tv_sec - lastUpdateTime_.tv_sec) > LONG_TIME_INTERVAL) {
245         offsetRandom_ = CommonUtils::DoubleRandom(0, 1);
246     }
247 }
248 
ApproximatelyLocation(const std::unique_ptr<Location> & location)249 std::unique_ptr<Location> ReportManager::ApproximatelyLocation(const std::unique_ptr<Location>& location)
250 {
251     std::unique_ptr<Location> coarseLocation = std::make_unique<Location>(*location);
252     double startLat = coarseLocation->GetLatitude();
253     double startLon = coarseLocation->GetLongitude();
254     double brg = offsetRandom_ * DIS_FROMLL_PARAMETER * M_PI; // 2PI
255     double dist = offsetRandom_ * (MAXIMUM_FUZZY_LOCATION_DISTANCE -
256         MINIMUM_FUZZY_LOCATION_DISTANCE) + MINIMUM_FUZZY_LOCATION_DISTANCE;
257     double perlat = (DIS_FROMLL_PARAMETER * M_PI * EARTH_RADIUS) / DEGREE_DOUBLE_PI; // the radian value of per degree
258 
259     double lat = startLat + (dist * sin(brg)) / perlat;
260     double lon;
261     if (cos(brg) < 0) {
262         lon = startLon - (dist * DEGREE_DOUBLE_PI) / (DIS_FROMLL_PARAMETER * M_PI * EARTH_RADIUS);
263     } else {
264         lon = startLon + (dist * DEGREE_DOUBLE_PI) / (DIS_FROMLL_PARAMETER * M_PI * EARTH_RADIUS);
265     }
266     if (lat < -MAX_LATITUDE) {
267         lat = -MAX_LATITUDE;
268     } else if (lat > MAX_LATITUDE) {
269         lat = MAX_LATITUDE;
270     } else {
271         lat = std::round(lat * std::pow(10, 8)) / std::pow(10, 8); // 8 decimal
272     }
273     if (lon < -MAX_LONGITUDE) {
274         lon = -MAX_LONGITUDE;
275     } else if (lon > MAX_LONGITUDE) {
276         lon = MAX_LONGITUDE;
277     } else {
278         lon = std::round(lon * std::pow(10, 8)) / std::pow(10, 8); // 8 decimal
279     }
280     coarseLocation->SetLatitude(lat);
281     coarseLocation->SetLongitude(lon);
282     coarseLocation->SetAccuracy(DEFAULT_APPROXIMATELY_ACCURACY); // approximately location acc
283     return coarseLocation;
284 }
285 } // namespace OHOS
286 } // namespace Location
287