service: Refactor IPC and singletons

This CL makes the following major refactors to the system service code:

  1. A new global Daemon object is introduced, which manages the main event
  loop and all other subsystems of the Bluetooth daemon. This object is the only
  singleton class and initializes and owns everything else.

  2. Everything that was a singleton and/or was initialized directly in main.cpp
  is now a) no longer a singleton; b) now initialized and owned by the global
  Daemon instance.

  3. All of the Chromecast specific IPC code has been moved into the ipc/
  subdirectory. This directory is meant for everything that is IPC related,
  paving the way for enabling multiple IPC systems (domain-socket based, Binder
  based, etc) simultaneously in the future. Main changes to the Chromecast IPC
  code are:

      a. All files and classes have been renamed to reflect the
      UNIX-domain-socket-specific nature of the IPC mechanism.

      b. The code no longer hogs up the main thread while listening for
      connections. All of this logic has been moved to a dedicated thread with
      its own MessageLoopForIO, so that it can use the built-in mechanisms for
      polling on client sockets in the future.

Bug: 22532180
Change-Id: I42db06dba6cff3bc8f8101a1ea2b6787a69409fd
diff --git a/service/Android.mk b/service/Android.mk
index 5dce8b8..9eed95f 100644
--- a/service/Android.mk
+++ b/service/Android.mk
@@ -37,8 +37,12 @@
 LOCAL_SRC_FILES := \
 	a2dp_source.cpp \
 	core_stack.cpp \
+	daemon.cpp \
 	gatt_server.cpp \
-	host.cpp \
+	ipc/ipc_handler.cpp \
+	ipc/ipc_handler_unix.cpp \
+	ipc/ipc_manager.cpp \
+	ipc/unix_ipc_host.cpp \
 	logging_helpers.cpp \
 	main.cpp \
 	settings.cpp \
