apmanager: support for WiFi devices and interfaces

Added DeviceInfo for enumerating WiFi devices (PHYs) and detecting
WiFi interfaces. Also Created a Device class for abstracting WiFi PHYs,
which will maintain the device's capabilities and manage interfaces
created on the device.

Integrate Device with Manager and Config to allow user to start
an AP service without providing interface information.

Next up, will focus on parsing HT/VHT capabilities for each band and
integrate it into ap configuration. Also adding shill support for
claim/release interface.

BUG=chromium:431763
TEST=unittest

Change-Id: I62f4251064483b57e264d1278fde68022a737aea
Reviewed-on: https://chromium-review.googlesource.com/231257
Reviewed-by: Peter Qiu <zqiu@chromium.org>
Commit-Queue: Peter Qiu <zqiu@chromium.org>
Tested-by: Peter Qiu <zqiu@chromium.org>
diff --git a/manager.cc b/manager.cc
index 9842b41..b4d84ef 100644
--- a/manager.cc
+++ b/manager.cc
@@ -10,12 +10,15 @@
 using chromeos::dbus_utils::AsyncEventSequencer;
 using chromeos::dbus_utils::ExportedObjectManager;
 using chromeos::dbus_utils::DBusMethodResponse;
+using std::string;
 
 namespace apmanager {
 
 Manager::Manager()
     : org::chromium::apmanager::ManagerAdaptor(this),
-      service_identifier_(0) {}
+      service_identifier_(0),
+      device_identifier_(0),
+      device_info_(this) {}
 
 Manager::~Manager() {}
 
@@ -32,10 +35,19 @@
       sequencer->GetHandler("Manager.RegisterAsync() failed.", true));
 }
 
+void Manager::Start() {
+  device_info_.Start();
+}
+
+void Manager::Stop() {
+  device_info_.Stop();
+}
+
 void Manager::CreateService(
     scoped_ptr<DBusMethodResponse<dbus::ObjectPath>> response) {
+  LOG(INFO) << "Manager::CreateService";
   scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
-  scoped_ptr<Service> service(new Service(service_identifier_++));
+  scoped_ptr<Service> service(new Service(this, service_identifier_++));
 
   service->RegisterAsync(dbus_object_->GetObjectManager().get(), sequencer);
   sequencer->OnAllTasksCompletedCall({
@@ -61,10 +73,45 @@
   return false;
 }
 
+scoped_refptr<Device> Manager::GetAvailableDevice() {
+  for (const auto& device : devices_) {
+    if (!device->GetInUsed()) {
+      return device;
+    }
+  }
+  return nullptr;
+}
+
+scoped_refptr<Device> Manager::GetDeviceFromInterfaceName(
+    const string& interface_name) {
+  for (const auto& device : devices_) {
+    if (device->InterfaceExists(interface_name)) {
+      return device;
+    }
+  }
+  return nullptr;
+}
+
+void Manager::RegisterDevice(scoped_refptr<Device> device) {
+  LOG(INFO) << "Manager::RegisterDevice: registering device "
+            << device->GetDeviceName();
+  // Register device DBbus interfaces.
+  scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
+  device->RegisterAsync(dbus_object_->GetObjectManager().get(),
+                        sequencer,
+                        device_identifier_++);
+  sequencer->OnAllTasksCompletedCall({
+    base::Bind(&Manager::DeviceRegistered,
+               base::Unretained(this),
+               device)
+  });
+}
+
 void Manager::ServiceRegistered(
     scoped_ptr<DBusMethodResponse<dbus::ObjectPath>> response,
     scoped_ptr<Service> service,
     bool success) {
+  LOG(INFO) << "ServiceRegistered";
   // Success should always be true since we've said that failures are fatal.
   CHECK(success) << "Init of one or more objects has failed.";
 
@@ -75,4 +122,12 @@
   response->Return(service_path);
 }
 
+void Manager::DeviceRegistered(scoped_refptr<Device> device, bool success) {
+  // Success should always be true since we've said that failures are fatal.
+  CHECK(success) << "Init of one or more objects has failed.";
+
+  devices_.push_back(device);
+  // TODO(zqiu): Property update for available devices.
+}
+
 }  // namespace apmanager