Merge "Restore LOG_NDEBUG condition on verbose logging."
diff --git a/service/Android.mk b/service/Android.mk
index de963a8..f497328 100644
--- a/service/Android.mk
+++ b/service/Android.mk
@@ -32,7 +32,9 @@
 	uuid.cpp
 
 btserviceBinderSrc := \
-	ipc/binder/IBluetooth.cpp
+	ipc/binder/IBluetooth.cpp \
+	ipc/binder/bluetooth_binder_server.cpp \
+	ipc/binder/ipc_handler_binder.cpp
 
 btserviceCommonIncludes := $(LOCAL_PATH)/../
 
@@ -67,6 +69,7 @@
 	test/fake_hal_util.cpp \
 	test/ipc_unix_unittest.cpp \
 	test/settings_unittest.cpp \
+	test/stub_ipc_handler_binder.cpp \
 	test/uuid_unittest.cpp
 LOCAL_C_INCLUDES += $(btserviceCommonIncludes)
 LOCAL_CFLAGS += -std=c++11
@@ -77,3 +80,18 @@
 LOCAL_STATIC_LIBRARIES += libgmock_host liblog
 include $(BUILD_HOST_NATIVE_TEST)
 endif
+
+# Native system service CLI for target
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+	$(btserviceBinderSrc) \
+	client/main.cpp
+LOCAL_C_INCLUDES += $(btserviceCommonIncludes)
+LOCAL_CFLAGS += -std=c++11
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := bluetooth-cli
+LOCAL_SHARED_LIBRARIES += \
+	libbinder \
+	libchrome \
+	libutils
+include $(BUILD_EXECUTABLE)
diff --git a/service/client/main.cpp b/service/client/main.cpp
new file mode 100644
index 0000000..c2b30b9
--- /dev/null
+++ b/service/client/main.cpp
@@ -0,0 +1,40 @@
+//
+//  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 <base/logging.h>
+
+#include "service/ipc/binder/IBluetooth.h"
+
+using android::sp;
+
+using ipc::binder::IBluetooth;
+
+// TODO(armansito): Build a REPL into this client so that we make Binder calls
+// based on user input. For now this just tests the IsEnabled() method and
+// exits.
+
+int main() {
+  sp<IBluetooth> bt_iface = IBluetooth::getClientInterface();
+  if (!bt_iface.get()) {
+    LOG(ERROR) << "Failed to obtain handle on IBluetooth";
+    return EXIT_FAILURE;
+  }
+
+  bool enabled = bt_iface->IsEnabled();
+  LOG(INFO) << "IsEnabled(): " << enabled;
+
+  return EXIT_SUCCESS;
+}
diff --git a/service/daemon.cpp b/service/daemon.cpp
index 400bb18..3d0e847 100644
--- a/service/daemon.cpp
+++ b/service/daemon.cpp
@@ -66,11 +66,15 @@
 
     ipc_manager_.reset(new ipc::IPCManager(core_stack_.get()));
 
-    // If an IPC socket path was given, initialize IPC with it.
-    if ((!settings_->create_ipc_socket_path().empty() ||
-         !settings_->android_ipc_socket_suffix().empty()) &&
-        !ipc_manager_->Start(ipc::IPCManager::TYPE_UNIX, nullptr)) {
-      LOG(ERROR) << "Failed to set up UNIX domain-socket IPCManager";
+    // If an IPC socket path was given, initialize IPC with it. Otherwise
+    // initialize Binder IPC.
+    if (settings_->UseSocketIPC()) {
+      if (!ipc_manager_->Start(ipc::IPCManager::TYPE_UNIX, nullptr)) {
+        LOG(ERROR) << "Failed to set up UNIX domain-socket IPCManager";
+        return false;
+      }
+    } else if (!ipc_manager_->Start(ipc::IPCManager::TYPE_BINDER, nullptr)) {
+      LOG(ERROR) << "Failed to set up Binder IPCManager";
       return false;
     }
 
diff --git a/service/gatt_server.cpp b/service/gatt_server.cpp
index 40db111..54a2618 100644
--- a/service/gatt_server.cpp
+++ b/service/gatt_server.cpp
@@ -567,10 +567,12 @@
   return true;
 }
 
