Add basic concept of module and module registry + dependency graph

Modules have protected lifecycle functions.
Modules are identified by a factory object that knows how to construct them.
Modules can indicate which dependencies they have.

Dependencies are started before their dependent modules.
Don't support incremental module stop for the moment - it's all or nothing.

Test: atest --host bluetooth_test_gd:ModuleTest
Change-Id: I026b9e893501506a6cea8387941b3a9424a9bec9
diff --git a/gd/Android.bp b/gd/Android.bp
index 1bbb95e..572eebc 100644
--- a/gd/Android.bp
+++ b/gd/Android.bp
@@ -99,6 +99,7 @@
     },
     srcs: [
         "stack_manager.cc",
+        "module.cc",
         ":BluetoothCommonSources",
         ":BluetoothHalSources",
         ":BluetoothPacketSources",
@@ -221,11 +222,17 @@
         },
     },
     srcs: [
+        "module_unittest.cc",
         ":BluetoothCommonTestSources",
         ":BluetoothHciTestSources",
         ":BluetoothL2capTestSources",
         ":BluetoothPacketTestSources",
     ],
+    cflags: [
+        "-Wno-unused-parameter",
+        "-Wno-implicit-fallthrough",
+        "-Wno-unused-result",
+    ],
     generated_headers : [
         "BluetoothGeneratedPackets_h",
     ],
