apmanager: add support for HT capability

Parse wiphy's HT capability and add it to the AP service's configuration
file to correctly support AP in 80211n mode.

BUG=chromium:431763
TEST=unittests and manual test by using python to invoke dbus calls
     to start AP service in 802.11n mode.

Change-Id: I6c902136832eea6b38b806f733231d6cbe14e3f6
Reviewed-on: https://chromium-review.googlesource.com/231681
Reviewed-by: Peter Qiu <zqiu@chromium.org>
Commit-Queue: Peter Qiu <zqiu@chromium.org>
Tested-by: Peter Qiu <zqiu@chromium.org>
diff --git a/config_unittest.cc b/config_unittest.cc
index c138846..f2297f6 100644
--- a/config_unittest.cc
+++ b/config_unittest.cc
@@ -15,9 +15,10 @@
 #include "apmanager/mock_device.h"
 #include "apmanager/mock_manager.h"
 
+using ::testing::_;
 using ::testing::Mock;
 using ::testing::Return;
-
+using ::testing::SetArgumentPointee;
 namespace apmanager {
 
 namespace {
@@ -26,39 +27,47 @@
 const char kSsid[] = "TestSsid";
 const char kInterface[] = "uap0";
 const char kPassphrase[] = "Passphrase";
+const char k24GHzHTCapab[] = "[LDPC SMPS-STATIC GF SHORT-GI-20]";
+const char k5GHzHTCapab[] =
+    "[LDPC HT40+ SMPS-STATIC GF SHORT-GI-20 SHORT-GI-40]";
+
 const uint16_t k24GHzChannel = 6;
 const uint16_t k5GHzChannel = 36;
 
 const char kExpected80211gConfigContent[] = "ssid=TestSsid\n"
                                             "channel=6\n"
-                                            "hw_mode=g\n"
                                             "interface=uap0\n"
+                                            "hw_mode=g\n"
                                             "driver=nl80211\n"
                                             "fragm_threshold=2346\n"
                                             "rts_threshold=2347\n";
 
-const char kExpected80211n5GHzConfigContent[] = "ssid=TestSsid\n"
-                                                "channel=36\n"
-                                                "ieee80211n=1\n"
-                                                "hw_mode=a\n"
-                                                "interface=uap0\n"
-                                                "driver=nl80211\n"
-                                                "fragm_threshold=2346\n"
-                                                "rts_threshold=2347\n";
+const char kExpected80211n5GHzConfigContent[] =
+    "ssid=TestSsid\n"
+    "channel=36\n"
+    "interface=uap0\n"
+    "ieee80211n=1\n"
+    "ht_capab=[LDPC HT40+ SMPS-STATIC GF SHORT-GI-20 SHORT-GI-40]\n"
+    "hw_mode=a\n"
+    "driver=nl80211\n"
+    "fragm_threshold=2346\n"
+    "rts_threshold=2347\n";
 
-const char kExpected80211n24GHzConfigContent[] = "ssid=TestSsid\n"
-                                                 "channel=6\n"
-                                                 "ieee80211n=1\n"
-                                                 "hw_mode=g\n"
-                                                 "interface=uap0\n"
-                                                 "driver=nl80211\n"
-                                                 "fragm_threshold=2346\n"
-                                                 "rts_threshold=2347\n";
+const char kExpected80211n24GHzConfigContent[] =
+    "ssid=TestSsid\n"
+    "channel=6\n"
+    "interface=uap0\n"
+    "ieee80211n=1\n"
+    "ht_capab=[LDPC SMPS-STATIC GF SHORT-GI-20]\n"
+    "hw_mode=g\n"
+    "driver=nl80211\n"
+    "fragm_threshold=2346\n"
+    "rts_threshold=2347\n";
 
 const char kExpectedRsnConfigContent[] = "ssid=TestSsid\n"
                                          "channel=6\n"
-                                         "hw_mode=g\n"
                                          "interface=uap0\n"
+                                         "hw_mode=g\n"
                                          "wpa=2\n"
                                          "rsn_pairwise=CCMP\n"
                                          "wpa_key_mgmt=WPA-PSK\n"
@@ -75,15 +84,16 @@
 
   void SetupDevice(const std::string& interface) {
     // Setup mock device.
-    scoped_refptr<MockDevice> device = new MockDevice();
-    device->SetPreferredApInterface(interface);
+    device_ = new MockDevice();
+    device_->SetPreferredApInterface(interface);
     EXPECT_CALL(manager_, GetDeviceFromInterfaceName(interface))
-        .WillRepeatedly(Return(device));
+        .WillRepeatedly(Return(device_));
   }
 
  protected:
   Config config_;
   MockManager manager_;
+  scoped_refptr<MockDevice> device_;
 };
 
 MATCHER_P(IsConfigErrorStartingWith, message, "") {
@@ -93,6 +103,29 @@
       StartsWithASCII(arg->GetMessage(), message, false);
 }
 
+TEST_F(ConfigTest, GetFrequencyFromChannel) {
+  uint32_t frequency;
+  // Invalid channel.
+  EXPECT_FALSE(Config::GetFrequencyFromChannel(0, &frequency));
+  EXPECT_FALSE(Config::GetFrequencyFromChannel(166, &frequency));
+  EXPECT_FALSE(Config::GetFrequencyFromChannel(14, &frequency));
+  EXPECT_FALSE(Config::GetFrequencyFromChannel(33, &frequency));
+
+  // Valid channel.
+  const uint32_t kChannel1Frequency = 2412;
+  const uint32_t kChannel13Frequency = 2472;
+  const uint32_t kChannel34Frequency = 5170;
+  const uint32_t kChannel165Frequency = 5825;
+  EXPECT_TRUE(Config::GetFrequencyFromChannel(1, &frequency));
+  EXPECT_EQ(kChannel1Frequency, frequency);
+  EXPECT_TRUE(Config::GetFrequencyFromChannel(13, &frequency));
+  EXPECT_EQ(kChannel13Frequency, frequency);
+  EXPECT_TRUE(Config::GetFrequencyFromChannel(34, &frequency));
+  EXPECT_EQ(kChannel34Frequency, frequency);
+  EXPECT_TRUE(Config::GetFrequencyFromChannel(165, &frequency));
+  EXPECT_EQ(kChannel165Frequency, frequency);
+}
+
 TEST_F(ConfigTest, NoSsid) {
   config_.SetChannel(k24GHzChannel);
   config_.SetHwMode(kHwMode80211g);
@@ -165,6 +198,9 @@
   config_.SetChannel(k5GHzChannel);
   std::string ghz5_config_content;
   chromeos::ErrorPtr error;
+  std::string ht_capab_5ghz(k5GHzHTCapab);
+  EXPECT_CALL(*device_.get(), GetHTCapability(k5GHzChannel, _))
+      .WillOnce(DoAll(SetArgumentPointee<1>(ht_capab_5ghz), Return(true)));
   EXPECT_TRUE(config_.GenerateConfigFile(&error, &ghz5_config_content));
   EXPECT_NE(std::string::npos, ghz5_config_content.find(
                                    kExpected80211n5GHzConfigContent))
@@ -172,11 +208,15 @@
       << kExpected80211n5GHzConfigContent << "..within content...\n"
       << ghz5_config_content;
   EXPECT_EQ(nullptr, error.get());
+  Mock::VerifyAndClearExpectations(device_.get());
 
   // 2.4GHz channel.
   config_.SetChannel(k24GHzChannel);
   std::string ghz24_config_content;
   chromeos::ErrorPtr error1;
+  std::string ht_capab_24ghz(k24GHzHTCapab);
+  EXPECT_CALL(*device_.get(), GetHTCapability(k24GHzChannel, _))
+      .WillOnce(DoAll(SetArgumentPointee<1>(ht_capab_24ghz), Return(true)));
   EXPECT_TRUE(config_.GenerateConfigFile(&error1, &ghz24_config_content));
   EXPECT_NE(std::string::npos, ghz24_config_content.find(
                                    kExpected80211n24GHzConfigContent))
@@ -184,6 +224,7 @@
       << kExpected80211n24GHzConfigContent << "..within content...\n"
       << ghz24_config_content;
   EXPECT_EQ(nullptr, error.get());
+  Mock::VerifyAndClearExpectations(device_.get());
 }
 
 TEST_F(ConfigTest, RsnConfig) {