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