-bool Server::SetAdvertisement(const std::vector<Uuid> &ids,
-                              const std::vector<uint8_t> &service_data,
+bool Server::SetAdvertisement(const std::vector<Uuid>& ids,
+                              const std::vector<uint8_t>& service_data,
+                              const std::vector<uint8_t>& manufacturer_data,
                               bool transmit_name) {
   std::vector<uint8_t> id_data;
+  auto mutable_manufacturer_data = manufacturer_data;
   auto mutable_service_data = service_data;
 
   for (const Uuid &id : ids) {
@@ -587,7 +589,8 @@
       false,                       /* no txpower */
       2, 2,                        /* interval */
       0,                           /* appearance */
-      0, nullptr,                  /* no mfg data */
+      mutable_manufacturer_data.size(),
+      reinterpret_cast<char *>(mutable_manufacturer_data.data()),
       mutable_service_data.size(),
       reinterpret_cast<char *>(mutable_service_data.data()), id_data.size(),
       reinterpret_cast<char *>(id_data.data()));
@@ -598,10 +601,12 @@
   return true;
 }
 
-bool Server::SetScanResponse(const std::vector<Uuid> &ids,
-                            const std::vector<uint8_t> &service_data,
-                            bool transmit_name) {
+bool Server::SetScanResponse(const std::vector<Uuid>& ids,
+                             const std::vector<uint8_t>& service_data,
+                             const std::vector<uint8_t>& manufacturer_data,
+                             bool transmit_name) {
   std::vector<uint8_t> id_data;
+  auto mutable_manufacturer_data = manufacturer_data;
   auto mutable_service_data = service_data;
 
   for (const Uuid &id : ids) {
@@ -618,7 +623,8 @@
       false,                      /* no txpower */
       2, 2,                       /* interval */
       0,                          /* appearance */
-      0, nullptr,                 /* no mfg data */
+      mutable_manufacturer_data.size(),
+      reinterpret_cast<char *>(mutable_manufacturer_data.data()),
       mutable_service_data.size(),
       reinterpret_cast<char *>(mutable_service_data.data()), id_data.size(),
       reinterpret_cast<char *>(id_data.data()));
@@ -663,8 +669,8 @@
   // Control attributes have fixed permissions/properties.
   btstat = internal_->AddCharacteristic(
       control_id,
-      kPermissionRead | kPermissionWrite,
-      kPropertyRead | kPropertyWrite);
+      kPropertyRead | kPropertyWrite,
+      kPermissionRead | kPermissionWrite);
   internal_->api_synchronize.wait(lock);
 
   // Finally, associate the control attribute with the value attribute.
diff --git a/service/gatt_server.h b/service/gatt_server.h
index c61399a..778b136 100644
--- a/service/gatt_server.h
+++ b/service/gatt_server.h
@@ -71,13 +71,15 @@
   bool Initialize(const Uuid &service_id, int *gatt_pipe, CoreStack *bt);
 
   // Control the content of service advertisement.
-  bool SetAdvertisement(const std::vector<Uuid> &ids,
-                        const std::vector<uint8_t> &service_data,
+  bool SetAdvertisement(const std::vector<Uuid>& ids,
+                        const std::vector<uint8_t>& service_data,
+                        const std::vector<uint8_t>& manufacturer_data,
                         bool transmit_name);
 
   // Control the content of service scan response.
-  bool SetScanResponse(const std::vector<Uuid> &ids,
-                       const std::vector<uint8_t> &service_data,
+  bool SetScanResponse(const std::vector<Uuid>& ids,
+                       const std::vector<uint8_t>& service_data,
+                       const std::vector<uint8_t>& manufacturer_data,
                        bool transmit_name);
 
   // Add an ordinary characteristic for reading and/or writing.
diff --git a/service/ipc/binder/bluetooth_binder_server.cpp b/service/ipc/binder/bluetooth_binder_server.cpp
new file mode 100644
index 0000000..15ae741
--- /dev/null
+++ b/service/ipc/binder/bluetooth_binder_server.cpp
@@ -0,0 +1,58 @@
+//
+//  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/binder/bluetooth_binder_server.h"
+
+#include <base/logging.h>
+
+namespace ipc {
+
+BluetoothBinderServer::BluetoothBinderServer(bluetooth::CoreStack* core_stack)
+    : core_stack_(core_stack) {
+  CHECK(core_stack_);
+}
+
+BluetoothBinderServer::~BluetoothBinderServer() {
+}
+
+// binder::BnBluetooth overrides:
+bool BluetoothBinderServer::IsEnabled() {
+  // TODO(armansito): Implement.
+  VLOG(2) << __func__;
+  return false;
+}
+
+int BluetoothBinderServer::GetState() {
+  // TODO(armansito): Implement.
+  return -1;
+}
+
+bool BluetoothBinderServer::Enable() {
+  // TODO(armansito): Implement.
+  return false;
+}
+
+bool BluetoothBinderServer::EnableNoAutoConnect() {
+  // TODO(armansito): Implement.
+  return false;
+}
+
+bool BluetoothBinderServer::Disable() {
+  // TODO(armansito): Implement.
+  return false;
+}
+
+}  // namespace ipc
diff --git a/service/ipc/binder/bluetooth_binder_server.h b/service/ipc/binder/bluetooth_binder_server.h
new file mode 100644
index 0000000..441aedd
--- /dev/null
+++ b/service/ipc/binder/bluetooth_binder_server.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 "service/ipc/binder/IBluetooth.h"
+
+namespace bluetooth {
+class CoreStack;
+}  // namespace bluetooth
+
+namespace ipc {
+
+// Implements the server side of the IBluetooth Binder interface.
+class BluetoothBinderServer : public binder::BnBluetooth {
+ public:
+  explicit BluetoothBinderServer(bluetooth::CoreStack* core_stack);
+  ~BluetoothBinderServer() override;
+
+  // binder::BnBluetooth overrides:
+  bool IsEnabled() override;
+  int GetState() override;
+  bool Enable() override;
+  bool EnableNoAutoConnect() override;
+  bool Disable() override;
+
+ private:
+  // Weak handle on the CoreStack.
+  bluetooth::CoreStack* core_stack_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothBinderServer);
+};
+
+}  // namespace ipc
diff --git a/service/ipc/binder/ipc_handler_binder.cpp b/service/ipc/binder/ipc_handler_binder.cpp
new file mode 100644
index 0000000..d15be08
--- /dev/null
+++ b/service/ipc/binder/ipc_handler_binder.cpp
@@ -0,0 +1,82 @@
+//
+//  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/binder/ipc_handler_binder.h"
+
+#include <base/bind.h>
+#include <base/logging.h>
+#include <base/message_loop/message_loop.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include "service/ipc/binder/bluetooth_binder_server.h"
+
+using android::defaultServiceManager;
+using android::sp;
+using android::status_t;
+using android::String16;
+
+namespace ipc {
+
+IPCHandlerBinder::IPCHandlerBinder(
+    bluetooth::CoreStack* core_stack,
+    IPCManager::Delegate* delegate)
+    : IPCHandler(core_stack, delegate) {
+}
+
+IPCHandlerBinder::~IPCHandlerBinder() {
+}
+
+bool IPCHandlerBinder::Run() {
+  CHECK(core_stack());
+
+  // Register the IBluetooth service with the Android ServiceManager.
+  android::sp<BluetoothBinderServer> bt_server =
+      new BluetoothBinderServer(core_stack());
+  status_t status = defaultServiceManager()->addService(
+      String16(binder::IBluetooth::kBluetoothServiceName),
+      bt_server);
+  if (status != android::NO_ERROR) {
+    LOG(ERROR) << "Failed to register Bluetooth service with ServiceManager";
+    return false;
+  }
+
+  // Notify the delegate. We do this in the message loop to avoid reentrancy.
+  if (delegate()) {
+    base::MessageLoop::current()->task_runner()->PostTask(
+        FROM_HERE,
+        base::Bind(&IPCHandlerBinder::NotifyStarted, this));
+  }
+
+  android::ProcessState::self()->startThreadPool();
+
+  return true;
+}
+
+void IPCHandlerBinder::Stop() {
+  // TODO(armansito): There are several methods in android::IPCThreadState that
+  // are related to shutting down the threadpool, however I haven't been able to
+  // make them shut things down cleanly. Figure out the right way to stop the
+  // Binder IPC here.
+}
+
+void IPCHandlerBinder::NotifyStarted() {
+  if (delegate())
+    delegate()->OnIPCHandlerStarted(IPCManager::TYPE_BINDER);
+}
+
+}  // namespace ipc
diff --git a/service/ipc/binder/ipc_handler_binder.h b/service/ipc/binder/ipc_handler_binder.h
new file mode 100644
index 0000000..f545802
--- /dev/null
+++ b/service/ipc/binder/ipc_handler_binder.h
@@ -0,0 +1,46 @@
+//
+//  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 "service/ipc/ipc_handler.h"
+#include "service/ipc/ipc_manager.h"
+
+namespace ipc {
+
+// Implements a Binder based IPCHandler.
+class IPCHandlerBinder : public IPCHandler {
+ public:
+  IPCHandlerBinder(bluetooth::CoreStack* core_stack,
+                   IPCManager::Delegate* delegate);
+  ~IPCHandlerBinder() override;
+
+  // IPCHandler overrides:
+  bool Run() override;
+  void Stop() override;
+
+ private:
+  IPCHandlerBinder() = default;
+
+  // Notify the delegate that IPC has started.
+  void NotifyStarted();
+
+  DISALLOW_COPY_AND_ASSIGN(IPCHandlerBinder);
+};
+
+}  // namespace ipc
diff --git a/service/ipc/ipc_handler_unix.h b/service/ipc/ipc_handler_unix.h
index 0beb852..53e84c1 100644
--- a/service/ipc/ipc_handler_unix.h
+++ b/service/ipc/ipc_handler_unix.h
@@ -30,10 +30,6 @@
 class SingleThreadTaskRunner;
 }  // namespace base
 
-namespace bluetooth {
-class CoreStack;
-}  // namespace bluetooth
-
 namespace ipc {
 
 // Implements a UNIX domain-socket based IPCHandler
diff --git a/service/ipc/ipc_manager.cpp b/service/ipc/ipc_manager.cpp
index 0ff67d5..ad9ae73 100644
--- a/service/ipc/ipc_manager.cpp
+++ b/service/ipc/ipc_manager.cpp
@@ -16,6 +16,7 @@
 
 #include "service/ipc/ipc_manager.h"
 
+#include "service/ipc/binder/ipc_handler_binder.h"
 #include "service/ipc/ipc_handler_unix.h"
 
 namespace ipc {
@@ -37,14 +38,31 @@
 bool IPCManager::Start(Type type, Delegate* delegate) {
   switch (type) {
   case TYPE_UNIX:
+    if (UnixStarted()) {
+      LOG(ERROR) << "IPCManagerUnix already started.";
+      return false;
+    }
+
     unix_handler_ = new IPCHandlerUnix(core_stack_, delegate);
     if (!unix_handler_->Run()) {
       unix_handler_ = nullptr;
       return false;
     }
     return true;
+
   case TYPE_BINDER:
-    // TODO(armansito): Support Binder
+    if (BinderStarted()) {
+      LOG(ERROR) << "IPCManagerBinder already started.";
+      return false;
+    }
+
+    binder_handler_ = new IPCHandlerBinder(core_stack_, delegate);
+    if (!binder_handler_->Run()) {
+      binder_handler_ = nullptr;
+      return false;
+    }
+    return true;
+
   default:
     LOG(ERROR) << "Unsupported IPC type given: " << type;
   }
diff --git a/service/ipc/unix_ipc_host.cpp b/service/ipc/unix_ipc_host.cpp
index bd1570d..dc2e981 100644
--- a/service/ipc/unix_ipc_host.cpp
+++ b/service/ipc/unix_ipc_host.cpp
@@ -184,6 +184,7 @@
 bool UnixIPCHost::OnSetAdvertisement(const std::string& service_uuid,
                               const std::string& advertise_uuids,
                               const std::string& advertise_data,
+                              const std::string& manufacturer_data,
                               const std::string& transmit_name) {
   LOG_INFO(LOG_TAG, "%s: service:%s uuids:%s data:%s", __func__, service_uuid.c_str(),
            advertise_uuids.c_str(), advertise_data.c_str());
@@ -198,8 +199,15 @@
 
   std::string decoded_data;
   base::Base64Decode(advertise_data, &decoded_data);
-  std::vector<uint8_t> blob_data(decoded_data.begin(), decoded_data.end());
-  gatt_servers_[service_uuid]->SetAdvertisement(ids, blob_data,
+  std::vector<uint8_t> decoded_advertise_data(decoded_data.begin(),
+                                              decoded_data.end());
+
+  base::Base64Decode(manufacturer_data, &decoded_data);
+  std::vector<uint8_t> decoded_manufacturer_data(decoded_data.begin(),
+                                                 decoded_data.end());
+
+  gatt_servers_[service_uuid]->SetAdvertisement(ids, decoded_advertise_data,
+                                                decoded_manufacturer_data,
                                                 TokenBool(transmit_name));
   return true;
 }
@@ -207,6 +215,7 @@
 bool UnixIPCHost::OnSetScanResponse(const std::string& service_uuid,
                              const std::string& scan_response_uuids,
                              const std::string& scan_response_data,
+                             const std::string& manufacturer_data,
                              const std::string& transmit_name) {
   std::vector<std::string> scan_response_uuid_tokens;
   base::SplitString(scan_response_uuids, '.', &scan_response_uuid_tokens);
@@ -218,8 +227,15 @@
 
   std::string decoded_data;
   base::Base64Decode(scan_response_data, &decoded_data);
-  std::vector<uint8_t> blob_data(decoded_data.begin(), decoded_data.end());
-  gatt_servers_[service_uuid]->SetScanResponse(ids, blob_data,
+  std::vector<uint8_t> decoded_advertise_data(decoded_data.begin(),
+                                              decoded_data.end());
+
+  base::Base64Decode(manufacturer_data, &decoded_data);
+  std::vector<uint8_t> decoded_manufacturer_data(decoded_data.begin(),
+                                                 decoded_data.end());
+
+  gatt_servers_[service_uuid]->SetScanResponse(ids, decoded_advertise_data,
+                                               decoded_manufacturer_data,
                                                TokenBool(transmit_name));
   return true;
 }
@@ -273,13 +289,15 @@
         return OnSetCharacteristicValue(tokens[1], tokens[2], tokens[3]);
       break;
     case 5:
-      if (tokens[0] == kSetAdvertisementCommand)
-        return OnSetAdvertisement(tokens[1], tokens[2], tokens[3], tokens[4]);
-      if (tokens[0] == kSetScanResponseCommand)
-        return OnSetScanResponse(tokens[1], tokens[2], tokens[3], tokens[4]);
       if (tokens[0] == kAddCharacteristicCommand)
         return OnAddCharacteristic(tokens[1], tokens[2], tokens[3], tokens[4]);
       break;
+    case 6:
+      if (tokens[0] == kSetAdvertisementCommand)
+        return OnSetAdvertisement(tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]);
+      if (tokens[0] == kSetScanResponseCommand)
+        return OnSetScanResponse(tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]);
+      break;
     default:
       break;
   }
diff --git a/service/ipc/unix_ipc_host.h b/service/ipc/unix_ipc_host.h
index 4bcfad0..3661c20 100644
--- a/service/ipc/unix_ipc_host.h
+++ b/service/ipc/unix_ipc_host.h
@@ -76,12 +76,14 @@
   bool OnSetAdvertisement(const std::string& service_uuid,
                           const std::string& advertise_uuids,
                           const std::string& advertise_data,
+                          const std::string& manufacturer_data,
                           const std::string& transmit_name);
 
   // Applies settings to scan response.
   bool OnSetScanResponse(const std::string& service_uuid,
                          const std::string& advertise_uuids,
                          const std::string& advertise_data,
+                         const std::string& manufacturer_data,
                          const std::string& transmit_name);
 
   // Starts service (advertisement and connections)
diff --git a/service/settings.cpp b/service/settings.cpp
index 66235e7..b7e9048 100644
--- a/service/settings.cpp
+++ b/service/settings.cpp
@@ -23,7 +23,8 @@
 
 namespace bluetooth {
 
-Settings::Settings() : initialized_(false) {
+Settings::Settings()
+    : initialized_(false) {
 }
 
 Settings::~Settings() {
diff --git a/service/settings.h b/service/settings.h
index 4747dba..4c4ea4f 100644
--- a/service/settings.h
+++ b/service/settings.h
@@ -53,6 +53,13 @@
     return create_ipc_socket_path_;
   }
 
+  // Returns true if domain-socket based IPC should be used. If false, then
+  // Binder IPC must be used.
+  inline bool UseSocketIPC() const {
+    return !android_ipc_socket_suffix().empty() ||
+        !create_ipc_socket_path().empty();
+  }
+
  private:
   bool initialized_;
   std::string android_ipc_socket_suffix_;
diff --git a/service/switches.h b/service/switches.h
index 755b4d2..6566638 100644
--- a/service/switches.h
+++ b/service/switches.h
@@ -31,11 +31,11 @@
     "\nBluetooth System Service\n"
     "\n"
     "Usage:\n"
-    "\t--help,-h\tShow this help message\n"
+    "\t--help,-h\t\t\tShow this help message\n"
     "\t--android-ipc-socket-suffix\tSuffix of socket created by Android init. "
     "Mutually exclusive with --create-ipc-socket.\n"
-    "\t--create-ipc-socket\tSocket path created for Unix domain socket based "
-    "IPC. Mutually exclusive with --android-ipc-socket-suffix.";
+    "\t--create-ipc-socket\t\tSocket path created for Unix domain socket based "
+    "IPC. Mutually exclusive with --android-ipc-socket-suffix.\n";
 
 }  // namespace switches
 }  // namespace bluetooth
diff --git a/service/test/stub_ipc_handler_binder.cpp b/service/test/stub_ipc_handler_binder.cpp
new file mode 100644
index 0000000..a9c6e64
--- /dev/null
+++ b/service/test/stub_ipc_handler_binder.cpp
@@ -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.
+//
+
+#include "service/ipc/binder/ipc_handler_binder.h"
+
+// TODO(armansito): This is a crappy workaround to link IPCHandlerBinder into
+// host-native unit tests. We should instead figure out a way to build Binder
+// unit tests for host.
+
+namespace ipc {
+
+IPCHandlerBinder::IPCHandlerBinder(
+    bluetooth::CoreStack* core_stack,
+    IPCManager::Delegate* delegate)
+    : IPCHandler(core_stack, delegate) {
+  // Stub
+}
+
+IPCHandlerBinder::~IPCHandlerBinder() {
+  // Stub
+}
+
+bool IPCHandlerBinder::Run() {
+  // Stub
+  return false;
+}
+
+void IPCHandlerBinder::Stop() {
+  // Stub
+}
+
+void IPCHandlerBinder::NotifyStarted() {
+  // Stub
+}
+
+}  // namespace