shill: Add method for querying geolocation objects on a device.
Currently, only WiFi is implemented.
BUG=chromium-os:34844
TEST=unit test
Change-Id: I1ef485162052af3165da71fb170940f617e4f071
Reviewed-on: https://gerrit.chromium.org/gerrit/35975
Reviewed-by: Paul Stewart <pstew@chromium.org>
Commit-Ready: Gaurav Shah <gauravsh@chromium.org>
Tested-by: Gaurav Shah <gauravsh@chromium.org>
diff --git a/Makefile b/Makefile
index 5a4d579..ecabbd2 100644
--- a/Makefile
+++ b/Makefile
@@ -167,6 +167,7 @@
ethernet.o \
ethernet_service.o \
event_dispatcher.o \
+ geolocation_info.o \
glib.o \
glib_io_ready_handler.o \
glib_io_input_handler.o \
diff --git a/device.cc b/device.cc
index bfc5b49..9ad0b32 100644
--- a/device.cc
+++ b/device.cc
@@ -25,6 +25,7 @@
#include "shill/dhcp_provider.h"
#include "shill/error.h"
#include "shill/event_dispatcher.h"
+#include "shill/geolocation_info.h"
#include "shill/http_proxy.h"
#include "shill/link_monitor.h"
#include "shill/logging.h"
@@ -271,6 +272,10 @@
return id;
}
+vector<GeolocationInfo> Device::GetGeolocationObjects() const {
+ return vector<GeolocationInfo>();
+};
+
string Device::GetTechnologyString(Error */*error*/) {
return Technology::NameFromIdentifier(technology());
}
diff --git a/device.h b/device.h
index 9cd823e..306f234 100644
--- a/device.h
+++ b/device.h
@@ -33,6 +33,7 @@
class Endpoint;
class Error;
class EventDispatcher;
+class GeolocationInfo;
class LinkMonitor;
class Manager;
class Metrics;
@@ -124,6 +125,11 @@
std::string GetRpcIdentifier();
std::string GetStorageIdentifier();
+ // Returns a list of Geolocation objects. Each object is multiple
+ // key-value pairs representing one entity that can be used for
+ // Geolocation.
+ virtual std::vector<GeolocationInfo> GetGeolocationObjects() const;
+
const std::string &address() const { return hardware_address_; }
const std::string &link_name() const { return link_name_; }
int interface_index() const { return interface_index_; }
diff --git a/geolocation_info.cc b/geolocation_info.cc
new file mode 100644
index 0000000..c975162
--- /dev/null
+++ b/geolocation_info.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "shill/geolocation_info.h"
+
+#include <map>
+#include <string>
+
+namespace shill {
+
+using std::string;
+
+GeolocationInfo::GeolocationInfo() {
+}
+
+GeolocationInfo::~GeolocationInfo() {
+}
+
+void GeolocationInfo::AddField(const std::string &key,
+ const std::string &value) {
+ properties_[key] = value;
+}
+
+const std::string &GeolocationInfo::GetFieldValue(
+ const std::string &key) const {
+ return properties_.find(key)->second;
+}
+
+bool GeolocationInfo::Equals(const GeolocationInfo &info) const{
+ return properties_ == info.properties_;
+}
+
+} // namespace shill
diff --git a/geolocation_info.h b/geolocation_info.h
new file mode 100644
index 0000000..45307e0
--- /dev/null
+++ b/geolocation_info.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SHILL_GEOLOCATION_INFO_
+#define SHILL_GEOLOCATION_INFO_
+
+#include <map>
+#include <string>
+
+#include <gtest/gtest_prod.h> // for FRIEND_TEST
+
+namespace shill {
+
+class WiFiMainTest;
+
+// This class stores properties (key-value pairs) for a single entity
+// (e.g. a WiFi access point) that may be used for geolocation.
+class GeolocationInfo {
+ public:
+ GeolocationInfo();
+ ~GeolocationInfo();
+
+ void AddField(const std::string &key, const std::string &value);
+ const std::string &GetFieldValue(const std::string &key) const;
+ private:
+ FRIEND_TEST(WiFiMainTest, GetGeolocationObjects);
+
+ // An equality testing helper for unit tests.
+ bool Equals(const GeolocationInfo &info) const;
+
+ std::map<std::string, std::string> properties_;
+};
+
+} // namespace shill
+
+#endif // SHILL_GEOLOCATION_INFO_
diff --git a/metrics.h b/metrics.h
index a6c8cf8..ec40c2e 100644
--- a/metrics.h
+++ b/metrics.h
@@ -19,6 +19,7 @@
namespace shill {
+class WiFiMainTest;
class WiFiService;
class Metrics {
@@ -321,6 +322,7 @@
FRIEND_TEST(MetricsTest, TimeToPortal);
FRIEND_TEST(MetricsTest, WiFiServiceChannel);
FRIEND_TEST(MetricsTest, WiFiServicePostReady);
+ FRIEND_TEST(WiFiMainTest, GetGeolocationObjects);
typedef ScopedVector<chromeos_metrics::TimerReporter> TimerReporters;
typedef std::list<chromeos_metrics::TimerReporter *> TimerReportersList;
diff --git a/wifi.cc b/wifi.cc
index 574baa2..40a705c 100644
--- a/wifi.cc
+++ b/wifi.cc
@@ -28,6 +28,7 @@
#include "shill/device.h"
#include "shill/error.h"
#include "shill/event_dispatcher.h"
+#include "shill/geolocation_info.h"
#include "shill/key_value_store.h"
#include "shill/ieee80211.h"
#include "shill/link_monitor.h"
@@ -1327,6 +1328,26 @@
}
}
+vector<GeolocationInfo> WiFi::GetGeolocationObjects() const {
+ vector<GeolocationInfo> objects;
+ for (EndpointMap::const_iterator it = endpoint_by_rpcid_.begin();
+ it != endpoint_by_rpcid_.end();
+ ++it) {
+ GeolocationInfo geoinfo;
+ WiFiEndpointRefPtr endpoint = it->second;
+ geoinfo.AddField(kGeoMacAddressProperty, endpoint->bssid_string());
+ geoinfo.AddField(kGeoSignalStrengthProperty,
+ StringPrintf("%d", endpoint->signal_strength()));
+ geoinfo.AddField(
+ kGeoChannelProperty,
+ StringPrintf("%d",
+ Metrics::WiFiFrequencyToChannel(endpoint->frequency())));
+ // TODO(gauravsh): Include age field. crosbug.com/35445
+ objects.push_back(geoinfo);
+ }
+ return objects;
+}
+
void WiFi::HelpRegisterDerivedInt32(
PropertyStore *store,
const string &name,
diff --git a/wifi.h b/wifi.h
index ce22485..b883ad8 100644
--- a/wifi.h
+++ b/wifi.h
@@ -101,6 +101,7 @@
namespace shill {
class Error;
+class GeolocationInfo;
class KeyValueStore;
class ProxyFactory;
class SupplicantInterfaceProxyInterface;
@@ -160,6 +161,9 @@
// Called by Linkmonitor (overriden from Device superclass).
virtual void OnLinkMonitorFailure();
+ // Overriden from Device superclass
+ virtual std::vector<GeolocationInfo> GetGeolocationObjects() const;
+
private:
friend class WiFiObjectTest; // access to supplicant_*_proxy_, link_up_
friend class WiFiTimerTest; // kNumFastScanAttempts, kFastScanIntervalSeconds
diff --git a/wifi_unittest.cc b/wifi_unittest.cc
index 0f5d6fe..2857c1d 100644
--- a/wifi_unittest.cc
+++ b/wifi_unittest.cc
@@ -28,6 +28,7 @@
#include "shill/dbus_adaptor.h"
#include "shill/event_dispatcher.h"
+#include "shill/geolocation_info.h"
#include "shill/ieee80211.h"
#include "shill/key_value_store.h"
#include "shill/logging.h"
@@ -2465,4 +2466,43 @@
EXPECT_TRUE(file_util::PathExists(FilePath(SYSROOT).Append(path)));
}
+struct BSS {
+ string bsspath;
+ string ssid;
+ string bssid;
+ int16_t signal_strength;
+ uint16 frequency;
+ const char* mode;
+};
+
+TEST_F(WiFiMainTest, GetGeolocationObjects) {
+ BSS bsses[] = {
+ {"bssid1", "ssid1", "00:00:00:00:00:00", 5, Metrics::kWiFiFrequency2412,
+ kNetworkModeInfrastructure},
+ {"bssid2", "ssid2", "01:00:00:00:00:00", 30, Metrics::kWiFiFrequency5170,
+ kNetworkModeInfrastructure},
+ // Same SSID but different BSSID is an additional geolocation object.
+ {"bssid3", "ssid1", "02:00:00:00:00:00", 100, 0,
+ kNetworkModeInfrastructure}
+ };
+ StartWiFi();
+ vector<GeolocationInfo> objects;
+ EXPECT_EQ(objects.size(), 0);
+
+ for (size_t i = 0; i < arraysize(bsses); ++i) {
+ ReportBSS(bsses[i].bsspath, bsses[i].ssid, bsses[i].bssid,
+ bsses[i].signal_strength, bsses[i].frequency, bsses[i].mode);
+ objects = wifi()->GetGeolocationObjects();
+ EXPECT_EQ(objects.size(), i + 1);
+
+ GeolocationInfo expected_info;
+ expected_info.AddField(kGeoMacAddressProperty, bsses[i].bssid);
+ expected_info.AddField(kGeoSignalStrengthProperty,
+ StringPrintf("%d", bsses[i].signal_strength));
+ expected_info.AddField(kGeoChannelProperty, StringPrintf(
+ "%d", Metrics::WiFiFrequencyToChannel(bsses[i].frequency)));
+ EXPECT_TRUE(objects[i].Equals(expected_info));
+ };
+};
+
} // namespace shill