shill: monitor bss signal strength
This wires WiFiEndpoint up to a proxy, to monitor
changes in the corresponding wpa_supplicant BSS
object.
The WiFiEndpoint object notifies its WiFi object
about the change, and WiFi relays the information
to the appropriate WiFiService.
BUG=chromium-os:16786
TEST=new unit tests, manual
Manual testing: ran on device (with --v=1000), observed
"signal is now" messages in log file.
Collateral changes:
- fix WiFiService leak in WiFi (reset |current_service| on Stop)
- suppress some "uninteresting call" messages in
WiFiMainTest.CurrentBSSChangedUpdateServiceEndpoint
Change-Id: Ic329ecd28f73d93238d517a73105f2cd35cbff2e
Reviewed-on: https://gerrit.chromium.org/gerrit/15868
Commit-Ready: mukesh agrawal <quiche@chromium.org>
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Tested-by: mukesh agrawal <quiche@chromium.org>
diff --git a/Makefile b/Makefile
index 412f412..08fc7e5 100644
--- a/Makefile
+++ b/Makefile
@@ -163,6 +163,7 @@
shill_test_config.o \
shill_time.o \
sockets.o \
+ supplicant_bss_proxy.o \
supplicant_interface_proxy.o \
supplicant_process_proxy.o \
technology.o \
@@ -241,6 +242,7 @@
mock_service.o \
mock_sockets.o \
mock_store.o \
+ mock_supplicant_bss_proxy.o \
mock_supplicant_interface_proxy.o \
mock_supplicant_process_proxy.o \
mock_time.o \
diff --git a/mock_supplicant_bss_proxy.cc b/mock_supplicant_bss_proxy.cc
new file mode 100644
index 0000000..025dc6d
--- /dev/null
+++ b/mock_supplicant_bss_proxy.cc
@@ -0,0 +1,15 @@
+// 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/mock_supplicant_bss_proxy.h"
+
+namespace shill {
+
+MockSupplicantBSSProxy::MockSupplicantBSSProxy() {}
+
+MockSupplicantBSSProxy::~MockSupplicantBSSProxy() {
+ Die();
+}
+
+} // namespace shill
diff --git a/mock_supplicant_bss_proxy.h b/mock_supplicant_bss_proxy.h
new file mode 100644
index 0000000..0de038b
--- /dev/null
+++ b/mock_supplicant_bss_proxy.h
@@ -0,0 +1,28 @@
+// 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 MOCK_SUPPLICANT_BSS_PROXY_H_
+#define MOCK_SUPPLICANT_BSS_PROXY_H_
+
+#include <base/basictypes.h>
+#include <gmock/gmock.h>
+
+#include "shill/supplicant_bss_proxy_interface.h"
+
+namespace shill {
+
+class MockSupplicantBSSProxy : public SupplicantBSSProxyInterface {
+ public:
+ explicit MockSupplicantBSSProxy();
+ virtual ~MockSupplicantBSSProxy();
+
+ MOCK_METHOD0(Die, void()); // So we can EXPECT the dtor.
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockSupplicantBSSProxy);
+};
+
+} // namespace shill
+
+#endif // MOCK_SUPPLICANT_BSS_PROXY_H_
diff --git a/mock_wifi.h b/mock_wifi.h
index b91af46..78b1b9f 100644
--- a/mock_wifi.h
+++ b/mock_wifi.h
@@ -14,6 +14,7 @@
#include "shill/key_value_store.h"
#include "shill/refptr_types.h"
#include "shill/wifi.h"
+#include "shill/wifi_endpoint.h"
#include "shill/wifi_service.h"
namespace shill {
@@ -43,6 +44,7 @@
void(WiFiService *service,
std::map<std::string, ::DBus::Variant> service_params));
MOCK_CONST_METHOD0(IsIdle, bool());
+ MOCK_METHOD1(NotifyEndpointChanged, void(const WiFiEndpoint &endpoint));
private:
DISALLOW_COPY_AND_ASSIGN(MockWiFi);
diff --git a/proxy_factory.cc b/proxy_factory.cc
index 346df34..14c1117 100644
--- a/proxy_factory.cc
+++ b/proxy_factory.cc
@@ -15,6 +15,7 @@
#include "shill/modem_proxy.h"
#include "shill/modem_simple_proxy.h"
#include "shill/power_manager_proxy.h"
+#include "shill/supplicant_bss_proxy.h"
#include "shill/supplicant_interface_proxy.h"
#include "shill/supplicant_process_proxy.h"
@@ -109,6 +110,14 @@
dbus_addr);
}
+SupplicantBSSProxyInterface *ProxyFactory::CreateSupplicantBSSProxy(
+ WiFiEndpoint *wifi_endpoint,
+ const DBus::Path &object_path,
+ const char *dbus_addr) {
+ return new SupplicantBSSProxy(
+ wifi_endpoint, connection(), object_path, dbus_addr);
+}
+
DHCPProxyInterface *ProxyFactory::CreateDHCPProxy(const string &service) {
return new DHCPCDProxy(connection(), service);
}
diff --git a/proxy_factory.h b/proxy_factory.h
index 3976364..5b4b7ee 100644
--- a/proxy_factory.h
+++ b/proxy_factory.h
@@ -33,6 +33,7 @@
class ModemSimpleProxyInterface;
class PowerManagerProxyDelegate;
class PowerManagerProxyInterface;
+class SupplicantBSSProxyInterface;
class SupplicantInterfaceProxyInterface;
class SupplicantProcessProxyInterface;
@@ -94,6 +95,12 @@
const DBus::Path &object_path,
const char *dbus_addr);
+ // See comment in supplicant_bss_proxy.h, about bare pointer.
+ virtual SupplicantBSSProxyInterface *CreateSupplicantBSSProxy(
+ WiFiEndpoint *wifi_endpoint,
+ const DBus::Path &object_path,
+ const char *dbus_addr);
+
virtual DHCPProxyInterface *CreateDHCPProxy(const std::string &service);
DBus::Connection *connection() const { return connection_.get(); }
diff --git a/supplicant_bss_proxy.cc b/supplicant_bss_proxy.cc
new file mode 100644
index 0000000..dc12b45
--- /dev/null
+++ b/supplicant_bss_proxy.cc
@@ -0,0 +1,43 @@
+// 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/supplicant_bss_proxy.h"
+
+#include <map>
+#include <string>
+
+#include <dbus-c++/dbus.h>
+
+#include "shill/wifi_endpoint.h"
+
+using std::map;
+using std::string;
+
+namespace shill {
+
+SupplicantBSSProxy::SupplicantBSSProxy(
+ WiFiEndpoint *wifi_endpoint,
+ DBus::Connection *bus,
+ const ::DBus::Path &object_path,
+ const char *dbus_addr)
+ : proxy_(wifi_endpoint, bus, object_path, dbus_addr) {}
+
+SupplicantBSSProxy::~SupplicantBSSProxy() {}
+
+// definitions for private class SupplicantBSSProxy::Proxy
+
+SupplicantBSSProxy::Proxy::Proxy(
+ WiFiEndpoint *wifi_endpoint, DBus::Connection *bus,
+ const DBus::Path &dbus_path, const char *dbus_addr)
+ : DBus::ObjectProxy(*bus, dbus_path, dbus_addr),
+ wifi_endpoint_(wifi_endpoint) {}
+
+SupplicantBSSProxy::Proxy::~Proxy() {}
+
+void SupplicantBSSProxy::Proxy::PropertiesChanged(
+ const std::map<string, ::DBus::Variant> &properties) {
+ wifi_endpoint_->PropertiesChanged(properties);
+}
+
+} // namespace shill
diff --git a/supplicant_bss_proxy.h b/supplicant_bss_proxy.h
new file mode 100644
index 0000000..4d80403
--- /dev/null
+++ b/supplicant_bss_proxy.h
@@ -0,0 +1,59 @@
+// 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 SUPPLICANT_BSS_PROXY_H_
+#define SUPPLICANT_BSS_PROXY_H_
+
+#include <map>
+#include <string>
+
+#include <base/basictypes.h>
+#include <dbus-c++/dbus.h>
+
+#include "shill/dbus_bindings/supplicant-bss.h"
+#include "shill/supplicant_bss_proxy_interface.h"
+
+namespace shill {
+
+class WiFiEndpoint;
+
+class SupplicantBSSProxy : public SupplicantBSSProxyInterface {
+ public:
+ SupplicantBSSProxy(WiFiEndpoint *wifi_endpoint,
+ DBus::Connection *bus,
+ const ::DBus::Path &object_path,
+ const char *dbus_addr);
+ virtual ~SupplicantBSSProxy();
+
+ private:
+ class Proxy : public fi::w1::wpa_supplicant1::BSS_proxy,
+ public ::DBus::ObjectProxy {
+ public:
+ Proxy(WiFiEndpoint *wifi_endpoint,
+ DBus::Connection *bus,
+ const ::DBus::Path &object_path,
+ const char *dbus_addr);
+ virtual ~Proxy();
+
+ private:
+ // signal handlers called by dbus-c++, via
+ // wpa_supplicant1_proxy interface.
+ virtual void PropertiesChanged(
+ const std::map<std::string, ::DBus::Variant> &properties);
+
+ // We use a bare pointer, because each SupplicantBSSProxy is owned
+ // (using a scoped_ptr) by a WiFiEndpoint. This means that if
+ // |wifi_endpoint_| is invalid, then so is |this|.
+ WiFiEndpoint *wifi_endpoint_;
+ DISALLOW_COPY_AND_ASSIGN(Proxy);
+ };
+
+ Proxy proxy_;
+
+ DISALLOW_COPY_AND_ASSIGN(SupplicantBSSProxy);
+};
+
+} // namespace shill
+
+#endif // SUPPLICANT_BSS_PROXY_H_
diff --git a/supplicant_bss_proxy_interface.h b/supplicant_bss_proxy_interface.h
new file mode 100644
index 0000000..7523867
--- /dev/null
+++ b/supplicant_bss_proxy_interface.h
@@ -0,0 +1,19 @@
+// 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 SUPPLICANT_BSS_PROXY_INTERFACE_H_
+#define SUPPLICANT_BSS_PROXY_INTERFACE_H_
+
+namespace shill {
+
+// SupplicantBSSProxyInterface declares only the subset of
+// fi::w1::wpa_supplicant1::BSS_proxy that is actually used by WiFi.
+class SupplicantBSSProxyInterface {
+ public:
+ virtual ~SupplicantBSSProxyInterface() {}
+};
+
+} // namespace shill
+
+#endif // SUPPLICANT_BSS_PROXY_INTERFACE_H_
diff --git a/wifi.cc b/wifi.cc
index f7694a5..68dd841 100644
--- a/wifi.cc
+++ b/wifi.cc
@@ -186,9 +186,12 @@
for (vector<WiFiServiceRefPtr>::const_iterator it = services_.begin();
it != services_.end();
++it) {
+ VLOG(3) << "WiFi " << link_name() << " deregistering service "
+ << (*it)->friendly_name();
manager()->DeregisterService(*it);
}
services_.clear(); // breaks reference cycles
+ current_service_ = NULL; // breaks a reference cycle
pending_service_ = NULL; // breaks a reference cycle
Device::Stop();
@@ -391,6 +394,15 @@
}
}
+void WiFi::NotifyEndpointChanged(const WiFiEndpoint &endpoint) {
+ WiFiService *service = FindServiceForEndpoint(endpoint);
+ DCHECK(service);
+ if (service) {
+ service->NotifyEndpointUpdated(endpoint);
+ return;
+ }
+}
+
string WiFi::CreateBgscanConfigString() {
return StringPrintf("%s:%d:%d:%d",
bgscan_method_.c_str(),
@@ -772,15 +784,11 @@
void WiFi::BSSAddedTask(
const ::DBus::Path &path,
const map<string, ::DBus::Variant> &properties) {
- // TODO(quiche): Write test to verify correct behavior in the case
- // where we get multiple BSSAdded events for a single endpoint.
- // (Old Endpoint's refcount should fall to zero, and old Endpoint
- // should be destroyed.)
- //
// Note: we assume that BSSIDs are unique across endpoints. This
// means that if an AP reuses the same BSSID for multiple SSIDs, we
// lose.
- WiFiEndpointRefPtr endpoint(new WiFiEndpoint(properties));
+ WiFiEndpointRefPtr endpoint(
+ new WiFiEndpoint(proxy_factory_, this, path, properties));
LOG(INFO) << "Found endpoint. "
<< "RPC path: " << path << ", "
<< "ssid: " << endpoint->ssid_string() << ", "
@@ -824,7 +832,13 @@
// Do this last, to maintain the invariant that any Endpoint we
// know about has a corresponding Service.
+ //
+ // TODO(quiche): Write test to verify correct behavior in the case
+ // where we get multiple BSSAdded events for a single endpoint.
+ // (Old Endpoint's refcount should fall to zero, and old Endpoint
+ // should be destroyed.)
endpoint_by_rpcid_[path] = endpoint;
+ endpoint->Start();
}
void WiFi::BSSRemovedTask(const ::DBus::Path &path) {
diff --git a/wifi.h b/wifi.h
index aab6439..80c91ac 100644
--- a/wifi.h
+++ b/wifi.h
@@ -61,6 +61,9 @@
virtual bool IsIdle() const;
virtual void ClearCachedCredentials();
+ // Called by WiFiEndpoint.
+ virtual void NotifyEndpointChanged(const WiFiEndpoint &endpoint);
+
// Called by Manager.
virtual WiFiServiceRefPtr GetService(const KeyValueStore &args, Error *error);
diff --git a/wifi_endpoint.cc b/wifi_endpoint.cc
index a36ad45..e78d6cd 100644
--- a/wifi_endpoint.cc
+++ b/wifi_endpoint.cc
@@ -12,7 +12,10 @@
#include <chromeos/dbus/service_constants.h>
#include "shill/ieee80211.h"
+#include "shill/proxy_factory.h"
+#include "shill/supplicant_bss_proxy_interface.h"
#include "shill/wifi.h"
+#include "shill/wifi_endpoint.h"
#include "shill/wpa_supplicant.h"
using std::map;
@@ -22,9 +25,14 @@
namespace shill {
-WiFiEndpoint::WiFiEndpoint(
- const map<string, ::DBus::Variant> &properties)
- : frequency_(0) {
+WiFiEndpoint::WiFiEndpoint(ProxyFactory *proxy_factory,
+ const WiFiRefPtr &device,
+ const string &rpc_id,
+ const map<string, ::DBus::Variant> &properties)
+ : frequency_(0),
+ proxy_factory_(proxy_factory),
+ device_(device),
+ rpc_id_(rpc_id) {
// XXX will segfault on missing properties
ssid_ =
properties.find(wpa_supplicant::kBSSPropertySSID)->second.
@@ -59,6 +67,25 @@
WiFiEndpoint::~WiFiEndpoint() {}
+void WiFiEndpoint::Start() {
+ supplicant_bss_proxy_.reset(
+ proxy_factory_->CreateSupplicantBSSProxy(
+ this, rpc_id_, wpa_supplicant::kDBusAddr));
+}
+
+void WiFiEndpoint::PropertiesChanged(
+ const map<string, ::DBus::Variant> &properties) {
+ LOG(INFO) << __func__;
+ map<string, ::DBus::Variant>::const_iterator properties_it =
+ properties.find(wpa_supplicant::kBSSPropertySignal);
+ if (properties_it != properties.end()) {
+ signal_strength_ = properties_it->second.reader().get_int16();
+ VLOG(2) << "WiFiEndpoint " << bssid_string_ << " signal is now "
+ << signal_strength_;
+ device_->NotifyEndpointChanged(*this);
+ }
+}
+
// static
uint32_t WiFiEndpoint::ModeStringToUint(const std::string &mode_string) {
if (mode_string == flimflam::kModeManaged)
@@ -112,8 +139,10 @@
}
// static
-WiFiEndpoint *WiFiEndpoint::MakeOpenEndpoint(
- const string &ssid, const string &bssid) {
+WiFiEndpoint *WiFiEndpoint::MakeOpenEndpoint(ProxyFactory *proxy_factory,
+ const WiFiRefPtr &wifi,
+ const string &ssid,
+ const string &bssid) {
map <string, ::DBus::Variant> args;
::DBus::MessageIter writer;
@@ -132,7 +161,8 @@
wpa_supplicant::kNetworkModeInfrastructure);
// We indicate this is an open BSS by leaving out all security properties.
- return new WiFiEndpoint(args);
+ return new WiFiEndpoint(
+ proxy_factory, wifi, bssid, args); // |bssid| fakes an RPC ID
}
// static
diff --git a/wifi_endpoint.h b/wifi_endpoint.h
index 4de7a15..902eb90 100644
--- a/wifi_endpoint.h
+++ b/wifi_endpoint.h
@@ -17,14 +17,31 @@
#include "shill/endpoint.h"
#include "shill/event_dispatcher.h"
#include "shill/metrics.h"
+#include "shill/refptr_types.h"
namespace shill {
+class ProxyFactory;
+class SupplicantBSSProxyInterface;
+
class WiFiEndpoint : public Endpoint {
public:
- WiFiEndpoint(const std::map<std::string, ::DBus::Variant> &properties);
+ WiFiEndpoint(ProxyFactory *proxy_factory,
+ const WiFiRefPtr &device,
+ const std::string &rpc_id,
+ const std::map<std::string, ::DBus::Variant> &properties);
virtual ~WiFiEndpoint();
+ // Set up RPC channel. Broken out from the ctor, so that WiFi can
+ // look over the Endpoint details before commiting to setting up
+ // RPC.
+ virtual void Start();
+
+ // Called by SupplicantBSSProxy, in response to events from
+ // wpa_supplicant.
+ void PropertiesChanged(
+ const std::map<std::string, ::DBus::Variant> &properties);
+
// Maps mode strings from flimflam's nomenclature, as defined
// in chromeos/dbus/service_constants.h, to uints used by supplicant
static uint32_t ModeStringToUint(const std::string &mode_string);
@@ -44,7 +61,6 @@
friend class WiFiEndpointTest;
friend class WiFiMainTest; // for MakeOpenEndpoint
friend class WiFiServiceTest; // for MakeOpenEndpoint
- FRIEND_TEST(WiFiEndpointTest, SSIDWithNull); // for MakeOpenEndpoint
// these test cases need access to the KeyManagement enum
FRIEND_TEST(WiFiEndpointTest, ParseKeyManagementMethodsEAP);
FRIEND_TEST(WiFiEndpointTest, ParseKeyManagementMethodsPSK);
@@ -57,8 +73,10 @@
};
// Build a simple WiFiEndpoint, for testing purposes.
- static WiFiEndpoint *MakeOpenEndpoint(
- const std::string &ssid, const std::string &bssid);
+ static WiFiEndpoint *MakeOpenEndpoint(ProxyFactory *proxy_factory,
+ const WiFiRefPtr &wifi,
+ const std::string &ssid,
+ const std::string &bssid);
// Maps mode strings from supplicant into flimflam's nomenclature, as defined
// in chromeos/dbus/service_constants.h
static const char *ParseMode(const std::string &mode_string);
@@ -66,7 +84,7 @@
// security property value, as defined in chromeos/dbus/service_constants.h
static const char *ParseSecurity(
const std::map<std::string, ::DBus::Variant> &properties);
- // Parses and Endpoint's properties' "RSN" or "WPA" sub-dictionary, to
+ // Parses an Endpoint's properties' "RSN" or "WPA" sub-dictionary, to
// identify supported key management methods (802.1x or PSK).
static void ParseKeyManagementMethods(
const std::map<std::string, ::DBus::Variant> &security_method_properties,
@@ -96,6 +114,11 @@
std::string network_mode_;
std::string security_mode_;
+ ProxyFactory *proxy_factory_;
+ WiFiRefPtr device_;
+ std::string rpc_id_;
+ scoped_ptr<SupplicantBSSProxyInterface> supplicant_bss_proxy_;
+
DISALLOW_COPY_AND_ASSIGN(WiFiEndpoint);
};
diff --git a/wifi_endpoint_unittest.cc b/wifi_endpoint_unittest.cc
index 1e682c7..556b966 100644
--- a/wifi_endpoint_unittest.cc
+++ b/wifi_endpoint_unittest.cc
@@ -11,9 +11,12 @@
#include <base/stl_util-inl.h>
#include <chromeos/dbus/service_constants.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "shill/ieee80211.h"
+#include "shill/mock_wifi.h"
+#include "shill/property_store_unittest.h"
#include "shill/refptr_types.h"
#include "shill/wpa_supplicant.h"
@@ -21,14 +24,22 @@
using std::set;
using std::string;
using std::vector;
-
-using ::testing::Test;
+using ::testing::_;
+using ::testing::NiceMock;
namespace shill {
-class WiFiEndpointTest : public Test {
+class WiFiEndpointTest : public PropertyStoreTest {
public:
- WiFiEndpointTest() {}
+ WiFiEndpointTest() : wifi_(
+ new NiceMock<MockWiFi>(
+ control_interface(),
+ dispatcher(),
+ metrics(),
+ manager(),
+ "wifi",
+ "aabbccddeeff", // fake mac
+ 0)) {}
virtual ~WiFiEndpointTest() {}
protected:
@@ -77,6 +88,18 @@
ies->insert(ies->end(), 3, 0); // OUI
ies->push_back(0); // data
}
+
+ WiFiEndpoint *MakeOpenEndpoint(ProxyFactory *proxy_factory,
+ const WiFiRefPtr &wifi,
+ const std::string &ssid,
+ const std::string &bssid) {
+ return WiFiEndpoint::MakeOpenEndpoint(proxy_factory, wifi, ssid, bssid);
+ }
+
+ scoped_refptr<MockWiFi> wifi() { return wifi_; }
+
+ private:
+ scoped_refptr<MockWiFi> wifi_;
};
TEST_F(WiFiEndpointTest, ParseKeyManagementMethodsEAP) {
@@ -146,7 +169,7 @@
TEST_F(WiFiEndpointTest, SSIDWithNull) {
WiFiEndpointRefPtr endpoint =
- WiFiEndpoint::MakeOpenEndpoint(string(1, 0), "00:00:00:00:00:01");
+ MakeOpenEndpoint(NULL, NULL, string(1, 0), "00:00:00:00:00:01");
EXPECT_EQ("?", endpoint->ssid_string());
}
@@ -217,4 +240,21 @@
}
}
+TEST_F(WiFiEndpointTest, PropertiesChanged) {
+ WiFiEndpointRefPtr endpoint =
+ MakeOpenEndpoint(NULL, wifi(), "ssid", "00:00:00:00:00:01");
+ map<string, ::DBus::Variant> changed_properties;
+ ::DBus::MessageIter writer;
+ int16_t signal_strength = 10;
+
+ EXPECT_NE(signal_strength, endpoint->signal_strength());
+ writer =
+ changed_properties[wpa_supplicant::kBSSPropertySignal].writer();
+ writer << signal_strength;
+
+ EXPECT_CALL(*wifi(), NotifyEndpointChanged(_));
+ endpoint->PropertiesChanged(changed_properties);
+ EXPECT_EQ(signal_strength, endpoint->signal_strength());
+}
+
} // namespace shill
diff --git a/wifi_service.cc b/wifi_service.cc
index 0567278..42c1329 100644
--- a/wifi_service.cc
+++ b/wifi_service.cc
@@ -195,6 +195,13 @@
// (crosbug.com/16786)
}
+void WiFiService::NotifyEndpointUpdated(const WiFiEndpoint &endpoint) {
+ DCHECK(endpoints_.find(&endpoint) != endpoints_.end());
+ // TODO(quiche): If this is the connected endpoint, or the "representative"
+ // endpoint (when the service is disconnected), then update signal and
+ // frequency. crosbug.com/16786
+}
+
string WiFiService::GetStorageIdentifier() const {
return storage_identifier_;
}
diff --git a/wifi_service.h b/wifi_service.h
index 01a3fc8..f57df7c 100644
--- a/wifi_service.h
+++ b/wifi_service.h
@@ -54,7 +54,11 @@
virtual void AddEndpoint(WiFiEndpointConstRefPtr endpoint);
virtual void RemoveEndpoint(WiFiEndpointConstRefPtr endpoint);
bool NumEndpoints() const { return endpoints_.size(); }
+ // Called to update the identity of the currently connected endpoint.
void NotifyCurrentEndpoint(const WiFiEndpoint &endpoint);
+ // Called to inform of changes in the properties of an endpoint.
+ // (Not necessarily the currently connected endpoint.)
+ void NotifyEndpointUpdated(const WiFiEndpoint &endpoint);
// wifi_<MAC>_<BSSID>_<mode_string>_<security_string>
std::string GetStorageIdentifier() const;
diff --git a/wifi_service_unittest.cc b/wifi_service_unittest.cc
index 5d1f433..e167109 100644
--- a/wifi_service_unittest.cc
+++ b/wifi_service_unittest.cc
@@ -28,8 +28,6 @@
using std::map;
using std::string;
using std::vector;
-
-namespace shill {
using ::testing::_;
using ::testing::DoAll;
using ::testing::NiceMock;
@@ -38,6 +36,8 @@
using ::testing::StrEq;
using ::testing::StrNe;
+namespace shill {
+
class WiFiServiceTest : public PropertyStoreTest {
public:
WiFiServiceTest() : wifi_(
@@ -74,7 +74,7 @@
return service->connectable();
}
WiFiEndpoint *MakeEndpoint(const string &ssid, const string &bssid) {
- return WiFiEndpoint::MakeOpenEndpoint(ssid, bssid);
+ return WiFiEndpoint::MakeOpenEndpoint(NULL, NULL, ssid, bssid);
}
scoped_refptr<MockWiFi> wifi() { return wifi_; }
diff --git a/wifi_unittest.cc b/wifi_unittest.cc
index d3bcfde..d7366ef 100644
--- a/wifi_unittest.cc
+++ b/wifi_unittest.cc
@@ -37,6 +37,7 @@
#include "shill/mock_metrics.h"
#include "shill/mock_rtnl_handler.h"
#include "shill/mock_store.h"
+#include "shill/mock_supplicant_bss_proxy.h"
#include "shill/mock_supplicant_interface_proxy.h"
#include "shill/mock_supplicant_process_proxy.h"
#include "shill/mock_wifi_service.h"
@@ -57,6 +58,7 @@
using ::testing::DefaultValue;
using ::testing::DoAll;
using ::testing::InSequence;
+using ::testing::Invoke;
using ::testing::Mock;
using ::testing::NiceMock;
using ::testing::Return;
@@ -166,6 +168,8 @@
supplicant_process_proxy_(new NiceMock<MockSupplicantProcessProxy>()),
supplicant_interface_proxy_(
new NiceMock<MockSupplicantInterfaceProxy>(wifi_)),
+ supplicant_bss_proxy_(
+ new NiceMock<MockSupplicantBSSProxy>()),
dhcp_config_(new MockDHCPConfig(&control_interface_,
&dispatcher_,
&dhcp_provider_,
@@ -194,10 +198,14 @@
ON_CALL(manager_, device_info()).
WillByDefault(Return(&device_info_));
EXPECT_CALL(manager_, DeregisterService(_)).Times(AnyNumber());
+ EXPECT_CALL(*supplicant_bss_proxy_, Die()).Times(AnyNumber());
}
virtual void TearDown() {
EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber());
+ if (supplicant_bss_proxy_.get()) {
+ EXPECT_CALL(*supplicant_bss_proxy_, Die());
+ }
wifi_->proxy_factory_ = NULL;
// must Stop WiFi instance, to clear its list of services.
// otherwise, the WiFi instance will not be deleted. (because
@@ -211,7 +219,7 @@
class TestProxyFactory : public ProxyFactory {
public:
- explicit TestProxyFactory(WiFiMainTest *test) : test_(test) {}
+ explicit TestProxyFactory(WiFiMainTest *test);
virtual SupplicantProcessProxyInterface *CreateSupplicantProcessProxy(
const char */*dbus_path*/, const char */*dbus_addr*/) {
@@ -225,7 +233,20 @@
return test_->supplicant_interface_proxy_.release();
}
+ MOCK_METHOD3(CreateSupplicantBSSProxy,
+ SupplicantBSSProxyInterface *(
+ WiFiEndpoint *wifi_endpoint,
+ const DBus::Path &object_path,
+ const char *dbus_addr));
+
private:
+ SupplicantBSSProxyInterface *CreateSupplicantBSSProxyInternal(
+ WiFiEndpoint */*wifi_endpoint*/,
+ const DBus::Path &/*object_path*/,
+ const char */*dbus_addr*/) {
+ return test_->supplicant_bss_proxy_.release();
+ }
+
WiFiMainTest *test_;
};
@@ -266,7 +287,7 @@
wifi_->DisconnectFrom(service);
}
WiFiEndpointRefPtr MakeEndpoint(const string &ssid, const string &bssid) {
- return WiFiEndpoint::MakeOpenEndpoint(ssid, bssid);
+ return WiFiEndpoint::MakeOpenEndpoint(&proxy_factory_, NULL, ssid, bssid);
}
MockWiFiServiceRefPtr MakeMockService() {
vector<uint8_t> ssid(1, 'a');
@@ -397,6 +418,10 @@
return wifi_;
}
+ TestProxyFactory *proxy_factory() {
+ return &proxy_factory_;
+ }
+
EventDispatcher dispatcher_;
NiceMock<MockRTNLHandler> rtnl_handler_;
@@ -419,6 +444,7 @@
scoped_ptr<MockSupplicantProcessProxy> supplicant_process_proxy_;
scoped_ptr<MockSupplicantInterfaceProxy> supplicant_interface_proxy_;
+ scoped_ptr<MockSupplicantBSSProxy> supplicant_bss_proxy_;
MockDHCPProvider dhcp_provider_;
scoped_refptr<MockDHCPConfig> dhcp_config_;
@@ -465,6 +491,14 @@
wifi_->BSSAddedTask(bss_path, bss_properties);
}
+WiFiMainTest::TestProxyFactory::TestProxyFactory(WiFiMainTest *test)
+ : test_(test) {
+ EXPECT_CALL(*this, CreateSupplicantBSSProxy(_, _, _)).Times(AnyNumber());
+ ON_CALL(*this, CreateSupplicantBSSProxy(_, _, _))
+ .WillByDefault(
+ Invoke(this, (&TestProxyFactory::CreateSupplicantBSSProxyInternal)));
+}
+
TEST_F(WiFiMainTest, ProxiesSetUpDuringStart) {
EXPECT_TRUE(GetSupplicantProcessProxy() == NULL);
EXPECT_TRUE(GetSupplicantInterfaceProxy() == NULL);
@@ -1400,6 +1434,10 @@
}
TEST_F(WiFiMainTest, CurrentBSSChangedUpdateServiceEndpoint) {
+ EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber());
+ EXPECT_CALL(*manager(), HasService(_)).Times(AnyNumber());
+ EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber());
+
const uint16 frequency1 = 2412;
const uint16 frequency2 = 2442;
StartWiFi();
@@ -1567,4 +1605,31 @@
dispatcher_.DispatchPendingEvents();
}
+TEST_F(WiFiMainTest, BSSAddedCreatesBSSProxy) {
+ EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber());
+ // TODO(quiche): Consider using a factory for WiFiEndpoints, so that
+ // we can test the interaction between WiFi and WiFiEndpoint. (Right
+ // now, we're testing across multiple layers.)
+ EXPECT_CALL(*supplicant_bss_proxy_, Die()).Times(AnyNumber());
+ EXPECT_CALL(*proxy_factory(), CreateSupplicantBSSProxy(_, _, _));
+ StartWiFi();
+ ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc);
+}
+
+TEST_F(WiFiMainTest, BSSRemovedDestroysBSSProxy) {
+ // TODO(quiche): As for BSSAddedCreatesBSSProxy, consider using a
+ // factory for WiFiEndpoints.
+ EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber());
+
+ // Get the pointer before we transfer ownership.
+ MockSupplicantBSSProxy *proxy = supplicant_bss_proxy_.get();
+ EXPECT_CALL(*proxy, Die());
+ StartWiFi();
+ ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc);
+ RemoveBSS("bss0");
+ // Check this now, to make sure RemoveBSS killed the proxy (rather
+ // than TearDown).
+ Mock::VerifyAndClearExpectations(proxy);
+}
+
} // namespace shill