diff --git a/service/BUILD.gn b/service/BUILD.gn
index b2124387..f2b3771 100644
--- a/service/BUILD.gn
+++ b/service/BUILD.gn
@@ -18,8 +18,12 @@
   sources = [
     "a2dp_source.cpp",
     "core_stack.cpp",
+    "daemon.cpp",
     "gatt_server.cpp",
-    "host.cpp",
+    "ipc/ipc_handler.cpp",
+    "ipc/ipc_handler_unix.cpp",
+    "ipc/ipc_manager.cpp",
+    "ipc/unix_ipc_host.cpp",
     "logging_helpers.cpp",
     "settings.cpp",
     "uuid.cpp"
diff --git a/service/daemon.cpp b/service/daemon.cpp
new file mode 100644
index 0000000..a88fc5f
--- /dev/null
+++ b/service/daemon.cpp
@@ -0,0 +1,108 @@
+//
+//  Copyright (C) 2015 Google, Inc.
+//
+//  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 "service/daemon.h"
+
+#include <base/logging.h>
+
+#include "service/core_stack.h"
+#include "service/ipc/ipc_manager.h"
+#include "service/settings.h"
+
+namespace bluetooth {
+
+namespace {
+
+// The global Daemon instance.
+Daemon* g_daemon = nullptr;
+
+}  // namespace
+
+// static
+bool Daemon::Initialize() {
+  CHECK(!g_daemon);
+
+  g_daemon = new Daemon();
+  if (g_daemon->Init())
+    return true;
+
+  LOG(ERROR) << "Failed to initialize the Daemon object";
+
+  delete g_daemon;
+  g_daemon = nullptr;
+
+  return false;
+}
+
+// static
+void Daemon::ShutDown() {
+  CHECK(g_daemon);
+  CHECK(g_daemon->initialized_);
+
+  delete g_daemon;
+  g_daemon = NULL;
+}
+
+// static
+Daemon* Daemon::Get() {
+  CHECK(g_daemon);
+  return g_daemon;
+}
+
+Daemon::Daemon() : initialized_(false) {
+}
+
+Daemon::~Daemon() {
+}
+
+void Daemon::StartMainLoop() {
+  CHECK(initialized_);
+  message_loop_->Run();
+}
+
+bool Daemon::Init() {
+  CHECK(!initialized_);
+
+  message_loop_.reset(new base::MessageLoop());
+
+  settings_.reset(new Settings());
+  if (!settings_->Init()) {
+    LOG(ERROR) << "Failed to set up Settings";
+    return false;
+  }
+
+  core_stack_.reset(new CoreStack());
+  if (!core_stack_->Initialize()) {
+    LOG(ERROR) << "Failed to set up CoreStack";
+    return false;
+  }
+
+  ipc_manager_.reset(new ipc::IPCManager(core_stack_.get()));
+
+  // If an IPC socket path was given, initialize the UNIX domain socket based
+  // IPC layer.
+  if (!settings_->ipc_socket_path().empty() &&
+      !ipc_manager_->Start(ipc::IPCManager::TYPE_UNIX)) {
+    LOG(ERROR) << "Failed to set up UNIX domain-socket IPCManager";
+    return false;
+  }
+
+  initialized_ = true;
+
+  return true;
+}
+
+}  // namespace bluetooth
diff --git a/service/daemon.h b/service/daemon.h
new file mode 100644
index 0000000..ab0225f
--- /dev/null
+++ b/service/daemon.h
@@ -0,0 +1,77 @@
+//
+//  Copyright (C) 2015 Google, Inc.
+//
+//  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 <memory>
+
+#include <base/macros.h>
+#include <base/message_loop/message_loop.h>
+
+namespace ipc {
+class IPCManager;
+}  // namespace ipc
+
+namespace bluetooth {
+
+class CoreStack;
+class Settings;
+
+// The Daemon class is a singleton that represents the root of the ownership
+// hierarchy. The single instance sets up and owns the main event loop, the IPC
+// handlers, global Settings, and the core Bluetooth stack.
+class Daemon {
+ public:
+  // Initializes the daemon. This must be called to at the start of the
+  // application to set up the global daemon instance and everything it manages.
+  // Returns false in case of a failure.
+  static bool Initialize();
+
+  // Cleans up all the resources associated with the global Daemon object.
+  static void ShutDown();
+
+  // Returns the singleton Daemon instance. All classes can interact with the
+  // Daemon, obtain its resources etc using this getter.
+  static Daemon* Get();
+
+  // The global Settings object. All classes have direct access to this through
+  // the Daemon object.
+  Settings* settings() const { return settings_.get(); }
+
+  // The main event loop. This should be used for any events and delayed tasks
+  // that should be executed on the daemon's main thread.
+  base::MessageLoop* message_loop() const { return message_loop_.get(); }
+
+  // Starts the daemon's main loop.
+  void StartMainLoop();
+
+ private:
+  Daemon();
+  ~Daemon();
+
+  // Private instance helper for Initialize().
+  bool Init();
+
+  bool initialized_;
+  std::unique_ptr<base::MessageLoop> message_loop_;
+  std::unique_ptr<Settings> settings_;
+  std::unique_ptr<CoreStack> core_stack_;
+  std::unique_ptr<ipc::IPCManager> ipc_manager_;
+
+  DISALLOW_COPY_AND_ASSIGN(Daemon);
+};
+
+}  // namespace bluetooth
diff --git a/service/ipc/ipc_handler.cpp b/service/ipc/ipc_handler.cpp
new file mode 100644
index 0000000..9013f84
--- /dev/null
+++ b/service/ipc/ipc_handler.cpp
@@ -0,0 +1,31 @@
+//
+//  Copyright (C) 2015 Google, Inc.
+//
+//  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 "service/ipc/ipc_handler.h"
+
+#include <base/logging.h>
+
+namespace ipc {
+
+IPCHandler::IPCHandler(bluetooth::CoreStack* core_stack)
+    : core_stack_(core_stack) {
+  CHECK(core_stack_);
+}
+
+IPCHandler::~IPCHandler() {
+}
+
+}  // namespace ipc
diff --git a/service/ipc/ipc_handler.h b/service/ipc/ipc_handler.h
new file mode 100644
index 0000000..aa658e5
--- /dev/null
+++ b/service/ipc/ipc_handler.h
@@ -0,0 +1,49 @@
+//
+//  Copyright (C) 2015 Google, Inc.
+//
+//  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 <base/macros.h>
+#include <base/memory/ref_counted.h>
+
+namespace bluetooth {
+class CoreStack;
+}  // namespace bluetooth
+
+namespace ipc {
+
+// IPCHandler is an interface that classes implementing different IPC mechanisms
+// must conform to.
+class IPCHandler : public base::RefCountedThreadSafe<IPCHandler> {
+ public:
+  explicit IPCHandler(bluetooth::CoreStack* core_stack);
+  virtual ~IPCHandler();
+
+  // Initializes and runs the IPC mechanis. Returns true on success, false
+  // otherwise.
+  virtual bool Run() = 0;
+
+ protected:
+  // Weak reference to the global CoreStack instance.
+  bluetooth::CoreStack* core_stack_;
+
+ private:
+  IPCHandler() = default;
+
+  DISALLOW_COPY_AND_ASSIGN(IPCHandler);
+};
+
+}  // namespace ipc
diff --git a/service/ipc/ipc_handler_unix.cpp b/service/ipc/ipc_handler_unix.cpp
new file mode 100644
index 0000000..37df848
--- /dev/null
+++ b/service/ipc/ipc_handler_unix.cpp
@@ -0,0 +1,135 @@
+//
+//  Copyright (C) 2015 Google, Inc.
+//
+//  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 "service/ipc/ipc_handler_unix.h"
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <base/bind.h>
+
+#include "service/daemon.h"
+#include "service/ipc/unix_ipc_host.h"
+#include "service/settings.h"
+
+namespace ipc {
+
+IPCHandlerUnix::IPCHandlerUnix(bluetooth::CoreStack* core_stack)
+    : IPCHandler(core_stack),
+      running_(false),
+      thread_("IPCHandlerUnix") {
+}
+
+IPCHandlerUnix::~IPCHandlerUnix() {
+}
+
+bool IPCHandlerUnix::Run() {
+  CHECK(!running_);
+
+  const base::FilePath& path =
+      bluetooth::Daemon::Get()->settings()->ipc_socket_path();
+  if (path.empty()) {
+    LOG(ERROR) << "No domain socket path provided";
+    return false;
+  }
+
+  CHECK(base::MessageLoop::current());  // An origin event loop is required.
+  origin_task_runner_ = base::MessageLoop::current()->task_runner();
+
+  // TODO(armansito): This is opens the door to potentially unlinking files in
+  // the current directory that we're not supposed to. For now we will have an
+  // assumption that the daemon runs in a sandbox but we should generally do
+  // this properly.
+  //
+  // Also, the daemon should clean this up properly as it shuts down.
+  unlink(path.value().c_str());
+
+  base::ScopedFD server_socket(socket(PF_UNIX, SOCK_SEQPACKET, 0));
+  if (!server_socket.is_valid()) {
+    LOG(ERROR) << "Failed to open domain socket for IPC";
+    return false;
+  }
+
+  struct sockaddr_un address;
+  memset(&address, 0, sizeof(address));
+  address.sun_family = AF_UNIX;
+  strncpy(address.sun_path, path.value().c_str(), sizeof(address.sun_path) - 1);
+  if (bind(server_socket.get(), (struct sockaddr*)&address,
+           sizeof(address)) < 0) {
+    LOG(ERROR) << "Failed to bind IPC socket to address: " << strerror(errno);
+    return false;
+  }
+
+  socket_.swap(server_socket);
+  running_ = true;  // Set this here before launching the thread.
+
+  // Start an IO thread and post the listening task.
+  base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
+  if (!thread_.StartWithOptions(options)) {
+    LOG(ERROR) << "Failed to start IPCHandlerUnix thread";
+    running_ = false;
+    return false;
+  }
+
+  thread_.task_runner()->PostTask(
+      FROM_HERE,
+      base::Bind(&IPCHandlerUnix::StartListeningOnThread, this));
+
+  return true;
+}
+
+void IPCHandlerUnix::StartListeningOnThread() {
+  CHECK(socket_.is_valid());
+  CHECK(core_stack_);
+  CHECK(running_);
+
+  LOG(INFO) << "Listening to incoming connections";
+
+  int status = listen(socket_.get(), SOMAXCONN);
+  if (status < 0) {
+    LOG(ERROR) << "Failed to listen on domain socket: " << strerror(errno);
+    origin_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&IPCHandlerUnix::ShutDownOnOriginThread, this));
+    return;
+  }
+
+  // TODO(icoolidge): accept simultaneous clients
+  while (true) {
+    int client_socket = accept4(socket_.get(), nullptr, nullptr, SOCK_NONBLOCK);
+    if (status == -1) {
+      LOG(ERROR) << "Failed to accept client connection: " << strerror(errno);
+      continue;
+    }
+
+    LOG(INFO) << "Established client connection: fd=" << client_socket;
+    UnixIPCHost ipc_host(client_socket, core_stack_);
+    // TODO(armansito): Use |thread_|'s MessageLoopForIO instead of using a
+    // custom event loop to poll from the socket.
+    ipc_host.EventLoop();
+  }
+}
+
+void IPCHandlerUnix::ShutDownOnOriginThread() {
+  LOG(INFO) << "Shutting down IPCHandlerUnix thread";
+  thread_.Stop();
+  running_ = false;
+
+  // TODO(armansito): Notify the upper layer so that they can perform clean-up
+  // tasks on unexpected shut-down.
+}
+
+}  // namespace ipc
diff --git a/service/ipc/ipc_handler_unix.h b/service/ipc/ipc_handler_unix.h
new file mode 100644
index 0000000..970dfa4
--- /dev/null
+++ b/service/ipc/ipc_handler_unix.h
@@ -0,0 +1,70 @@
+//
+//  Copyright (C) 2015 Google, Inc.
+//
+//  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 <base/files/scoped_file.h>
+#include <base/macros.h>
+#include <base/threading/thread.h>
+
+#include "service/ipc/ipc_handler.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}  // namespace base
+
+namespace bluetooth {
+class CoreStack;
+}  // namespace bluetooth
+
+namespace ipc {
+
+// Implements a UNIX domain-socket based IPCHandler
+class IPCHandlerUnix : public IPCHandler {
+ public:
+  explicit IPCHandlerUnix(bluetooth::CoreStack* core_stack);
+  ~IPCHandlerUnix() override;
+
+  // IPCHandler override:
+  bool Run() override;
+
+ private:
+  IPCHandlerUnix() = default;
+
+  // Starts listening for incoming connections. Posted on |thread_| by Run().
+  void StartListeningOnThread();
+
+  // Stops the IPC thread. This helper is needed since base::Thread requires
+  // threads to be stopped on the thread that started them.
+  void ShutDownOnOriginThread();
+
+  // True, if the IPC mechanism is running.
+  bool running_;
+
+  // The server socket on which we listen to incoming connections.
+  base::ScopedFD socket_;
+
+  // We use a dedicated thread for listening to incoming connections and
+  // polling from the socket to avoid blocking the main thread.
+  base::Thread thread_;
+
+  // The origin thread's task runner.
+  scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(IPCHandlerUnix);
+};
+
+}  // namespace ipc
diff --git a/service/ipc/ipc_manager.cpp b/service/ipc/ipc_manager.cpp
new file mode 100644
index 0000000..10eca04
--- /dev/null
+++ b/service/ipc/ipc_manager.cpp
@@ -0,0 +1,53 @@
+//
+//  Copyright (C) 2015 Google, Inc.
+//
+//  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 "service/ipc/ipc_manager.h"
+
+#include "service/ipc/ipc_handler_unix.h"
+
+namespace ipc {
+
+IPCManager::IPCManager(bluetooth::CoreStack* core_stack)
+    : core_stack_(core_stack) {
+  CHECK(core_stack_);
+}
+
+IPCManager::~IPCManager() {
+}
+
+bool IPCManager::Start(Type type) {
+  switch (type) {
+  case TYPE_UNIX:
+    unix_handler_ = new IPCHandlerUnix(core_stack_);
+    return unix_handler_->Run();
+  case TYPE_BINDER:
+    // TODO(armansito): Support Binder
+  default:
+    LOG(ERROR) << "Unsupported IPC type given: " << type;
+  }
+
+  return false;
+}
+
+bool IPCManager::BinderStarted() const {
+  return binder_handler_.get();
+}
+
+bool IPCManager::UnixStarted() const {
+  return unix_handler_.get();
+}
+
+}  // namespace ipc
diff --git a/service/ipc/ipc_manager.h b/service/ipc/ipc_manager.h
new file mode 100644
index 0000000..058ed43
--- /dev/null
+++ b/service/ipc/ipc_manager.h
@@ -0,0 +1,75 @@
+//
+//  Copyright (C) 2015 Google, Inc.
+//
+//  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 <memory>
+
+#include <base/macros.h>
+#include <base/memory/ref_counted.h>
+
+namespace bluetooth {
+class CoreStack;
+}  // namespace bluetooth
+
+namespace ipc {
+
+class IPCHandler;
+
+// IPCManager is a class for initializing and running supported IPC mechanisms.
+// It manages the life-time of different IPC flavors that are available on the
+// system. There are two flavors: a plain UNIX domain socket based system and
+// one based on the Binder-based android.bluetooth framework.
+class IPCManager {
+ public:
+  // Possible IPC types.
+  enum Type {
+    TYPE_UNIX,  // IPC based on a UNIX domain socket
+    TYPE_BINDER  // IPC based on the Binder
+  };
+
+  explicit IPCManager(bluetooth::CoreStack* core_stack);
+  ~IPCManager();
+
+  // Initialize the underlying IPC handler based on |type|, if that type has not
+  // yet been initialized and returns true on success. Returns false if that
+  // type has already been initialized or an error occurs.
+  //
+  // If TYPE_UNIX is given, the file path to use for the domain socket will be
+  // obtained from the global Settings object. Hence, the Settings object must
+  // have been initialized before calling this method.
+  bool Start(Type type);
+
+  // Returns true if an IPC type has been initialized.
+  bool BinderStarted() const;
+  bool UnixStarted() const;
+
+ private:
+  IPCManager() = default;
+
+  // Pointers to the different IPC handler classes. These are initialized and
+  // owned by us.
+  scoped_refptr<IPCHandler> binder_handler_;
+  scoped_refptr<IPCHandler> unix_handler_;
+
+  // The global CoreStack instance that represents the current Bluetooth
+  // adapter.
+  bluetooth::CoreStack* core_stack_;
+
+  DISALLOW_COPY_AND_ASSIGN(IPCManager);
+};
+
+}  // namespace ipc
diff --git a/service/host.cpp b/service/ipc/unix_ipc_host.cpp
similarity index 85%
rename from service/host.cpp
rename to service/ipc/unix_ipc_host.cpp
index af3c2c5..3ebc44a 100644
--- a/service/host.cpp
+++ b/service/ipc/unix_ipc_host.cpp
@@ -13,7 +13,8 @@
 //  See the License for the specific language governing permissions and
 //  limitations under the License.
 //
