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