diff --git a/gd/module.cc b/gd/module.cc
new file mode 100644
index 0000000..95f4d10
--- /dev/null
+++ b/gd/module.cc
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "module.h"
+
+namespace bluetooth {
+
+ModuleFactory::ModuleFactory(std::function<Module*()> ctor) : ctor_(ctor) {
+}
+
+bool ModuleRegistry::IsStarted(const ModuleFactory* factory) const {
+  return started_modules_.find(factory) != started_modules_.end();
+}
+
+void ModuleRegistry::Start(ModuleList* modules) {
+  for (auto it = modules->list_.begin(); it != modules->list_.end(); it++) {
+    if (IsStarted(*it)) {
+      continue;
+    }
+
+    Module* instance = (*it)->ctor_();
+    ModuleList dependencies;
+    instance->ListDependencies(&dependencies);
+    Start(&dependencies);
+
+    instance->Start(this);
+    start_order_.push_back(*it);
+    started_modules_[*it] = instance;
+  }
+}
+
+void ModuleRegistry::StopAll() {
+  // Since modules were brought up in dependency order,
+  // it is safe to tear down by going in reverse order.
+  for (auto it = start_order_.rbegin(); it != start_order_.rend(); it++) {
+    auto instance = started_modules_.find(*it);
+    ASSERT(instance != started_modules_.end());
+    instance->second->Stop(this);
+
+    delete instance->second;
+    started_modules_.erase(instance);
+  }
+
+  ASSERT(started_modules_.empty());
+  start_order_.clear();
+}
+}  // namespace bluetooth
diff --git a/gd/module.h b/gd/module.h
new file mode 100644
index 0000000..2e78bca
--- /dev/null
+++ b/gd/module.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <functional>
+#include <vector>
+#include <map>
+
+#include "os/log.h"
+
+namespace bluetooth {
+
+class Module;
+class ModuleRegistry;
+
+class ModuleFactory {
+ friend ModuleRegistry;
+ public:
+  ModuleFactory(std::function<Module*()> ctor);
+
+ private:
+  std::function<Module*()> ctor_;
+};
+
+class ModuleList {
+ friend ModuleRegistry;
+ public:
+  template <class T>
+  void add() {
+    list_.push_back(&T::Factory);
+  }
+
+ private:
+  std::vector<const ModuleFactory*> list_;
+};
+
+// Each leaf node module must have a factory like so:
+//
+// static const ModuleFactory Factory;
+//
+// which will provide a constructor for the module registry to call.
+// The module registry will also use the Factory as the identifier
+// for that module.
+class Module {
+ friend ModuleRegistry;
+ public:
+  virtual ~Module() = default;
+ protected:
+  // Populate the provided list with modules that must start before yours
+  virtual void ListDependencies(ModuleList* list) = 0;
+
+  // You can grab your started dependencies from the registry in this call
+  virtual void Start(const ModuleRegistry* registry) = 0;
+
+  // Release all resources, you're about to be deleted
+  virtual void Stop(const ModuleRegistry* registry) = 0;
+};
+
+class ModuleRegistry {
+ public:
+  template <class T>
+  T* GetInstance() const {
+    auto instance = started_modules_.find(&T::Factory);
+    ASSERT(instance != started_modules_.end());
+    return static_cast<T *>(instance->second);
+  };
+
+  template <class T>
+  bool IsStarted() const {
+    return IsStarted(&T::Factory);
+  }
+
+  bool IsStarted(const ModuleFactory* factory) const;
+
+  // Start all the modules on this list and their dependencies
+  // in dependency order
+  void Start(ModuleList* modules);
+
+  // Stop all running modules in reverse order of start
+  void StopAll();
+
+ private:
+  std::map<const ModuleFactory*, Module*> started_modules_;
+  std::vector<const ModuleFactory*> start_order_;
+};
+
+}  // namespace bluetooth
diff --git a/gd/module_unittest.cc b/gd/module_unittest.cc
new file mode 100644
index 0000000..62e8966
--- /dev/null
+++ b/gd/module_unittest.cc
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "module.h"
+
+#include "gtest/gtest.h"
+
+namespace bluetooth {
+namespace {
+
+class ModuleTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    registry_ = new ModuleRegistry();
+  }
+
+  void TearDown() override {
+    delete registry_;
+  }
+
+  ModuleRegistry* registry_;
+};
+
+class TestModuleNoDependency : public Module {
+ public:
+  static const ModuleFactory Factory;
+
+ protected:
+  void ListDependencies(ModuleList* list) override {
+  }
+
+  void Start(const ModuleRegistry* registry) override {
+    // A module is not considered started until Start() finishes
+    EXPECT_FALSE(registry->IsStarted<TestModuleNoDependency>());
+  }
+
+  void Stop(const ModuleRegistry* registry) override {
+    // A module is not considered stopped until after Stop() finishes
+    EXPECT_TRUE(registry->IsStarted<TestModuleNoDependency>());
+  }
+};
+
+const ModuleFactory TestModuleNoDependency::Factory = ModuleFactory([]() {
+  return new TestModuleNoDependency();
+});
+
+class TestModuleOneDependency : public Module {
+ public:
+  static const ModuleFactory Factory;
+
+ protected:
+  void ListDependencies(ModuleList* list) override {
+    list->add<TestModuleNoDependency>();
+  }
+
+  void Start(const ModuleRegistry* registry) override {
+    EXPECT_TRUE(registry->IsStarted<TestModuleNoDependency>());
+
+    // A module is not considered started until Start() finishes
+    EXPECT_FALSE(registry->IsStarted<TestModuleOneDependency>());
+  }
+
+  void Stop(const ModuleRegistry* registry) override {
+    EXPECT_TRUE(registry->IsStarted<TestModuleNoDependency>());
+
+    // A module is not considered stopped until after Stop() finishes
+    EXPECT_TRUE(registry->IsStarted<TestModuleOneDependency>());
+  }
+};
+
+const ModuleFactory TestModuleOneDependency::Factory = ModuleFactory([]() {
+  return new TestModuleOneDependency();
+});
+
+
+class TestModuleNoDependencyTwo : public Module {
+ public:
+  static const ModuleFactory Factory;
+
+ protected:
+  void ListDependencies(ModuleList* list) override {
+  }
+
+  void Start(const ModuleRegistry* registry) override {
+    // A module is not considered started until Start() finishes
+    EXPECT_FALSE(registry->IsStarted<TestModuleNoDependencyTwo>());
+  }
+
+  void Stop(const ModuleRegistry* registry) override {
+    // A module is not considered stopped until after Stop() finishes
+    EXPECT_TRUE(registry->IsStarted<TestModuleNoDependencyTwo>());
+  }
+};
+
+const ModuleFactory TestModuleNoDependencyTwo::Factory = ModuleFactory([]() {
+  return new TestModuleNoDependencyTwo();
+});
+
+class TestModuleTwoDependencies : public Module {
+ public:
+  static const ModuleFactory Factory;
+
+ protected:
+  void ListDependencies(ModuleList* list) override {
+    list->add<TestModuleOneDependency>();
+    list->add<TestModuleNoDependencyTwo>();
+  }
+
+  void Start(const ModuleRegistry* registry) override {
+    EXPECT_TRUE(registry->IsStarted<TestModuleOneDependency>());
+    EXPECT_TRUE(registry->IsStarted<TestModuleNoDependencyTwo>());
+
+    // A module is not considered started until Start() finishes
+    EXPECT_FALSE(registry->IsStarted<TestModuleTwoDependencies>());
+  }
+
+  void Stop(const ModuleRegistry* registry) override {
+    EXPECT_TRUE(registry->IsStarted<TestModuleOneDependency>());
+    EXPECT_TRUE(registry->IsStarted<TestModuleNoDependencyTwo>());
+
+    // A module is not considered stopped until after Stop() finishes
+    EXPECT_TRUE(registry->IsStarted<TestModuleTwoDependencies>());
+  }
+};
+
+const ModuleFactory TestModuleTwoDependencies::Factory = ModuleFactory([]() {
+  return new TestModuleTwoDependencies();
+});
+
+TEST_F(ModuleTest, no_dependency) {
+  ModuleList list;
+  list.add<TestModuleNoDependency>();
+  registry_->Start(&list);
+
+  EXPECT_TRUE(registry_->IsStarted<TestModuleNoDependency>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleOneDependency>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleNoDependencyTwo>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleTwoDependencies>());
+
+  registry_->StopAll();
+
+  EXPECT_FALSE(registry_->IsStarted<TestModuleNoDependency>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleOneDependency>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleNoDependencyTwo>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleTwoDependencies>());
+}
+
+TEST_F(ModuleTest, one_dependency) {
+  ModuleList list;
+  list.add<TestModuleOneDependency>();
+  registry_->Start(&list);
+
+  EXPECT_TRUE(registry_->IsStarted<TestModuleNoDependency>());
+  EXPECT_TRUE(registry_->IsStarted<TestModuleOneDependency>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleNoDependencyTwo>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleTwoDependencies>());
+
+  registry_->StopAll();
+
+  EXPECT_FALSE(registry_->IsStarted<TestModuleNoDependency>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleOneDependency>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleNoDependencyTwo>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleTwoDependencies>());
+}
+
+TEST_F(ModuleTest, two_dependencies) {
+  ModuleList list;
+  list.add<TestModuleTwoDependencies>();
+  registry_->Start(&list);
+
+  EXPECT_TRUE(registry_->IsStarted<TestModuleNoDependency>());
+  EXPECT_TRUE(registry_->IsStarted<TestModuleOneDependency>());
+  EXPECT_TRUE(registry_->IsStarted<TestModuleNoDependencyTwo>());
+  EXPECT_TRUE(registry_->IsStarted<TestModuleTwoDependencies>());
+
+  registry_->StopAll();
+
+  EXPECT_FALSE(registry_->IsStarted<TestModuleNoDependency>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleOneDependency>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleNoDependencyTwo>());
+  EXPECT_FALSE(registry_->IsStarted<TestModuleTwoDependencies>());
+}
+
+}  // namespace
+}  // namespace bluetooth