-#include "host.h"
+
+#include "service/ipc/unix_ipc_host.h"
 
 #include <errno.h>
 #include <stdio.h>
@@ -32,9 +33,14 @@
 
 #define LOG_TAG "bt_bluetooth_host"
 #include "osi/include/log.h"
-#include "core_stack.h"
-#include "gatt_server.h"
-#include "uuid.h"
+#include "service/core_stack.h"
+#include "service/gatt_server.h"
+#include "service/uuid.h"
+
+using bluetooth::CoreStack;
+using bluetooth::Uuid;
+
+using namespace bluetooth::gatt;
 
 namespace {
 
@@ -51,9 +57,9 @@
 const char kStopServiceCommand[] = "stop-service";
 const char kWriteCharacteristicCommand[] = "write-characteristic";
 
-// Useful values for indexing Host::pfds_
+// Useful values for indexing UnixIPCHost::pfds_
 // Not super general considering that we should be able to support
-// many GATT FDs owned by one Host.
+// many GATT FDs owned by one UnixIPCHost.
 enum {
   kFdIpc = 0,
   kFdGatt = 1,
@@ -66,16 +72,16 @@
 
 }  // namespace
 
-namespace bluetooth {
+namespace ipc {
 
-Host::Host(int sockfd, CoreStack* bt)
+UnixIPCHost::UnixIPCHost(int sockfd, CoreStack* bt)
     : bt_(bt), pfds_(1, {sockfd, POLLIN, 0}) {}
 
-Host::~Host() {
+UnixIPCHost::~UnixIPCHost() {
   close(pfds_[0].fd);
 }
 
-bool Host::EventLoop() {
+bool UnixIPCHost::EventLoop() {
   while (true) {
     int status =
         TEMP_FAILURE_RETRY(ppoll(pfds_.data(), pfds_.size(), nullptr, nullptr));
@@ -97,14 +103,14 @@
   return true;
 }
 
-bool Host::OnSetAdapterName(const std::string& name) {
+bool UnixIPCHost::OnSetAdapterName(const std::string& name) {
   std::string decoded_data;
   base::Base64Decode(name, &decoded_data);
   return bt_->SetAdapterName(decoded_data);
 }
 
-bool Host::OnCreateService(const std::string& service_uuid) {
-  gatt_servers_[service_uuid] = std::unique_ptr<gatt::Server>(new gatt::Server);
+bool UnixIPCHost::OnCreateService(const std::string& service_uuid) {
+  gatt_servers_[service_uuid] = std::unique_ptr<Server>(new Server);
 
   int gattfd;
   bool status =
@@ -118,14 +124,14 @@
   return true;
 }
 
-bool Host::OnDestroyService(const std::string& service_uuid) {
+bool UnixIPCHost::OnDestroyService(const std::string& service_uuid) {
   gatt_servers_.erase(service_uuid);
   close(pfds_[1].fd);
   pfds_.resize(1);
   return true;
 }
 
-bool Host::OnAddCharacteristic(const std::string& service_uuid,
+bool UnixIPCHost::OnAddCharacteristic(const std::string& service_uuid,
                                const std::string& characteristic_uuid,
                                const std::string& control_uuid,
                                const std::string& options) {
@@ -137,19 +143,19 @@
 
   if (std::find(option_tokens.begin(), option_tokens.end(), "notify") !=
       option_tokens.end()) {
-    permissions_mask |= gatt::kPermissionRead;
-    properties_mask |= gatt::kPropertyRead;
-    properties_mask |= gatt::kPropertyNotify;
+    permissions_mask |= kPermissionRead;
+    properties_mask |= kPropertyRead;
+    properties_mask |= kPropertyNotify;
   }
   if (std::find(option_tokens.begin(), option_tokens.end(), "read") !=
       option_tokens.end()) {
-    permissions_mask |= gatt::kPermissionRead;
-    properties_mask |= gatt::kPropertyRead;
+    permissions_mask |= kPermissionRead;
+    properties_mask |= kPropertyRead;
   }
   if (std::find(option_tokens.begin(), option_tokens.end(), "write") !=
       option_tokens.end()) {
-    permissions_mask |= gatt::kPermissionWrite;
-    properties_mask |= gatt::kPropertyWrite;
+    permissions_mask |= kPermissionWrite;
+    properties_mask |= kPropertyWrite;
   }
 
   if (control_uuid.empty()) {
@@ -163,7 +169,7 @@
   return true;
 }
 
-bool Host::OnSetCharacteristicValue(const std::string& service_uuid,
+bool UnixIPCHost::OnSetCharacteristicValue(const std::string& service_uuid,
                                     const std::string& characteristic_uuid,
                                     const std::string& value) {
   std::string decoded_data;
@@ -174,7 +180,7 @@
   return true;
 }
 
-bool Host::OnSetAdvertisement(const std::string& service_uuid,
+bool UnixIPCHost::OnSetAdvertisement(const std::string& service_uuid,
                               const std::string& advertise_uuids,
                               const std::string& advertise_data,
                               const std::string& transmit_name) {
@@ -197,7 +203,7 @@
   return true;
 }
 
-bool Host::OnSetScanResponse(const std::string& service_uuid,
+bool UnixIPCHost::OnSetScanResponse(const std::string& service_uuid,
                              const std::string& scan_response_uuids,
                              const std::string& scan_response_data,
                              const std::string& transmit_name) {
@@ -217,15 +223,15 @@
   return true;
 }
 
-bool Host::OnStartService(const std::string& service_uuid) {
+bool UnixIPCHost::OnStartService(const std::string& service_uuid) {
   return gatt_servers_[service_uuid]->Start();
 }
 
-bool Host::OnStopService(const std::string& service_uuid) {
+bool UnixIPCHost::OnStopService(const std::string& service_uuid) {
   return gatt_servers_[service_uuid]->Stop();
 }
 
-bool Host::OnMessage() {
+bool UnixIPCHost::OnMessage() {
   std::string ipc_msg;
   int size = recv(pfds_[kFdIpc].fd, &ipc_msg[0], 0, MSG_PEEK | MSG_TRUNC);
   if (-1 == size) {
@@ -281,7 +287,7 @@
   return false;
 }
 
-bool Host::OnGattWrite() {
+bool UnixIPCHost::OnGattWrite() {
   Uuid::Uuid128Bit id;
   int r = read(pfds_[kFdGatt].fd, id.data(), id.size());
   if (r != id.size()) {
@@ -311,4 +317,4 @@
   return true;
 }
 
-}  // namespace bluetooth
+}  // namespace ipc
diff --git a/service/host.h b/service/ipc/unix_ipc_host.h
similarity index 89%
rename from service/host.h
rename to service/ipc/unix_ipc_host.h
index e695717..4bcfad0 100644
--- a/service/host.h
+++ b/service/ipc/unix_ipc_host.h
@@ -21,22 +21,24 @@
 #include <string>
 #include <unordered_map>
 
-#include "gatt_server.h"
-#include "uuid.h"
+#include "service/gatt_server.h"
+#include "service/uuid.h"
 
 namespace bluetooth {
-
 class CoreStack;
+}  // namespace bluetooth
+
+namespace ipc {
 
 // This implements a single threaded event loop which dispatches
 // reads from a set of FDs (pfds_) to a set of handlers.
 // Reads from the GATT pipe read end will result in a write to
 // to the IPC socket, and vise versa.
-class Host {
+class UnixIPCHost {
  public:
-  // Host owns the passed sockfd.
-  Host(int sockfd, CoreStack* bt);
-  ~Host();
+  // UnixIPCHost owns the passed sockfd.
+  UnixIPCHost(int sockfd, bluetooth::CoreStack* bt);
+  ~UnixIPCHost();
 
   // Synchronously handle all events on input FDs.
   bool EventLoop();
@@ -89,14 +91,15 @@
   bool OnStopService(const std::string& service_uuid);
 
   // weak reference.
-  CoreStack *bt_;
+  bluetooth::CoreStack *bt_;
 
   // File descripters that we will block against.
   std::vector<struct pollfd> pfds_;
 
   // Container for multiple GATT servers. Currently only one is supported.
   // TODO(icoolidge): support many to one for real.
-  std::unordered_map<std::string, std::unique_ptr<gatt::Server>> gatt_servers_;
+  std::unordered_map<std::string, std::unique_ptr<bluetooth::gatt::Server>>
+      gatt_servers_;
 };
 
-}  // namespace bluetooth
+}  // namespace ipc
diff --git a/service/main.cpp b/service/main.cpp
index da973f3..b8245f6 100644
--- a/service/main.cpp
+++ b/service/main.cpp
@@ -14,29 +14,17 @@
 //  limitations under the License.
 //
 
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-
 #include <base/at_exit.h>
 #include <base/command_line.h>
 #include <base/files/scoped_file.h>
 
-#define LOG_TAG "bt_host"
 // For system properties
 // TODO(icoolidge): abstraction or non-cutils stub.
 #if !defined(OS_GENERIC)
 #include <cutils/properties.h>
 #endif  // !defined(OS_GENERIC)
 
-#include "osi/include/log.h"
-#include "osi/include/socket_utils/sockets.h"
-#include "service/core_stack.h"
-#include "service/host.h"
-#include "service/settings.h"
+#include "service/daemon.h"
 #include "service/switches.h"
 
 namespace {
@@ -65,78 +53,27 @@
     return EXIT_SUCCESS;
   }
 
-  if (!bluetooth::Settings::Initialize()) {
-    LOG(ERROR) << "Failed to parse the command-line.";
-    return EXIT_FAILURE;
-  }
-
-  // TODO(armansito): Move all of the IPC connection establishment into its own
-  // class. Here we should only need to initialize and start the main
-  // MessageLoop and the CoreStack instance.
-  int status;
-
 #if !defined(OS_GENERIC)
   // TODO(armansito): Remove Chromecast specific property out of here. This
   // should just be obtained from global config.
   char disable_value[PROPERTY_VALUE_MAX];
-  status = property_get(kDisableProperty, disable_value, nullptr);
+  int status = property_get(kDisableProperty, disable_value, nullptr);
   if (status && !strcmp(disable_value, "1")) {
     LOG(INFO) << "service disabled";
     return EXIT_SUCCESS;
   }
 #endif  // !defined(OS_GENERIC)
 
-  base::ScopedFD server_socket(socket(PF_UNIX, SOCK_SEQPACKET, 0));
-  if (!server_socket.is_valid()) {
-    LOG(ERROR) << "failed to open domain socket for IPC";
+  if (!bluetooth::Daemon::Initialize()) {
+    LOG(ERROR) << "Failed to initialize Daemon";
     return EXIT_FAILURE;
   }
 
-  // TODO(armansito): This is opens the door to potentially unlinking files in
-  // the current directory that we're not supposed to. For now we will have an
-  // assumption that the daemon runs in a sandbox but we should generally do
-  // this properly.
-  //
-  // Also, the daemon should clean this up properly as it shuts down.
-  unlink(bluetooth::Settings::Get().ipc_socket_path().value().c_str());
+  // Start the main event loop.
+  bluetooth::Daemon::Get()->StartMainLoop();
 
-  struct sockaddr_un address;
-  memset(&address, 0, sizeof(address));
-  address.sun_family = AF_UNIX;
-  strncpy(address.sun_path,
-          bluetooth::Settings::Get().ipc_socket_path().value().c_str(),
-          sizeof(address.sun_path) - 1);
-  if (bind(server_socket.get(), (struct sockaddr*)&address,
-           sizeof(address)) < 0) {
-    LOG(ERROR) << "Failed to bind IPC socket to address: " << strerror(errno);
-    return EXIT_FAILURE;
-  }
-
-  status = listen(server_socket.get(), SOMAXCONN);
-  if (status < 0) {
-    LOG(ERROR) << "Failed to listen on IPC socket: " << strerror(errno);
-    return EXIT_FAILURE;
-  }
-
-  bluetooth::CoreStack bt;
-  if (!bt.Initialize()) {
-    LOG(ERROR) << "Failed to initialize the Bluetooth stack";
-    return EXIT_FAILURE;
-  }
-
-  // TODO(icoolidge): accept simultaneous clients
-  while (true) {
-    int client_socket = accept4(server_socket.get(), nullptr,
-                                nullptr, SOCK_NONBLOCK);
-    if (status == -1) {
-      LOG(ERROR) << "accept failed: %s" << strerror(errno);
-      return EXIT_FAILURE;
-    }
-
-    LOG(INFO) << "client connected: %d" << client_socket;
-    bluetooth::Host bluetooth_host(client_socket, &bt);
-    bluetooth_host.EventLoop();
-  }
+  // The main message loop has exited; clean up the Daemon.
+  bluetooth::Daemon::Get()->ShutDown();
 
   return EXIT_SUCCESS;
 }
diff --git a/service/settings.cpp b/service/settings.cpp
index 874fc4e..2558eaa 100644
--- a/service/settings.cpp
+++ b/service/settings.cpp
@@ -17,37 +17,12 @@
 #include "service/settings.h"
 
 #include <base/command_line.h>
-#include <base/lazy_instance.h>
 #include <base/logging.h>
 
 #include "service/switches.h"
 
 namespace bluetooth {
 
-namespace {
-
-// The global settings instance. We use a LazyInstance here so that we can
-// lazily initialize the instance AND guarantee that it will be cleaned up at
-// exit time without violating the Google C++ style guide.
-base::LazyInstance<Settings> g_settings = LAZY_INSTANCE_INITIALIZER;
-
-void LogRequiredOption(const std::string& option) {
-  LOG(ERROR) << "Required option: \"" << option << "\"";
-}
-
-}  // namespace
-
-// static
-bool Settings::Initialize() {
-  return g_settings.Get().Init();
-}
-
-// static
-const Settings& Settings::Get() {
-  CHECK(g_settings.Get().initialized_);
-  return g_settings.Get();
-}
-
 Settings::Settings() : initialized_(false) {
 }
 
@@ -57,25 +32,24 @@
 bool Settings::Init() {
   CHECK(!initialized_);
   auto command_line = base::CommandLine::ForCurrentProcess();
+  const auto& switches = command_line->GetSwitches();
 
-  // Since we have only one meaningful command-line flag for now, it's OK to
-  // hard-code this here. As we add more switches, we should process this in a
-  // more meaningful way.
-  if (command_line->GetSwitches().size() > 1) {
-    LOG(ERROR) << "Unexpected command-line switches found";
-    return false;
-  }
+  for (const auto& iter : switches) {
+    if (iter.first == switches::kIPCSocketPath) {
+      // kIPCSocketPath: An optional argument that initializes an IPC socket
+      // path for IPC. If this is not present, the daemon will default to Binder
+      // for the IPC mechanism.
+      base::FilePath path(iter.second);
+      if (path.empty() || path.EndsWithSeparator()) {
+        LOG(ERROR) << "Invalid IPC socket path";
+        return false;
+      }
 
-  if (!command_line->HasSwitch(switches::kIPCSocketPath)) {
-    LogRequiredOption(switches::kIPCSocketPath);
-    return false;
-  }
-
-  base::FilePath path = command_line->GetSwitchValuePath(
-      switches::kIPCSocketPath);
-  if (path.value().empty() || path.EndsWithSeparator()) {
-    LOG(ERROR) << "Invalid IPC socket path";
-    return false;
+      ipc_socket_path_ = path;
+    } else {
+      LOG(ERROR) << "Unexpected command-line switches found";
+      return false;
+    }
   }
 
   // The daemon has no arguments
@@ -84,8 +58,6 @@
     return false;
   }
 
-  ipc_socket_path_ = path;
-
   initialized_ = true;
   return true;
 }
diff --git a/service/settings.h b/service/settings.h
index f600465..900408c 100644
--- a/service/settings.h
+++ b/service/settings.h
@@ -31,23 +31,17 @@
   // Constant for the "--help" command-line switches.
   static const char kHelp[];
 
-  // Initializes Settings from the command-line arguments and switches for the
-  // current process. Returns false if initialization fails, for example if an
-  // incorrect command-line option has been given.
-  static bool Initialize();
-
-  // Non-mutable getter for the global Settings object. Use this getter for
-  // accessing settings in a read-only fashion (which should be the case for
-  // most of the code that wants to use this class).
-  static const Settings& Get();
-
-  // DO NOT call these directly. Instead, interact with the global instance
-  // using the static Initialize and Get methods.
   Settings();
   ~Settings();
 
   // TODO(armansito): Write an instance method for storing things into a file.
 
+  // Initializes the Settings object. This reads the command-line options for
+  // the current process (which must have been initialized using
+  // base::CommandLine) and sets up the initial global settings. Returns false
+  // if there is an error, e.g. if the parameters/switches are malformed.
+  bool Init();
+
   // Path to the unix domain socket for Bluetooth IPC. On Android, this needs to
   // match the init provided socket domain prefix. Outside Android, this will be
   // the path for the traditional Unix domain socket that the daemon will
@@ -57,9 +51,6 @@
   }
 
  private:
-  // Instance helper for the static Initialize() method.
-  bool Init();
-
   bool initialized_;
   base::FilePath ipc_socket_path_;
 
diff --git a/service/switches.h b/service/switches.h
index 4dd9f1b..424f266 100644
--- a/service/switches.h
+++ b/service/switches.h
@@ -31,7 +31,7 @@
     "\n"
     "Usage:\n"
     "\t--help,-h\tShow this help message\n"
-    "\t--ipc-socket\tSocket path used for IPC";
+    "\t--ipc-socket\tSocket path used for domain socket based IPC";
 
 }  // namespace switches
 }  // namespace bluetooth
diff --git a/service/test/settings_unittest.cpp b/service/test/settings_unittest.cpp
index 4c8a056..fa47c37 100644
--- a/service/test/settings_unittest.cpp
+++ b/service/test/settings_unittest.cpp
@@ -35,32 +35,50 @@
     base::CommandLine::Reset();
   }
 
- private:
-  base::AtExitManager exit_manager;
+ protected:
+  base::AtExitManager exit_manager_;
+  Settings settings_;
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(SettingsTest);
 };
 
 TEST_F(SettingsTest, EmptyCommandLine) {
   const base::CommandLine::CharType* argv[] = { "program" };
   base::CommandLine::Init(arraysize(argv), argv);
-  EXPECT_FALSE(Settings::Initialize());
+  EXPECT_TRUE(settings_.Init());
 }
 
-TEST_F(SettingsTest, UnexpectedSwitches) {
+TEST_F(SettingsTest, UnexpectedSwitches1) {
   const base::CommandLine::CharType* argv[] = {
     "program", "--ipc-socket-path=foobar", "--foobarbaz"
   };
   base::CommandLine::Init(arraysize(argv), argv);
-  EXPECT_FALSE(Settings::Initialize());
+  EXPECT_FALSE(settings_.Init());
 }
 
-TEST_F(SettingsTest, UnexpectedArguments) {
+TEST_F(SettingsTest, UnexpectedSwitches2) {
+  const base::CommandLine::CharType* argv[] = {
+    "program", "--foobarbaz"
+  };
+  base::CommandLine::Init(arraysize(argv), argv);
+  EXPECT_FALSE(settings_.Init());
+}
+
+TEST_F(SettingsTest, UnexpectedArguments1) {
+  const base::CommandLine::CharType* argv[] = {
+    "program", "foobarbaz"
+  };
+  base::CommandLine::Init(arraysize(argv), argv);
+  EXPECT_FALSE(settings_.Init());
+}
+
+TEST_F(SettingsTest, UnexpectedArguments2) {
   const base::CommandLine::CharType* argv[] = {
     "program", "--ipc-socket-path=foobar", "foobarbaz"
   };
   base::CommandLine::Init(arraysize(argv), argv);
-  EXPECT_FALSE(Settings::Initialize());
+  EXPECT_FALSE(settings_.Init());
 }
 
 TEST_F(SettingsTest, GoodArguments) {
@@ -68,7 +86,7 @@
     "program", "--ipc-socket=foobar"
   };
   base::CommandLine::Init(arraysize(argv), argv);
-  EXPECT_TRUE(Settings::Initialize());
+  EXPECT_TRUE(settings_.Init());
 }
 
 }  // namespace