shill: Send Modem 'Enable' command when modem is disabled

ModemManager rejects the 'Enable' command if the modem is not
in the disabled state.  When shill attempts to enable a modem,
it first checks the modem's state.  If it is disabled, it sends
the 'Enable' command immediately.  Otherwise, it buffers the
'Enable' command and sends it when the modem transitions to
the disabled state.

This affects modemmanager-next (MM1) only.

BUG=chromium-os:23789
TEST=Added new unit test.  With Y3300, Y3400 and E362 and a locked SIM,
verify that unlocking the SIM results in the modem being successfully
enabled.

Change-Id: I922301ab7d17f44bd17ae122e80cd2889ec5790a
Reviewed-on: https://gerrit.chromium.org/gerrit/31040
Reviewed-by: Ben Chan <benchan@chromium.org>
Commit-Ready: Gary Morain <gmorain@chromium.org>
Tested-by: Gary Morain <gmorain@chromium.org>
diff --git a/cellular_capability_universal_unittest.cc b/cellular_capability_universal_unittest.cc
index 23c64c8..b26666a 100644
--- a/cellular_capability_universal_unittest.cc
+++ b/cellular_capability_universal_unittest.cc
@@ -41,6 +41,7 @@
 using std::string;
 using std::vector;
 using testing::InSequence;
+using testing::Mock;
 using testing::NiceMock;
 using testing::Return;
 using testing::SaveArg;
@@ -276,21 +277,47 @@
               GetAll(MM_DBUS_INTERFACE_MODEM_MODEM3GPP))
       .WillOnce(Return(modem3gpp_properties));
 
+  // Let the modem report that it is initializing.  StartModem() should defer
+  // enabling the modem until its state changes to disabled.
+  EXPECT_CALL(*modem_proxy_, State())
+      .WillOnce(Return(Cellular::kModemStateInitializing));
+
   // After setup we lose pointers to the proxies, so it is hard to set
   // expectations.
   SetUp();
 
   Error error;
-  EXPECT_CALL(*this, TestCallback(IsSuccess()));
+  EXPECT_CALL(*this, TestCallback(_)).Times(0);
   ResultCallback callback =
       Bind(&CellularCapabilityUniversalTest::TestCallback, Unretained(this));
   capability_->StartModem(&error, callback);
+
+  // Verify that the modem has not been eabled.
+  EXPECT_TRUE(capability_->imei_.empty());
+  EXPECT_EQ(0, capability_->access_technologies_);
+  Mock::VerifyAndClearExpectations(this);
+
+  // Change the state to kModemStateDisabling and verify that it still has not
+  // been eabled.
+  EXPECT_CALL(*this, TestCallback(_)).Times(0);
+  capability_->OnModemStateChangedSignal(Cellular::kModemStateInitializing,
+                                         Cellular::kModemStateDisabling, 0);
+  EXPECT_TRUE(capability_->imei_.empty());
+  EXPECT_EQ(0, capability_->access_technologies_);
+  Mock::VerifyAndClearExpectations(this);
+
+  // Change the state of the modem to disabled and verify that it gets enabled.
+  EXPECT_CALL(*this, TestCallback(IsSuccess()));
+  capability_->OnModemStateChangedSignal(Cellular::kModemStateDisabling,
+                                         Cellular::kModemStateDisabled, 0);
   EXPECT_TRUE(error.IsSuccess());
   EXPECT_EQ(kImei, capability_->imei_);
   EXPECT_EQ(kAccessTechnologies, capability_->access_technologies_);
 }
 
 TEST_F(CellularCapabilityUniversalTest, StartModemFail) {
+  EXPECT_CALL(*modem_proxy_, State())
+          .WillOnce(Return(Cellular::kModemStateDisabled));
   EXPECT_CALL(*modem_proxy_,
               Enable(true, _, _, CellularCapability::kTimeoutEnable))
       .WillOnce(