Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: content/browser/geolocation/gps_location_provider_linux.cc

Issue 25752005: Geolocation: delete GpsLocationProvider and third_party/gpsd/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/geolocation/gps_location_provider_linux.h"
6
7 #include <errno.h>
8
9 #include <algorithm>
10 #include <cmath>
11
12 #include "base/bind.h"
13 #include "base/compiler_specific.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/strings/stringprintf.h"
18 #include "content/public/common/geoposition.h"
19
20 namespace content {
21 namespace {
22
23 const int kGpsdReconnectRetryIntervalMillis = 10 * 1000;
24
25 // As per http://gpsd.berlios.de/performance.html#id374524, poll twice per sec.
26 const int kPollPeriodMovingMillis = 500;
27
28 // Poll less frequently whilst stationary.
29 const int kPollPeriodStationaryMillis = kPollPeriodMovingMillis * 3;
30
31 // GPS reading must differ by more than this amount to be considered movement.
32 const int kMovementThresholdMeters = 20;
33
34 // This algorithm is reused from the corresponding code in the Gears project.
35 // The arbitrary delta is decreased (Gears used 100 meters); if we need to
36 // decrease it any further we'll likely want to do some smarter filtering to
37 // remove GPS location jitter noise.
38 bool PositionsDifferSiginificantly(const Geoposition& position_1,
39 const Geoposition& position_2) {
40 const bool pos_1_valid = position_1.Validate();
41 if (pos_1_valid != position_2.Validate())
42 return true;
43 if (!pos_1_valid) {
44 DCHECK(!position_2.Validate());
45 return false;
46 }
47 double delta = std::sqrt(
48 std::pow(std::fabs(position_1.latitude - position_2.latitude), 2) +
49 std::pow(std::fabs(position_1.longitude - position_2.longitude), 2));
50 // Convert to meters. 1 minute of arc of latitude (or longitude at the
51 // equator) is 1 nautical mile or 1852m.
52 delta *= 60 * 1852;
53 return delta > kMovementThresholdMeters;
54 }
55
56 } // namespace
57
58 #if defined(USE_LIBGPS)
59
60 // See http://crbug.com/103751.
61 COMPILE_ASSERT(GPSD_API_MAJOR_VERSION == 5, GPSD_API_version_is_not_5);
62
63 namespace {
64
65 const char kLibGpsName[] = "libgps.so.20";
66
67 } // namespace
68
69 LibGps::LibGps()
70 : gps_data_(new gps_data_t),
71 is_open_(false) {
72 }
73
74 LibGps::~LibGps() {
75 Stop();
76 }
77
78 LibGps* LibGps::New() {
79 scoped_ptr<LibGps> libgps(new LibGps);
80 if (!libgps->libgps_loader_.Load(kLibGpsName))
81 return NULL;
82
83 return libgps.release();
84 }
85
86 bool LibGps::Start() {
87 if (is_open_)
88 return true;
89
90 errno = 0;
91 if (libgps_loader_.gps_open(GPSD_SHARED_MEMORY, 0, gps_data_.get()) != 0) {
92 // See gps.h NL_NOxxx for definition of gps_open() error numbers.
93 DLOG(WARNING) << "gps_open() failed " << errno;
94 return false;
95 }
96
97 is_open_ = true;
98 return true;
99 }
100
101 void LibGps::Stop() {
102 if (is_open_)
103 libgps_loader_.gps_close(gps_data_.get());
104 is_open_ = false;
105 }
106
107 bool LibGps::Read(Geoposition* position) {
108 DCHECK(position);
109 position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
110 if (!is_open_) {
111 DLOG(WARNING) << "No gpsd connection";
112 position->error_message = "No gpsd connection";
113 return false;
114 }
115
116 if (libgps_loader_.gps_read(gps_data_.get()) < 0) {
117 DLOG(WARNING) << "gps_read() fails";
118 position->error_message = "gps_read() fails";
119 return false;
120 }
121
122 if (!GetPositionIfFixed(position)) {
123 DLOG(WARNING) << "No fixed position";
124 position->error_message = "No fixed position";
125 return false;
126 }
127
128 position->error_code = Geoposition::ERROR_CODE_NONE;
129 position->timestamp = base::Time::Now();
130 if (!position->Validate()) {
131 // GetPositionIfFixed returned true, yet we've not got a valid fix.
132 // This shouldn't happen; something went wrong in the conversion.
133 NOTREACHED() << "Invalid position from GetPositionIfFixed: lat,long "
134 << position->latitude << "," << position->longitude
135 << " accuracy " << position->accuracy << " time "
136 << position->timestamp.ToDoubleT();
137 position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
138 position->error_message = "Bad fix from gps";
139 return false;
140 }
141 return true;
142 }
143
144 bool LibGps::GetPositionIfFixed(Geoposition* position) {
145 DCHECK(position);
146 if (gps_data_->status == STATUS_NO_FIX) {
147 DVLOG(2) << "Status_NO_FIX";
148 return false;
149 }
150
151 if (isnan(gps_data_->fix.latitude) || isnan(gps_data_->fix.longitude)) {
152 DVLOG(2) << "No valid lat/lon value";
153 return false;
154 }
155
156 position->latitude = gps_data_->fix.latitude;
157 position->longitude = gps_data_->fix.longitude;
158
159 if (!isnan(gps_data_->fix.epx) && !isnan(gps_data_->fix.epy)) {
160 position->accuracy = std::max(gps_data_->fix.epx, gps_data_->fix.epy);
161 } else if (isnan(gps_data_->fix.epx) && !isnan(gps_data_->fix.epy)) {
162 position->accuracy = gps_data_->fix.epy;
163 } else if (!isnan(gps_data_->fix.epx) && isnan(gps_data_->fix.epy)) {
164 position->accuracy = gps_data_->fix.epx;
165 } else {
166 // TODO(joth): Fixme. This is a workaround for http://crbug.com/99326
167 DVLOG(2) << "libgps reported accuracy NaN, forcing to zero";
168 position->accuracy = 0;
169 }
170
171 if (gps_data_->fix.mode == MODE_3D && !isnan(gps_data_->fix.altitude)) {
172 position->altitude = gps_data_->fix.altitude;
173 if (!isnan(gps_data_->fix.epv))
174 position->altitude_accuracy = gps_data_->fix.epv;
175 }
176
177 if (!isnan(gps_data_->fix.track))
178 position->heading = gps_data_->fix.track;
179 if (!isnan(gps_data_->fix.speed))
180 position->speed = gps_data_->fix.speed;
181 return true;
182 }
183
184 #else // !defined(USE_LIBGPS)
185
186 // Stub implementation of LibGps.
187 LibGps::LibGps() {
188 }
189
190 LibGps::~LibGps() {
191 }
192
193 LibGps* LibGps::New() {
194 return NULL;
195 }
196
197 bool LibGps::Start() {
198 return false;
199 }
200
201 void LibGps::Stop() {
202 }
203
204 bool LibGps::Read(Geoposition* position) {
205 return false;
206 }
207
208 bool LibGps::GetPositionIfFixed(Geoposition* position) {
209 return false;
210 }
211
212 #endif // !defined(USE_LIBGPS)
213
214 GpsLocationProviderLinux::GpsLocationProviderLinux(LibGpsFactory libgps_factory)
215 : gpsd_reconnect_interval_millis_(kGpsdReconnectRetryIntervalMillis),
216 poll_period_moving_millis_(kPollPeriodMovingMillis),
217 poll_period_stationary_millis_(kPollPeriodStationaryMillis),
218 libgps_factory_(libgps_factory),
219 weak_factory_(this) {
220 DCHECK(libgps_factory_);
221 }
222
223 GpsLocationProviderLinux::~GpsLocationProviderLinux() {
224 }
225
226 bool GpsLocationProviderLinux::StartProvider(bool high_accuracy) {
227 if (!high_accuracy) {
228 StopProvider();
229 return true; // Not an error condition, so still return true.
230 }
231 if (gps_ != NULL) {
232 DCHECK(weak_factory_.HasWeakPtrs());
233 return true;
234 }
235 position_.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
236 gps_.reset(libgps_factory_());
237 if (gps_ == NULL) {
238 DLOG(WARNING) << "libgps could not be loaded";
239 return false;
240 }
241 ScheduleNextGpsPoll(0);
242 return true;
243 }
244
245 void GpsLocationProviderLinux::StopProvider() {
246 weak_factory_.InvalidateWeakPtrs();
247 gps_.reset();
248 }
249
250 void GpsLocationProviderLinux::GetPosition(Geoposition* position) {
251 DCHECK(position);
252 *position = position_;
253 DCHECK(position->Validate() ||
254 position->error_code != Geoposition::ERROR_CODE_NONE);
255 }
256
257 void GpsLocationProviderLinux::RequestRefresh() {
258 ScheduleNextGpsPoll(0);
259 }
260
261 void GpsLocationProviderLinux::OnPermissionGranted() {
262 }
263
264 void GpsLocationProviderLinux::DoGpsPollTask() {
265 if (!gps_->Start()) {
266 DLOG(WARNING) << "Couldn't start GPS provider.";
267 ScheduleNextGpsPoll(gpsd_reconnect_interval_millis_);
268 return;
269 }
270
271 Geoposition new_position;
272 if (!gps_->Read(&new_position)) {
273 ScheduleNextGpsPoll(poll_period_stationary_millis_);
274 return;
275 }
276
277 DCHECK(new_position.Validate() ||
278 new_position.error_code != Geoposition::ERROR_CODE_NONE);
279 const bool differ = PositionsDifferSiginificantly(position_, new_position);
280 ScheduleNextGpsPoll(differ ? poll_period_moving_millis_ :
281 poll_period_stationary_millis_);
282 if (differ || new_position.error_code != Geoposition::ERROR_CODE_NONE) {
283 // Update if the new location is interesting or we have an error to report.
284 position_ = new_position;
285 NotifyCallback(position_);
286 }
287 }
288
289 void GpsLocationProviderLinux::ScheduleNextGpsPoll(int interval) {
290 weak_factory_.InvalidateWeakPtrs();
291 base::MessageLoop::current()->PostDelayedTask(
292 FROM_HERE,
293 base::Bind(&GpsLocationProviderLinux::DoGpsPollTask,
294 weak_factory_.GetWeakPtr()),
295 base::TimeDelta::FromMilliseconds(interval));
296 }
297
298 LocationProvider* NewSystemLocationProvider() {
299 return new GpsLocationProviderLinux(LibGps::New);
300 }
301
302 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698