| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright (c) 2010 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 <algorithm> |  | 
| 8 #include <cmath> |  | 
| 9 |  | 
| 10 #include "base/compiler_specific.h" |  | 
| 11 #include "base/logging.h" |  | 
| 12 #include "base/message_loop.h" |  | 
| 13 #include "content/browser/geolocation/libgps_wrapper_linux.h" |  | 
| 14 |  | 
| 15 namespace { |  | 
| 16 const int kGpsdReconnectRetryIntervalMillis = 10 * 1000; |  | 
| 17 // As per http://gpsd.berlios.de/performance.html#id374524, poll twice per sec. |  | 
| 18 const int kPollPeriodMovingMillis = 500; |  | 
| 19 // Poll less frequently whilst stationary. |  | 
| 20 const int kPollPeriodStationaryMillis = kPollPeriodMovingMillis * 3; |  | 
| 21 // GPS reading must differ by more than this amount to be considered movement. |  | 
| 22 const int kMovementThresholdMeters = 20; |  | 
| 23 |  | 
| 24 // This algorithm is reused from the corresponding code in the gears project. |  | 
| 25 // The arbitrary delta is decreased (gears used 100 meters); if we need to |  | 
| 26 // decrease it any further we'll likely want to do some smarter filtering to |  | 
| 27 // remove GPS location jitter noise. |  | 
| 28 bool PositionsDifferSiginificantly(const Geoposition& position_1, |  | 
| 29                                    const Geoposition& position_2) { |  | 
| 30   const bool pos_1_valid = position_1.IsValidFix(); |  | 
| 31   if (pos_1_valid != position_2.IsValidFix()) |  | 
| 32     return true; |  | 
| 33   if (!pos_1_valid) { |  | 
| 34     DCHECK(!position_2.IsValidFix()); |  | 
| 35     return false; |  | 
| 36   } |  | 
| 37   double delta = std::sqrt( |  | 
| 38       std::pow(std::fabs(position_1.latitude - position_2.latitude), 2) + |  | 
| 39       std::pow(std::fabs(position_1.longitude - position_2.longitude), 2)); |  | 
| 40   // Convert to meters. 1 minute of arc of latitude (or longitude at the |  | 
| 41   // equator) is 1 nautical mile or 1852m. |  | 
| 42   delta *= 60 * 1852; |  | 
| 43   return delta > kMovementThresholdMeters; |  | 
| 44 } |  | 
| 45 }  // namespace |  | 
| 46 |  | 
| 47 GpsLocationProviderLinux::GpsLocationProviderLinux(LibGpsFactory libgps_factory) |  | 
| 48     : libgps_factory_(libgps_factory), |  | 
| 49       ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) { |  | 
| 50   DCHECK(libgps_factory_); |  | 
| 51 } |  | 
| 52 |  | 
| 53 GpsLocationProviderLinux::~GpsLocationProviderLinux() { |  | 
| 54 } |  | 
| 55 |  | 
| 56 bool GpsLocationProviderLinux::StartProvider(bool high_accuracy) { |  | 
| 57   if (!high_accuracy) { |  | 
| 58     StopProvider(); |  | 
| 59     return true;  // Not an error condition, so still return true. |  | 
| 60   } |  | 
| 61   if (gps_ != NULL) { |  | 
| 62     DCHECK(!task_factory_.empty()); |  | 
| 63     return true; |  | 
| 64   } |  | 
| 65   position_.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; |  | 
| 66   gps_.reset(libgps_factory_()); |  | 
| 67   if (gps_ == NULL) { |  | 
| 68     DLOG(WARNING) << "libgps.so could not be loaded"; |  | 
| 69     return false; |  | 
| 70   } |  | 
| 71   ScheduleNextGpsPoll(0); |  | 
| 72   return true; |  | 
| 73 } |  | 
| 74 |  | 
| 75 void GpsLocationProviderLinux::StopProvider() { |  | 
| 76   task_factory_.RevokeAll(); |  | 
| 77   gps_.reset(); |  | 
| 78 } |  | 
| 79 |  | 
| 80 void GpsLocationProviderLinux::GetPosition(Geoposition* position) { |  | 
| 81   DCHECK(position); |  | 
| 82   *position = position_; |  | 
| 83   DCHECK(position->IsInitialized()); |  | 
| 84 } |  | 
| 85 |  | 
| 86 void GpsLocationProviderLinux::UpdatePosition() { |  | 
| 87   ScheduleNextGpsPoll(0); |  | 
| 88 } |  | 
| 89 |  | 
| 90 void GpsLocationProviderLinux::OnPermissionGranted( |  | 
| 91     const GURL& requesting_frame) { |  | 
| 92 } |  | 
| 93 |  | 
| 94 void GpsLocationProviderLinux::DoGpsPollTask() { |  | 
| 95   if (!gps_->Start()) { |  | 
| 96     DLOG(WARNING) << "Couldn't start GPS provider."; |  | 
| 97     ScheduleNextGpsPoll(kGpsdReconnectRetryIntervalMillis); |  | 
| 98     return; |  | 
| 99   } |  | 
| 100   if (!gps_->Poll()) { |  | 
| 101     ScheduleNextGpsPoll(kPollPeriodStationaryMillis); |  | 
| 102     return; |  | 
| 103   } |  | 
| 104   Geoposition new_position; |  | 
| 105   gps_->GetPosition(&new_position); |  | 
| 106   DCHECK(new_position.IsInitialized()); |  | 
| 107   const bool differ = PositionsDifferSiginificantly(position_, new_position); |  | 
| 108   ScheduleNextGpsPoll(differ ? kPollPeriodMovingMillis : |  | 
| 109                                kPollPeriodStationaryMillis); |  | 
| 110   if (differ || new_position.error_code != Geoposition::ERROR_CODE_NONE) { |  | 
| 111     // Update if the new location is interesting or we have an error to report. |  | 
| 112     position_ = new_position; |  | 
| 113     UpdateListeners(); |  | 
| 114   } |  | 
| 115 } |  | 
| 116 |  | 
| 117 void GpsLocationProviderLinux::ScheduleNextGpsPoll(int interval) { |  | 
| 118   task_factory_.RevokeAll(); |  | 
| 119   MessageLoop::current()->PostDelayedTask( |  | 
| 120       FROM_HERE, |  | 
| 121       task_factory_.NewRunnableMethod(&GpsLocationProviderLinux::DoGpsPollTask), |  | 
| 122       interval); |  | 
| 123 } |  | 
| 124 |  | 
| 125 LocationProviderBase* NewSystemLocationProvider() { |  | 
| 126   return new GpsLocationProviderLinux(LibGps::New); |  | 
| 127 } |  | 
| OLD | NEW | 
|---|