shill: Register the modem, create service and obtain signal strength.
Also, listen for registration info and signal quality change notifications.
BUG=chromium-os:18315
TEST=unit tests, tested on device
Change-Id: I19e5e97257bc53f2004d6b7f0606da2553be4b5d
Reviewed-on: http://gerrit.chromium.org/gerrit/5328
Reviewed-by: Darin Petkov <petkov@chromium.org>
Tested-by: Darin Petkov <petkov@chromium.org>
diff --git a/cellular.cc b/cellular.cc
index 2ca6951..5a26d75 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -108,10 +108,6 @@
state_(kStateDisabled),
dbus_owner_(owner),
dbus_path_(path),
- service_(new CellularService(control_interface,
- dispatcher,
- manager,
- this)),
service_registered_(false),
allow_roaming_(false),
prl_version_(0),
@@ -183,7 +179,6 @@
}
GetModemInfo();
GetModemRegistrationState();
- ReportEnabled();
// TODO(petkov): Device::Start();
}
@@ -193,6 +188,7 @@
cdma_proxy_.reset();
manager_->DeregisterService(service_);
service_ = NULL; // Breaks a reference cycle.
+ state_ = kStateDisabled;
// TODO(petkov): Device::Stop();
}
@@ -209,7 +205,7 @@
case kTypeCDMA:
cdma_proxy_.reset(
ProxyFactory::factory()->CreateModemCDMAProxy(
- dbus_path_, dbus_owner_));
+ this, dbus_path_, dbus_owner_));
break;
default: NOTREACHED();
}
@@ -285,6 +281,7 @@
break;
default: NOTREACHED();
}
+ HandleNewRegistrationState();
}
void Cellular::GetCDMARegistrationState() {
@@ -301,15 +298,94 @@
NOTIMPLEMENTED();
}
-void Cellular::ReportEnabled() {
+bool Cellular::IsModemRegistered() {
+ return cdma_.registration_state_1x !=
+ MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN ||
+ cdma_.registration_state_evdo !=
+ MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
+ // TODO(petkov): Handle GSM states.
+}
+
+void Cellular::HandleNewRegistrationState() {
+ VLOG(2) << __func__;
+ if (!IsModemRegistered()) {
+ service_ = NULL;
+ if (state_ == kStateConnected || state_ == kStateRegistered) {
+ state_ = kStateEnabled;
+ }
+ return;
+ }
+
+ if (state_ == kStateEnabled) {
+ state_ = kStateRegistered;
+ }
+ if (!service_.get()) {
+ // For now, no endpoint is created. Revisit if necessary.
+ CreateService();
+ }
+ GetModemSignalQuality();
+ // TODO(petkov): Update the service.
+}
+
+void Cellular::GetModemSignalQuality() {
+ uint32 strength = 0;
+ switch (type_) {
+ case kTypeGSM:
+ strength = GetGSMSignalQuality();
+ break;
+ case kTypeCDMA:
+ strength = GetCDMASignalQuality();
+ break;
+ default: NOTREACHED();
+ }
+ HandleNewSignalQuality(strength);
+}
+
+uint32 Cellular::GetCDMASignalQuality() {
+ CHECK_EQ(kTypeCDMA, type_);
+ // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
+ return cdma_proxy_->GetSignalQuality();
+}
+
+uint32 Cellular::GetGSMSignalQuality() {
// TODO(petkov): Implement this.
NOTIMPLEMENTED();
+ return 0;
+}
+
+void Cellular::HandleNewSignalQuality(uint32 strength) {
+ VLOG(2) << "Signal strength: " << strength;
+ if (service_.get()) {
+ service_->set_strength(strength);
+ }
+}
+
+void Cellular::CreateService() {
+ CHECK(!service_.get());
+ service_ =
+ new CellularService(control_interface_, dispatcher_, manager_, this);
+ // TODO(petkov): Set activation_state.
+ // TODO(petkov): Set operator.
+ // TODO(petkov): Set old_url/usage_url.
}
bool Cellular::TechnologyIs(const Device::Technology type) {
return type == Device::kCellular;
}
+void Cellular::OnCDMARegistrationStateChanged(uint32 state_1x,
+ uint32 state_evdo) {
+ CHECK_EQ(kTypeCDMA, type_);
+ cdma_.registration_state_1x = state_1x;
+ cdma_.registration_state_evdo = state_evdo;
+ HandleNewRegistrationState();
+}
+
+void Cellular::OnCDMASignalQualityChanged(uint32 strength) {
+ CHECK_EQ(kTypeCDMA, type_);
+ HandleNewSignalQuality(strength);
+}
+
Stringmaps Cellular::EnumerateNetworks() {
Stringmaps to_return;
for (vector<Network>::const_iterator it = found_networks_.begin();
diff --git a/cellular.h b/cellular.h
index a88cb09..4f8efbf 100644
--- a/cellular.h
+++ b/cellular.h
@@ -11,16 +11,17 @@
#include <gtest/gtest_prod.h> // for FRIEND_TEST
#include "shill/device.h"
+#include "shill/modem_cdma_proxy_interface.h"
#include "shill/refptr_types.h"
#include "shill/shill_event.h"
namespace shill {
-class ModemCDMAProxyInterface;
class ModemProxyInterface;
class ModemSimpleProxyInterface;
-class Cellular : public Device {
+class Cellular : public Device,
+ public ModemCDMAProxyListener {
public:
enum Type {
kTypeGSM,
@@ -98,6 +99,7 @@
private:
FRIEND_TEST(CellularTest, GetCDMARegistrationState);
+ FRIEND_TEST(CellularTest, GetCDMASignalQuality);
FRIEND_TEST(CellularTest, GetModemInfo);
FRIEND_TEST(CellularTest, GetModemStatus);
FRIEND_TEST(CellularTest, GetStateString);
@@ -124,19 +126,40 @@
void GetModemStatus();
void GetGSMProperties();
void RegisterGSMModem();
- void ReportEnabled();
// Obtains the modem identifiers: MEID for CDMA; IMEI, IMSI, SPN and MSISDN
// for GSM.
void GetModemIdentifiers();
- // Obtain modem's manufacturer, model ID, and hardware revision.
+ // Obtains modem's manufacturer, model ID, and hardware revision.
void GetModemInfo();
void GetModemRegistrationState();
void GetCDMARegistrationState();
void GetGSMRegistrationState();
+ // Processes a change in the modem registration state, possibly creating,
+ // destroying or updating the CellularService.
+ void HandleNewRegistrationState();
+
+ void CreateService();
+
+ void GetModemSignalQuality();
+ uint32 GetCDMASignalQuality();
+ uint32 GetGSMSignalQuality();
+
+ void HandleNewSignalQuality(uint32 strength);
+
+ // Returns true if the modem is registered. Note that this method looks at the
+ // latest CDMA/GSM registration info obtained from the modem rather than the
+ // device |state_|.
+ bool IsModemRegistered();
+
+ // Signal callbacks from ModemCDMAProxyListener.
+ virtual void OnCDMARegistrationStateChanged(uint32 state_1x,
+ uint32 state_evdo);
+ virtual void OnCDMASignalQualityChanged(uint32 strength);
+
Type type_;
State state_;
@@ -148,7 +171,7 @@
CDMA cdma_;
- ServiceRefPtr service_;
+ CellularServiceRefPtr service_;
bool service_registered_;
// Properties
diff --git a/cellular_service.h b/cellular_service.h
index e074202..ad39dab 100644
--- a/cellular_service.h
+++ b/cellular_service.h
@@ -26,10 +26,14 @@
EventDispatcher *dispatcher,
Manager *manager,
const CellularRefPtr &device);
- ~CellularService();
+ virtual ~CellularService();
+
void Connect();
void Disconnect();
+ uint8 strength() const { return strength_; }
+ void set_strength(uint8 strength) { strength_ = strength; }
+
protected:
virtual std::string CalculateState() { return "idle"; }
@@ -50,6 +54,7 @@
CellularRefPtr cellular_;
const std::string type_;
+
DISALLOW_COPY_AND_ASSIGN(CellularService);
};
diff --git a/cellular_unittest.cc b/cellular_unittest.cc
index 6b3e575..26f9eec 100644
--- a/cellular_unittest.cc
+++ b/cellular_unittest.cc
@@ -7,6 +7,7 @@
#include <chromeos/dbus/service_constants.h>
#include <mm/mm-modem.h>
+#include "shill/cellular_service.h"
#include "shill/mock_modem_cdma_proxy.h"
#include "shill/mock_modem_proxy.h"
#include "shill/mock_modem_simple_proxy.h"
@@ -63,6 +64,7 @@
}
virtual ModemCDMAProxyInterface *CreateModemCDMAProxy(
+ ModemCDMAProxyListener *listener,
const string &path,
const string &service) {
return test_->cdma_proxy_.release();
@@ -207,6 +209,7 @@
}
TEST_F(CellularTest, GetCDMARegistrationState) {
+ EXPECT_FALSE(device_->service_.get());
EXPECT_EQ(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN,
device_->cdma_.registration_state_1x);
EXPECT_EQ(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN,
@@ -216,12 +219,32 @@
.WillOnce(DoAll(
SetArgumentPointee<0>(MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED),
SetArgumentPointee<1>(MM_MODEM_CDMA_REGISTRATION_STATE_HOME)));
+ EXPECT_CALL(*cdma_proxy_, GetSignalQuality()).WillOnce(Return(90));
device_->cdma_proxy_.reset(cdma_proxy_.release());
device_->GetModemRegistrationState();
EXPECT_EQ(MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED,
device_->cdma_.registration_state_1x);
EXPECT_EQ(MM_MODEM_CDMA_REGISTRATION_STATE_HOME,
device_->cdma_.registration_state_evdo);
+ EXPECT_TRUE(device_->service_.get());
+}
+
+TEST_F(CellularTest, GetCDMASignalQuality) {
+ const int kStrength = 90;
+ device_->type_ = Cellular::kTypeCDMA;
+ EXPECT_CALL(*cdma_proxy_, GetSignalQuality())
+ .Times(2)
+ .WillRepeatedly(Return(kStrength));
+ device_->cdma_proxy_.reset(cdma_proxy_.release());
+
+ EXPECT_FALSE(device_->service_.get());
+ device_->GetModemSignalQuality();
+
+ device_->service_ = new CellularService(
+ &control_interface_, &dispatcher_, &manager_, device_);
+ EXPECT_EQ(0, device_->service_->strength());
+ device_->GetModemSignalQuality();
+ EXPECT_EQ(kStrength, device_->service_->strength());
}
} // namespace shill
diff --git a/device.cc b/device.cc
index 51615b9..e212cbf 100644
--- a/device.cc
+++ b/device.cc
@@ -51,6 +51,8 @@
running_(false),
link_name_(link_name),
unique_id_(link_name),
+ control_interface_(control_interface),
+ dispatcher_(dispatcher),
manager_(manager),
adaptor_(control_interface->CreateDeviceAdaptor(this)) {
diff --git a/device.h b/device.h
index 08548e6..be2ba2a 100644
--- a/device.h
+++ b/device.h
@@ -110,6 +110,8 @@
bool running_;
const std::string link_name_;
const std::string unique_id_;
+ ControlInterface *control_interface_;
+ EventDispatcher *dispatcher_;
Manager *manager_;
IPConfigRefPtr ipconfig_;
diff --git a/mock_modem_cdma_proxy.h b/mock_modem_cdma_proxy.h
index afdf183..fdd9d93 100644
--- a/mock_modem_cdma_proxy.h
+++ b/mock_modem_cdma_proxy.h
@@ -15,6 +15,7 @@
public:
MOCK_METHOD2(GetRegistrationState, void(uint32 *cdma_1x_state,
uint32 *evdo_state));
+ MOCK_METHOD0(GetSignalQuality, uint32());
};
} // namespace shill
diff --git a/modem_cdma_proxy.cc b/modem_cdma_proxy.cc
index aab7c4a..4380c2d 100644
--- a/modem_cdma_proxy.cc
+++ b/modem_cdma_proxy.cc
@@ -10,10 +10,11 @@
namespace shill {
-ModemCDMAProxy::ModemCDMAProxy(DBus::Connection *connection,
+ModemCDMAProxy::ModemCDMAProxy(ModemCDMAProxyListener *listener,
+ DBus::Connection *connection,
const string &path,
const string &service)
- : proxy_(connection, path, service) {}
+ : proxy_(listener, connection, path, service) {}
ModemCDMAProxy::~ModemCDMAProxy() {}
@@ -22,10 +23,16 @@
proxy_.GetRegistrationState(*cdma_1x_state, *evdo_state);
}
-ModemCDMAProxy::Proxy::Proxy(DBus::Connection *connection,
+uint32 ModemCDMAProxy::GetSignalQuality() {
+ return proxy_.GetSignalQuality();
+}
+
+ModemCDMAProxy::Proxy::Proxy(ModemCDMAProxyListener *listener,
+ DBus::Connection *connection,
const string &path,
const string &service)
- : DBus::ObjectProxy(*connection, path, service.c_str()) {}
+ : DBus::ObjectProxy(*connection, path, service.c_str()),
+ listener_(listener) {}
ModemCDMAProxy::Proxy::~Proxy() {}
@@ -39,17 +46,15 @@
}
void ModemCDMAProxy::Proxy::SignalQuality(const uint32 &quality) {
- VLOG(2) << __func__;
- // TODO(petkov): Implement this.
- NOTIMPLEMENTED();
+ VLOG(2) << __func__ << "(" << quality << ")";
+ listener_->OnCDMASignalQualityChanged(quality);
}
void ModemCDMAProxy::Proxy::RegistrationStateChanged(
- const uint32_t &cdma_1x_state,
- const uint32_t &evdo_state) {
- VLOG(2) << __func__;
- // TODO(petkov): Implement this.
- NOTIMPLEMENTED();
+ const uint32 &cdma_1x_state,
+ const uint32 &evdo_state) {
+ VLOG(2) << __func__ << "(" << cdma_1x_state << ", " << evdo_state << ")";
+ listener_->OnCDMARegistrationStateChanged(cdma_1x_state, evdo_state);
}
} // namespace shill
diff --git a/modem_cdma_proxy.h b/modem_cdma_proxy.h
index b1ef84f..33d021f 100644
--- a/modem_cdma_proxy.h
+++ b/modem_cdma_proxy.h
@@ -13,19 +13,24 @@
class ModemCDMAProxy : public ModemCDMAProxyInterface {
public:
- ModemCDMAProxy(DBus::Connection *connection,
+ // Constructs a ModemManager.Modem.CDMA DBus object proxy at |path| owned by
+ // |service|. Caught signals will be dispatched to |listener|.
+ ModemCDMAProxy(ModemCDMAProxyListener *listener,
+ DBus::Connection *connection,
const std::string &path,
const std::string &service);
virtual ~ModemCDMAProxy();
// Inherited from ModemCDMAProxyInterface.
virtual void GetRegistrationState(uint32 *cdma_1x_state, uint32 *evdo_state);
+ virtual uint32 GetSignalQuality();
private:
class Proxy : public org::freedesktop::ModemManager::Modem::Cdma_proxy,
public DBus::ObjectProxy {
public:
- Proxy(DBus::Connection *connection,
+ Proxy(ModemCDMAProxyListener *listener,
+ DBus::Connection *connection,
const std::string &path,
const std::string &service);
virtual ~Proxy();
@@ -37,8 +42,10 @@
const uint32 &activation_error,
const DBusPropertiesMap &status_changes);
virtual void SignalQuality(const uint32 &quality);
- virtual void RegistrationStateChanged(const uint32_t &cdma_1x_state,
- const uint32_t &evdo_state);
+ virtual void RegistrationStateChanged(const uint32 &cdma_1x_state,
+ const uint32 &evdo_state);
+
+ ModemCDMAProxyListener *listener_;
DISALLOW_COPY_AND_ASSIGN(Proxy);
};
diff --git a/modem_cdma_proxy_interface.h b/modem_cdma_proxy_interface.h
index c4f4c9c..04f058e 100644
--- a/modem_cdma_proxy_interface.h
+++ b/modem_cdma_proxy_interface.h
@@ -17,6 +17,18 @@
virtual void GetRegistrationState(uint32 *cdma_1x_state,
uint32 *evdo_state) = 0;
+
+ virtual uint32 GetSignalQuality() = 0;
+};
+
+// ModemManager.Modem.CDMA signal listener to be associated with the proxy.
+class ModemCDMAProxyListener {
+ public:
+ virtual ~ModemCDMAProxyListener() {}
+
+ virtual void OnCDMARegistrationStateChanged(uint32 state_1x,
+ uint32 state_evdo) = 0;
+ virtual void OnCDMASignalQualityChanged(uint32 strength) = 0;
};
} // namespace shill
diff --git a/proxy_factory.cc b/proxy_factory.cc
index 3d250ac..2e90348 100644
--- a/proxy_factory.cc
+++ b/proxy_factory.cc
@@ -57,9 +57,10 @@
}
ModemCDMAProxyInterface *ProxyFactory::CreateModemCDMAProxy(
+ ModemCDMAProxyListener *listener,
const string &path,
const string &service) {
- return new ModemCDMAProxy(connection(), path, service);
+ return new ModemCDMAProxy(listener, connection(), path, service);
}
SupplicantProcessProxyInterface *ProxyFactory::CreateSupplicantProcessProxy(
diff --git a/proxy_factory.h b/proxy_factory.h
index 6c1b0f4..0fc1cbd 100644
--- a/proxy_factory.h
+++ b/proxy_factory.h
@@ -19,6 +19,7 @@
class DHCPProxyInterface;
class Modem;
class ModemCDMAProxyInterface;
+class ModemCDMAProxyListener;
class ModemManager;
class ModemManagerProxyInterface;
class ModemProxyInterface;
@@ -52,6 +53,7 @@
const std::string &service);
virtual ModemCDMAProxyInterface *CreateModemCDMAProxy(
+ ModemCDMAProxyListener *listener,
const std::string &path,
const std::string &service);
diff --git a/wifi.cc b/wifi.cc
index e245d76..2cbaed1 100644
--- a/wifi.cc
+++ b/wifi.cc
@@ -51,8 +51,6 @@
link,
interface_index),
task_factory_(this),
- control_interface_(control_interface),
- dispatcher_(dispatcher),
bgscan_short_interval_(0),
bgscan_signal_threshold_(0),
scan_pending_(false),
diff --git a/wifi.h b/wifi.h
index c5bad6b..2808b79 100644
--- a/wifi.h
+++ b/wifi.h
@@ -59,8 +59,6 @@
void ScanDoneTask();
ScopedRunnableMethodFactory<WiFi> task_factory_;
- ControlInterface *control_interface_;
- EventDispatcher *dispatcher_;
scoped_ptr<SupplicantProcessProxyInterface> supplicant_process_proxy_;
scoped_ptr<SupplicantInterfaceProxyInterface> supplicant_interface_proxy_;
EndpointMap endpoint_by_bssid_;