gn-build: Add bluetooth-service target

This patch makes the Bluetooth system service (service/) buildable using GN:

1. Added new BUILD.gn file for service/
2. Added conditional compilation for global config paths, with TODOs for
generalizing them later.
3. Added a shim for loading the Bluetooth library that calls hw_get_module on
Android and explicitly calls dlopen on OS_GENERIC.
4. Fixed compile warnings and errors.
5. Did some minor clean up in gatt_server.cpp for better readability.

Bug: 22124644
Change-Id: I3226537a3a5211a6762651a35707638df29956b0
diff --git a/service/main.cpp b/service/main.cpp
index cb536eb..46bff4a 100644
--- a/service/main.cpp
+++ b/service/main.cpp
@@ -13,14 +13,20 @@
 //  See the License for the specific language governing permissions and
 //  limitations under the License.
 //
+
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.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 "core_stack.h"
 #include "host.h"
@@ -29,27 +35,62 @@
 
 namespace {
 
+// TODO(armansito): None of these should be hardcoded here. Instead, pass these
+// via commandline.
 const char kDisableProperty[] = "persist.bluetooth.disable";
 const char kSocketFromInit[] = "bluetooth";
+const char kUnixIpcSocketPath[] = "bluetooth-ipc-socket";
 
 }  // namespace
 
 int main() {
+  // 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)
   char disable_value[PROPERTY_VALUE_MAX];
-  int status = property_get(kDisableProperty, disable_value, nullptr);
+  status = property_get(kDisableProperty, disable_value, nullptr);
   if (status && !strcmp(disable_value, "1")) {
     LOG_INFO(LOG_TAG, "%s", "service disabled");
     return EXIT_SUCCESS;
   }
 
   int server_socket = osi_android_get_control_socket(kSocketFromInit);
-  if (server_socket == -1) {
+  if (server_socket < 0) {
     LOG_ERROR(LOG_TAG, "failed to get socket from init");
     return EXIT_FAILURE;
   }
+#else  // defined(OS_GENERIC)
+  int server_socket = socket(PF_UNIX, SOCK_SEQPACKET, 0);
+  if (server_socket < 0) {
+    LOG_ERROR(LOG_TAG, "failed to open domain socket for IPC");
+    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(kUnixIpcSocketPath);
+
+  struct sockaddr_un address;
+  memset(&address, 0, sizeof(address));
+  address.sun_family = AF_UNIX;
+  strncpy(address.sun_path, kUnixIpcSocketPath, sizeof(address.sun_path) - 1);
+
+  if (bind(server_socket, (struct sockaddr*)&address, sizeof(address)) < 0) {
+    LOG_ERROR(LOG_TAG, "Failed to bind IPC socket to address");
+    return EXIT_FAILURE;
+  }
+
+#endif  // !defined(OS_GENERIC)
 
   status = listen(server_socket, SOMAXCONN);
-  if (status == -1) {
+  if (status < 0) {
     LOG_ERROR(LOG_TAG, "listen failed: %s", strerror(errno));
     return EXIT_FAILURE;
   }
@@ -71,5 +112,6 @@
   }
 
   close(server_socket);
+
   return EXIT_SUCCESS;
 }