Add bthost, a simple BLE GATT server.

This is accessible via Unix socket.
It only has a couple of interesting features:

 * Built in support for large blob attributes (>512 octets)
 * Attribute caching (avoid frame-level IO for IPC clients)

Some string utilies are taken from modp_b64 and Chromium base.

Bug: 21076037
Change-Id: I6a29959159de76f8dd68d6bbaabe2100daabb6fa
diff --git a/service/main.cpp b/service/main.cpp
new file mode 100644
index 0000000..a818f74
--- /dev/null
+++ b/service/main.cpp
@@ -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.
+//
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define LOG_TAG "BtHost"
+#include "osi/include/log.h"
+// For system properties
+// TODO(icoolidge): abstraction or non-cutils stub.
+#include <cutils/properties.h>
+// For init socket environment variable decode
+// TODO(icoolidge): abstraction or remove.
+#include <cutils/sockets.h>
+
+#include "core_stack.h"
+#include "host.h"
+
+namespace {
+
+const char kDisableProperty[] = "persist.bluetooth.disable";
+const char kSocketFromInit[] = "bluetooth";
+
+}  // namespace
+
+int main() {
+  char disable_value[PROPERTY_VALUE_MAX];
+  int status = property_get(kDisableProperty, disable_value, nullptr);
+  if (status && !strcmp(disable_value, "1")) {
+    LOG_INFO("service disabled");
+    return EXIT_SUCCESS;
+  }
+
+  int server_socket = android_get_control_socket(kSocketFromInit);
+  if (server_socket == -1) {
+    LOG_ERROR("failed to get socket from init");
+    return EXIT_FAILURE;
+  }
+
+  status = listen(server_socket, SOMAXCONN);
+  if (status == -1) {
+    LOG_ERROR("listen failed: %s", strerror(errno));
+    return EXIT_FAILURE;
+  }
+
+  bluetooth::CoreStack bt;
+  bt.Initialize();
+
+  // TODO(icoolidge): accept simultaneous clients
+  while (true) {
+    int client_socket = accept4(server_socket, 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();
+  }
+
+  close(server_socket);
+  return EXIT_SUCCESS;
+}