Add Binder support to weaved and remove D-Bus interface

Added binder-based IPC to weaved instead of D-Bus. Removed the
old weave commands based on D-Bus and redesigned client library
interface to be more in line with how Binder operates.

BUG: 23782171, 25523591

Change-Id: Ic39a6a2edf2e033e506d233919c9d04e4fab8d01
diff --git a/Android.mk b/Android.mk
index baf3bd5..10d7ba3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -30,7 +30,6 @@
 
 buffetCommonCIncludes := \
 	$(LOCAL_PATH)/.. \
-	$(LOCAL_PATH)/dbus-proxies \
 	external/cros/system_api \
 	external/gtest/include \
 
@@ -38,7 +37,10 @@
 	libapmanager-client \
 	libavahi-common \
 	libavahi-client \
+	libbinder \
+	libbinderwrapper \
 	libbrillo \
+	libbrillo-binder \
 	libbrillo-dbus \
 	libbrillo-http \
 	libbrillo-stream \
@@ -47,6 +49,7 @@
 	libcutils \
 	libdbus \
 	libshill-client \
+	libutils \
 	libweave \
 	libwebserv \
 
@@ -58,10 +61,38 @@
 
 endif
 
-# buffet-common
+# weave-common
+# Code shared between weaved daemon and libweaved client library
 # ========================================================
 include $(CLEAR_VARS)
-LOCAL_MODULE := buffet-common
+LOCAL_MODULE := weave-common
+LOCAL_CPP_EXTENSION := $(buffetCommonCppExtension)
+LOCAL_CFLAGS := $(buffetCommonCFlags)
+LOCAL_CPPFLAGS := $(buffetCommonCppFlags)
+LOCAL_C_INCLUDES := $(buffetCommonCIncludes)
+LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/brillo
+LOCAL_SHARED_LIBRARIES := $(buffetSharedLibraries)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+LOCAL_CLANG := true
+
+LOCAL_SRC_FILES := \
+	brillo/android/weave/IWeaveClient.aidl \
+	brillo/android/weave/IWeaveCommand.aidl \
+	brillo/android/weave/IWeaveService.aidl \
+	brillo/android/weave/IWeaveServiceManager.aidl \
+	brillo/android/weave/IWeaveServiceManagerNotificationListener.aidl \
+	common/binder_constants.cc \
+	common/binder_utils.cc \
+	common/data_conversion.cc \
+
+include $(BUILD_STATIC_LIBRARY)
+
+# weave-daemon-common
+# Code shared between weaved daemon and unit test runner.
+# This is essentially the implementation of weaved in a static library format.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := weave-daemon-common
 LOCAL_CPP_EXTENSION := $(buffetCommonCppExtension)
 LOCAL_CFLAGS := $(buffetCommonCFlags)
 # TODO(avakulenko): Remove -Wno-deprecated-declarations when legacy libweave
@@ -69,17 +100,17 @@
 LOCAL_CPPFLAGS := $(buffetCommonCppFlags) -Wno-deprecated-declarations
 LOCAL_C_INCLUDES := $(buffetCommonCIncludes)
 LOCAL_SHARED_LIBRARIES := $(buffetSharedLibraries)
-LOCAL_STATIC_LIBRARIES :=
+LOCAL_STATIC_LIBRARIES := weave-common
 LOCAL_CLANG := true
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
 
 LOCAL_SRC_FILES := \
+	brillo/weaved_system_properties.cc \
 	buffet/ap_manager_client.cc \
 	buffet/avahi_mdns_client.cc \
+	buffet/binder_command_proxy.cc \
+	buffet/binder_weave_service.cc \
 	buffet/buffet_config.cc \
-	buffet/dbus_command_dispatcher.cc \
-	buffet/dbus_command_proxy.cc \
-	buffet/dbus_conversion.cc \
 	buffet/dbus_constants.cc \
 	buffet/flouride_socket_bluetooth_client.cc \
 	buffet/http_transport_client.cc \
@@ -87,9 +118,6 @@
 	buffet/shill_client.cc \
 	buffet/socket_stream.cc \
 	buffet/webserv_client.cc \
-	buffet/dbus_bindings/dbus-service-config.json \
-	buffet/dbus_bindings/com.android.Weave.Command.dbus-xml \
-	buffet/dbus_bindings/com.android.Weave.Manager.dbus-xml \
 
 ifdef BRILLO
 LOCAL_SRC_FILES += buffet/keystore_encryptor.cc
@@ -99,28 +127,13 @@
 
 include $(BUILD_STATIC_LIBRARY)
 
-# weaved-brillo-api
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := weaved-brillo-api
-LOCAL_CPP_EXTENSION := $(buffetCommonCppExtension)
-LOCAL_CFLAGS := $(buffetCommonCFlags)
-LOCAL_CPPFLAGS := $(buffetCommonCppFlags)
-LOCAL_CLANG := true
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-LOCAL_SRC_FILES := \
-	brillo/weaved_system_properties.cc \
-
-include $(BUILD_STATIC_LIBRARY)
-
 # weaved
+# The main binary of the weave daemon.
 # ========================================================
 include $(CLEAR_VARS)
 LOCAL_MODULE := weaved
 LOCAL_REQUIRED_MODULES := \
 	avahi-daemon \
-	com.android.Weave.conf \
 	libweaved \
 	webservd \
 
@@ -130,8 +143,9 @@
 LOCAL_C_INCLUDES := $(buffetCommonCIncludes)
 LOCAL_INIT_RC := weaved.rc
 LOCAL_SHARED_LIBRARIES := $(buffetSharedLibraries)
-LOCAL_STATIC_LIBRARIES := weaved-brillo-api
-LOCAL_WHOLE_STATIC_LIBRARIES := buffet-common
+LOCAL_STATIC_LIBRARIES := weave-common \
+
+LOCAL_WHOLE_STATIC_LIBRARIES := weave-daemon-common
 LOCAL_CLANG := true
 
 LOCAL_SRC_FILES := \
@@ -139,22 +153,9 @@
 
 include $(BUILD_EXECUTABLE)
 
-# libweaved-internal
-# ========================================================
-# You do not want to depend on this.  Depend on libweaved instead.
-# libweaved abstracts and helps you consume this interface.
-include $(CLEAR_VARS)
-LOCAL_MODULE := libweaved-internal
-LOCAL_DBUS_PROXY_PREFIX := buffet
-
-LOCAL_SRC_FILES := \
-	buffet/dbus_bindings/dbus-service-config.json \
-	buffet/dbus_bindings/com.android.Weave.Command.dbus-xml \
-	buffet/dbus_bindings/com.android.Weave.Manager.dbus-xml \
-
-include $(BUILD_SHARED_LIBRARY)
-
 # libweaved
+# The client library for the weave daemon. You should link to libweaved,
+# if you need to communicate with weaved.
 # ========================================================
 include $(CLEAR_VARS)
 LOCAL_MODULE := libweaved
@@ -163,16 +164,14 @@
 LOCAL_CPPFLAGS := $(buffetCommonCppFlags)
 LOCAL_C_INCLUDES := external/gtest/include
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-LOCAL_SHARED_LIBRARIES := \
-	$(buffetSharedLibraries) \
-	libweaved-internal \
+LOCAL_SHARED_LIBRARIES := $(buffetSharedLibraries)
+LOCAL_STATIC_LIBRARIES := weave-common
 
-LOCAL_STATIC_LIBRARIES :=
 LOCAL_CLANG := true
 
 LOCAL_SRC_FILES := \
 	libweaved/command.cc \
-	libweaved/device.cc \
+	libweaved/service.cc \
 
 include $(BUILD_SHARED_LIBRARY)
 
@@ -192,30 +191,20 @@
 	$(buffetSharedLibraries) \
 
 LOCAL_STATIC_LIBRARIES := \
-	buffet-common \
 	libbrillo-test-helpers \
-	libchrome_dbus_test_helpers \
 	libchrome_test_helpers \
 	libgtest \
 	libgmock \
 	libweave-test \
-	weaved-brillo-api \
+	weave-daemon-common \
+	weave-common \
 
 LOCAL_CLANG := true
 
 LOCAL_SRC_FILES := \
+	buffet/binder_command_proxy_unittest.cc \
 	buffet/buffet_config_unittest.cc \
 	buffet/buffet_testrunner.cc \
-	buffet/dbus_command_proxy_unittest.cc \
-	buffet/dbus_conversion_unittest.cc \
+	common/data_conversion_unittest.cc \
 
 include $(BUILD_NATIVE_TEST)
-
-# DBus config files for /etc/dbus-1
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := com.android.Weave.conf
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/dbus-1
-LOCAL_SRC_FILES := buffet/etc/dbus-1/com.android.Weave.conf
-include $(BUILD_PREBUILT)
diff --git a/brillo/android/weave/IWeaveClient.aidl b/brillo/android/weave/IWeaveClient.aidl
new file mode 100644
index 0000000..7712c9d
--- /dev/null
+++ b/brillo/android/weave/IWeaveClient.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.weave;
+
+import android.weave.IWeaveCommand;
+import android.weave.IWeaveService;
+
+interface IWeaveClient {
+  oneway void onServiceConnected(in IWeaveService service);
+  oneway void onCommand(in String componentName,
+                        in String commandName,
+                        in IWeaveCommand command);
+}
diff --git a/brillo/android/weave/IWeaveCommand.aidl b/brillo/android/weave/IWeaveCommand.aidl
new file mode 100644
index 0000000..b445fb0
--- /dev/null
+++ b/brillo/android/weave/IWeaveCommand.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.weave;
+
+interface IWeaveCommand {
+  String getId();
+  String getName();
+  String getComponent();
+  String getState();
+  String getOrigin();
+  String getParameters();
+  String getProgress();
+  String getResults();
+
+  void setProgress(in String progress);
+  void complete(in String results);
+  void abort(in String errorCode, in String errorMessage);
+  void cancel();
+  void pause();
+  void setError(in String errorCode, in String errorMessage);
+}
diff --git a/brillo/android/weave/IWeaveService.aidl b/brillo/android/weave/IWeaveService.aidl
new file mode 100644
index 0000000..0fcc422
--- /dev/null
+++ b/brillo/android/weave/IWeaveService.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.weave;
+
+interface IWeaveService {
+  void addComponent(in String name, in List<String> traits);
+  void registerCommandHandler(in String component, in String command);
+  void updateState(in String component, in String state);
+}
diff --git a/brillo/android/weave/IWeaveServiceManager.aidl b/brillo/android/weave/IWeaveServiceManager.aidl
new file mode 100644
index 0000000..ff8a4c6
--- /dev/null
+++ b/brillo/android/weave/IWeaveServiceManager.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.weave;
+
+import android.weave.IWeaveClient;
+import android.weave.IWeaveServiceManagerNotificationListener;
+
+interface IWeaveServiceManager {
+  oneway void connect(in IWeaveClient client);
+  oneway void registerNotificationListener(
+      in IWeaveServiceManagerNotificationListener listener);
+
+  String getCloudId();
+  String getDeviceId();
+  String getDeviceName();
+  String getDeviceDescription();
+  String getDeviceLocation();
+  String getOemName();
+  String getModelName();
+  String getModelId();
+  String getPairingSessionId();
+  String getPairingMode();
+  String getPairingCode();
+  String getState();
+  String getTraits();
+  String getComponents();
+}
diff --git a/brillo/android/weave/IWeaveServiceManagerNotificationListener.aidl b/brillo/android/weave/IWeaveServiceManagerNotificationListener.aidl
new file mode 100644
index 0000000..a3b91a3
--- /dev/null
+++ b/brillo/android/weave/IWeaveServiceManagerNotificationListener.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.weave;
+
+oneway interface IWeaveServiceManagerNotificationListener {
+  const int CLOUD_ID = 1;
+  const int DEVICE_ID = 2;
+  const int DEVICE_NAME = 3;
+  const int DEVICE_DESCRIPTION = 4;
+  const int DEVICE_LOCATION = 5;
+  const int OEM_NAME = 6;
+  const int MODEL_NAME = 7;
+  const int MODEL_ID = 8;
+  const int PAIRING_SESSION_ID = 9;
+  const int PAIRING_MODE = 10;
+  const int PAIRING_CODE = 11;
+  const int TRAITS = 12;
+  const int COMPONENTS = 13;
+  const int STATE = 14;
+
+  void notifyServiceManagerChange(in int[] notificationIds);
+}
diff --git a/buffet/binder_command_proxy.cc b/buffet/binder_command_proxy.cc
new file mode 100644
index 0000000..487f6cc
--- /dev/null
+++ b/buffet/binder_command_proxy.cc
@@ -0,0 +1,182 @@
+// Copyright 2016 The Android Open Source Project
+//
+// 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 "buffet/binder_command_proxy.h"
+
+#include <weave/enum_to_string.h>
+
+#include "buffet/weave_error_conversion.h"
+#include "common/binder_utils.h"
+
+using weaved::binder_utils::ParseDictionary;
+using weaved::binder_utils::ToStatus;
+using weaved::binder_utils::ToString;
+using weaved::binder_utils::ToString16;
+
+namespace buffet {
+
+namespace {
+
+const char kErrorDomain[] = "weaved";
+
+android::binder::Status ReportDestroyedError() {
+  return android::binder::Status::fromServiceSpecificError(
+      1, android::String8{"Command has been destroyed"});
+}
+
+}  // anonymous namespace
+
+BinderCommandProxy::BinderCommandProxy(
+    const std::weak_ptr<weave::Command>& command) : command_{command} {}
+
+android::binder::Status BinderCommandProxy::getId(android::String16* id) {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  *id = ToString16(command->GetID());
+  return android::binder::Status::ok();
+}
+
+android::binder::Status BinderCommandProxy::getName(android::String16* name) {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  *name = ToString16(command->GetName());
+  return android::binder::Status::ok();
+}
+
+android::binder::Status BinderCommandProxy::getComponent(
+    android::String16* component) {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  *component = ToString16(command->GetComponent());
+  return android::binder::Status::ok();
+}
+
+android::binder::Status BinderCommandProxy::getState(android::String16* state) {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  *state = ToString16(EnumToString(command->GetState()));
+  return android::binder::Status::ok();
+}
+
+android::binder::Status BinderCommandProxy::getOrigin(
+    android::String16* origin) {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  *origin = ToString16(EnumToString(command->GetOrigin()));
+  return android::binder::Status::ok();
+}
+
+android::binder::Status BinderCommandProxy::getParameters(
+    android::String16* parameters) {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  *parameters = ToString16(command->GetParameters());
+  return android::binder::Status::ok();
+}
+
+android::binder::Status BinderCommandProxy::getProgress(
+    android::String16* progress) {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  *progress = ToString16(command->GetProgress());
+  return android::binder::Status::ok();
+}
+
+android::binder::Status BinderCommandProxy::getResults(
+    android::String16* results) {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  *results = ToString16(command->GetResults());
+  return android::binder::Status::ok();
+}
+
+android::binder::Status BinderCommandProxy::setProgress(
+    const android::String16& progress) {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  std::unique_ptr<base::DictionaryValue> dict;
+  auto status = ParseDictionary(progress, &dict);
+  if (status.isOk()) {
+    weave::ErrorPtr error;
+    status = ToStatus(command->SetProgress(*dict, &error), &error);
+  }
+  return status;
+}
+
+android::binder::Status BinderCommandProxy::complete(
+    const android::String16& results) {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  std::unique_ptr<base::DictionaryValue> dict;
+  auto status = ParseDictionary(results, &dict);
+  if (status.isOk()) {
+    weave::ErrorPtr error;
+    status = ToStatus(command->Complete(*dict, &error), &error);
+  }
+  return status;
+}
+
+android::binder::Status BinderCommandProxy::abort(
+    const android::String16& errorCode,
+    const android::String16& errorMessage) {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  weave::ErrorPtr command_error;
+  weave::Error::AddTo(&command_error, FROM_HERE, kErrorDomain,
+                      ToString(errorCode), ToString(errorMessage));
+  weave::ErrorPtr error;
+  return ToStatus(command->Abort(command_error.get(), &error), &error);
+}
+
+android::binder::Status BinderCommandProxy::cancel() {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  weave::ErrorPtr error;
+  return ToStatus(command->Cancel(&error), &error);
+}
+
+android::binder::Status BinderCommandProxy::pause() {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  weave::ErrorPtr error;
+  return ToStatus(command->Pause(&error), &error);
+}
+
+android::binder::Status BinderCommandProxy::setError(
+    const android::String16& errorCode,
+    const android::String16& errorMessage) {
+  auto command = command_.lock();
+  if (!command)
+    return ReportDestroyedError();
+  weave::ErrorPtr command_error;
+  weave::Error::AddTo(&command_error, FROM_HERE, kErrorDomain,
+                      ToString(errorCode), ToString(errorMessage));
+  weave::ErrorPtr error;
+  return ToStatus(command->SetError(command_error.get(), &error), &error);
+}
+
+}  // namespace buffet
diff --git a/buffet/binder_command_proxy.h b/buffet/binder_command_proxy.h
new file mode 100644
index 0000000..4c05b89
--- /dev/null
+++ b/buffet/binder_command_proxy.h
@@ -0,0 +1,62 @@
+// Copyright 2016 The Android Open Source Project
+//
+// 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.
+
+#ifndef BUFFET_BINDER_COMMAND_PROXY_H_
+#define BUFFET_BINDER_COMMAND_PROXY_H_
+
+#include <string>
+
+#include <base/macros.h>
+#include <weave/command.h>
+
+#include "android/weave/BnWeaveCommand.h"
+
+namespace buffet {
+
+// Implementation of android::weave::IWeaveCommand binder object.
+// This class simply redirects binder calls to the underlying weave::Command
+// object (and performs necessary parameter/result type conversions).
+class BinderCommandProxy : public android::weave::BnWeaveCommand {
+ public:
+  explicit BinderCommandProxy(const std::weak_ptr<weave::Command>& command);
+  ~BinderCommandProxy() override = default;
+
+  android::binder::Status getId(android::String16* id) override;
+  android::binder::Status getName(android::String16* name) override;
+  android::binder::Status getComponent(android::String16* component) override;
+  android::binder::Status getState(android::String16* state) override;
+  android::binder::Status getOrigin(android::String16* origin) override;
+  android::binder::Status getParameters(android::String16* parameters) override;
+  android::binder::Status getProgress(android::String16* progress) override;
+  android::binder::Status getResults(android::String16* results) override;
+  android::binder::Status setProgress(
+      const android::String16& progress) override;
+  android::binder::Status complete(const android::String16& results) override;
+  android::binder::Status abort(const android::String16& errorCode,
+                                const android::String16& errorMessage) override;
+  android::binder::Status cancel() override;
+  android::binder::Status pause() override;
+  android::binder::Status setError(
+      const android::String16& errorCode,
+      const android::String16& errorMessage) override;
+
+ private:
+  std::weak_ptr<weave::Command> command_;
+
+  DISALLOW_COPY_AND_ASSIGN(BinderCommandProxy);
+};
+
+}  // namespace buffet
+
+#endif  // BUFFET_BINDER_COMMAND_PROXY_H_
diff --git a/buffet/binder_command_proxy_unittest.cc b/buffet/binder_command_proxy_unittest.cc
new file mode 100644
index 0000000..0905440
--- /dev/null
+++ b/buffet/binder_command_proxy_unittest.cc
@@ -0,0 +1,163 @@
+// Copyright 2016 The Android Open Source Project
+//
+// 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 "buffet/binder_command_proxy.h"
+
+#include <memory>
+
+#include <gtest/gtest.h>
+#include <weave/command.h>
+#include <weave/enum_to_string.h>
+#include <weave/test/mock_command.h>
+#include <weave/test/unittest_utils.h>
+
+#include "common/binder_utils.h"
+
+using weaved::binder_utils::ToString;
+using weaved::binder_utils::ToString16;
+
+namespace buffet {
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::ReturnRef;
+using ::testing::ReturnRefOfCopy;
+using ::testing::StrictMock;
+
+using weave::test::CreateDictionaryValue;
+using weave::test::IsEqualValue;
+
+namespace {
+
+const char kTestCommandId[] = "cmd_1";
+
+MATCHER_P(EqualToJson, json, "") {
+  auto json_value = CreateDictionaryValue(json);
+  return IsEqualValue(*json_value, arg);
+}
+
+MATCHER_P2(ExpectError, code, message, "") {
+  return arg->GetCode() == code && arg->GetMessage() == message;
+}
+
+}  // namespace
+
+class BinderCommandProxyTest : public ::testing::Test {
+ public:
+  void SetUp() override {
+    command_ = std::make_shared<StrictMock<weave::test::MockCommand>>();
+
+    expected_result_dict_.SetInteger("height", 53);
+    expected_result_dict_.SetString("_jumpType", "_withKick");
+    EXPECT_CALL(*command_, GetID())
+        .WillRepeatedly(ReturnRefOfCopy<std::string>(kTestCommandId));
+    EXPECT_CALL(*command_, GetName())
+        .WillRepeatedly(ReturnRefOfCopy<std::string>("robot.jump"));
+    EXPECT_CALL(*command_, GetComponent())
+        .WillRepeatedly(ReturnRefOfCopy<std::string>("myComponent"));
+    EXPECT_CALL(*command_, GetState())
+        .WillRepeatedly(Return(weave::Command::State::kQueued));
+    EXPECT_CALL(*command_, GetOrigin())
+        .WillRepeatedly(Return(weave::Command::Origin::kLocal));
+    EXPECT_CALL(*command_, GetParameters())
+        .WillRepeatedly(ReturnRef(expected_result_dict_));
+    EXPECT_CALL(*command_, GetProgress())
+        .WillRepeatedly(ReturnRef(empty_dict_));
+    EXPECT_CALL(*command_, GetResults())
+        .WillRepeatedly(ReturnRef(empty_dict_));
+
+    proxy_.reset(
+        new BinderCommandProxy{std::weak_ptr<weave::Command>{command_}});
+  }
+
+  BinderCommandProxy* GetCommandProxy() const { return proxy_.get(); }
+
+  weave::Command::State GetCommandState() const {
+    weave::Command::State state;
+    android::String16 state_string;
+    EXPECT_TRUE(GetCommandProxy()->getState(&state_string).isOk());
+    EXPECT_TRUE(StringToEnum(ToString(state_string), &state));
+    return state;
+  }
+
+  weave::Command::Origin GetCommandOrigin() const {
+    weave::Command::Origin origin;
+    android::String16 origin_string;
+    EXPECT_TRUE(GetCommandProxy()->getOrigin(&origin_string).isOk());
+    EXPECT_TRUE(StringToEnum(ToString(origin_string), &origin));
+    return origin;
+  }
+
+  base::DictionaryValue empty_dict_;
+  base::DictionaryValue expected_result_dict_;
+
+  std::shared_ptr<StrictMock<weave::test::MockCommand>> command_;
+  std::unique_ptr<BinderCommandProxy> proxy_;
+};
+
+TEST_F(BinderCommandProxyTest, Init) {
+  android::String16 result;
+  EXPECT_EQ(weave::Command::State::kQueued, GetCommandState());
+  EXPECT_EQ(weave::Command::Origin::kLocal, GetCommandOrigin());
+  EXPECT_TRUE(GetCommandProxy()->getParameters(&result).isOk());
+  EXPECT_EQ(R"({"_jumpType":"_withKick","height":53})", ToString(result));
+  EXPECT_TRUE(GetCommandProxy()->getProgress(&result).isOk());
+  EXPECT_EQ("{}", ToString(result));
+  EXPECT_TRUE(GetCommandProxy()->getResults(&result).isOk());
+  EXPECT_EQ("{}", ToString(result));
+  EXPECT_TRUE(GetCommandProxy()->getName(&result).isOk());
+  EXPECT_EQ("robot.jump", ToString(result));
+  EXPECT_TRUE(GetCommandProxy()->getComponent(&result).isOk());
+  EXPECT_EQ("myComponent", ToString(result));
+  EXPECT_TRUE(GetCommandProxy()->getId(&result).isOk());
+  EXPECT_EQ(kTestCommandId, ToString(result));
+}
+
+TEST_F(BinderCommandProxyTest, SetProgress) {
+  EXPECT_CALL(*command_, SetProgress(EqualToJson("{'progress': 10}"), _))
+      .WillOnce(Return(true));
+  EXPECT_TRUE(
+      GetCommandProxy()->setProgress(ToString16(R"({"progress": 10})")).isOk());
+}
+
+TEST_F(BinderCommandProxyTest, Complete) {
+  EXPECT_CALL(
+      *command_,
+      Complete(
+          EqualToJson("{'foo': 42, 'bar': 'foobar', 'resultList': [1, 2, 3]}"),
+          _))
+      .WillOnce(Return(true));
+  const android::String16 result{
+      R"({"foo": 42, "bar": "foobar", "resultList": [1, 2, 3]})"};
+  EXPECT_TRUE(GetCommandProxy()->complete(result).isOk());
+}
+
+TEST_F(BinderCommandProxyTest, Abort) {
+  EXPECT_CALL(*command_, Abort(ExpectError("foo", "bar"), _))
+      .WillOnce(Return(true));
+  EXPECT_TRUE(
+      GetCommandProxy()->abort(ToString16("foo"), ToString16("bar")).isOk());
+}
+
+TEST_F(BinderCommandProxyTest, Cancel) {
+  EXPECT_CALL(*command_, Cancel(_)).WillOnce(Return(true));
+  EXPECT_TRUE(GetCommandProxy()->cancel().isOk());
+}
+
+TEST_F(BinderCommandProxyTest, Pause) {
+  EXPECT_CALL(*command_, Pause(_)).WillOnce(Return(true));
+  EXPECT_TRUE(GetCommandProxy()->pause().isOk());
+}
+
+}  // namespace buffet
diff --git a/buffet/binder_weave_service.cc b/buffet/binder_weave_service.cc
new file mode 100644
index 0000000..adbad11
--- /dev/null
+++ b/buffet/binder_weave_service.cc
@@ -0,0 +1,90 @@
+// Copyright 2016 The Android Open Source Project
+//
+// 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 "buffet/binder_weave_service.h"
+
+#include <algorithm>
+
+#include <base/bind.h>
+#include <weave/command.h>
+#include <weave/device.h>
+
+#include "buffet/binder_command_proxy.h"
+#include "common/binder_utils.h"
+
+using weaved::binder_utils::ToStatus;
+using weaved::binder_utils::ToString;
+using weaved::binder_utils::ToString16;
+
+namespace buffet {
+
+BinderWeaveService::BinderWeaveService(
+    weave::Device* device,
+    android::sp<android::weave::IWeaveClient> client)
+    : device_{device}, client_{client} {}
+
+BinderWeaveService::~BinderWeaveService() {
+  // TODO(avakulenko): Make it possible to remove components from the tree in
+  // libweave and enable the following code.
+  // for (const std::string& component : components_)
+  //   device_->RemoveComponent(component, nullptr);
+}
+
+android::binder::Status BinderWeaveService::addComponent(
+    const android::String16& name,
+    const std::vector<android::String16>& traits) {
+  std::string component_name = ToString(name);
+  weave::ErrorPtr error;
+  std::vector<std::string> supported_traits;
+  std::transform(traits.begin(), traits.end(),
+                 std::back_inserter(supported_traits), ToString);
+  if (!device_->AddComponent(component_name, supported_traits, &error))
+    return ToStatus(false, &error);
+  components_.push_back(component_name);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status BinderWeaveService::registerCommandHandler(
+    const android::String16& component,
+    const android::String16& command) {
+  std::string component_name = ToString(component);
+  std::string command_name = ToString(command);
+  device_->AddCommandHandler(component_name, command_name,
+                             base::Bind(&BinderWeaveService::OnCommand,
+                                        weak_ptr_factory_.GetWeakPtr(),
+                                        component_name, command_name));
+  return android::binder::Status::ok();
+}
+
+android::binder::Status BinderWeaveService::updateState(
+    const android::String16& component,
+    const android::String16& state) {
+  weave::ErrorPtr error;
+  return ToStatus(device_->SetStatePropertiesFromJson(ToString(component),
+                                                      ToString(state),
+                                                      &error),
+                  &error);
+}
+
+void BinderWeaveService::OnCommand(
+    const std::string& component_name,
+    const std::string& command_name,
+    const std::weak_ptr<weave::Command>& command) {
+  android::sp<android::weave::IWeaveCommand> command_proxy =
+      new BinderCommandProxy{command};
+  client_->onCommand(ToString16(component_name), ToString16(command_name),
+                     command_proxy);
+}
+
+}  // namespace buffet
diff --git a/buffet/binder_weave_service.h b/buffet/binder_weave_service.h
new file mode 100644
index 0000000..c033366
--- /dev/null
+++ b/buffet/binder_weave_service.h
@@ -0,0 +1,72 @@
+// Copyright 2016 The Android Open Source Project
+//
+// 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.
+
+#ifndef BUFFET_BINDER_WEAVE_SERVICE_H_
+#define BUFFET_BINDER_WEAVE_SERVICE_H_
+
+#include <memory>
+#include <vector>
+#include <string>
+
+#include <base/macros.h>
+#include <base/memory/weak_ptr.h>
+
+#include "android/weave/IWeaveClient.h"
+#include "android/weave/BnWeaveService.h"
+
+namespace weave {
+class Command;
+class Device;
+}
+
+namespace buffet {
+
+// An implementation of android::weave::IWeaveService binder.
+// This object is a proxy for weave::Device. A new instance of weave service is
+// created for each connected client. As soon as the client disconnects, this
+// object takes care of cleaning up that client's resources (e.g. it removes
+// the components and their state added by the client).
+class BinderWeaveService final : public android::weave::BnWeaveService {
+ public:
+  BinderWeaveService(weave::Device* device,
+                     android::sp<android::weave::IWeaveClient> client);
+  ~BinderWeaveService() override;
+
+ private:
+  // Binder methods for android::weave::IWeaveService:
+  android::binder::Status addComponent(
+      const android::String16& name,
+      const std::vector<android::String16>& traits) override;
+  android::binder::Status registerCommandHandler(
+      const android::String16& component,
+      const android::String16& command) override;
+  android::binder::Status updateState(
+      const android::String16& component,
+      const android::String16& state) override;
+
+  void OnCommand(const std::string& component_name,
+                 const std::string& command_name,
+                 const std::weak_ptr<weave::Command>& command);
+
+  weave::Device* device_;
+  android::sp<android::weave::IWeaveClient> client_;
+  std::vector<std::string> components_;
+
+  base::WeakPtrFactory<BinderWeaveService> weak_ptr_factory_{this};
+  DISALLOW_COPY_AND_ASSIGN(BinderWeaveService);
+};
+
+}  // namespace buffet
+
+#endif  // BUFFET_BINDER_WEAVE_SERVICE_H_
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp
deleted file mode 100644
index 3eeaa44..0000000
--- a/buffet/buffet.gyp
+++ /dev/null
@@ -1,162 +0,0 @@
-{
-  'target_defaults': {
-    'variables': {
-      'deps': [
-        'libbrillo-<(libbase_ver)',
-        'libchrome-<(libbase_ver)',
-        'system_api',
-      ],
-    },
-    'include_dirs': [
-      '.',
-    ],
-  },
-  'targets': [
-    {
-      'target_name': 'buffet_common',
-      'type': 'static_library',
-      'variables': {
-        'dbus_adaptors_out_dir': 'include/buffet/dbus_bindings',
-        'dbus_service_config': 'dbus_bindings/dbus-service-config.json',
-        'exported_deps': [
-          'libweave-<(libbase_ver)',
-        ],
-        'deps': ['>@(exported_deps)'],
-      },
-      'all_dependent_settings': {
-        'variables': {
-          'deps': [
-            '<@(exported_deps)',
-          ],
-        },
-      },
-      'sources': [
-        'ap_manager_client.cc',
-        'buffet_config.cc',
-        'dbus_bindings/com.android.Weave.Command.dbus-xml',
-        'dbus_bindings/com.android.Weave.Manager.dbus-xml',
-        'dbus_command_dispatcher.cc',
-        'dbus_command_proxy.cc',
-        'dbus_conversion.cc',
-        'dbus_constants.cc',
-        'http_transport_client.cc',
-        'manager.cc',
-        'shill_client.cc',
-        'socket_stream.cc',
-      ],
-      'conditions': [
-        ['USE_wifi_bootstrapping == 1', {
-          'variables': {
-            'exported_deps': [
-              'libpeerd-client',
-              'libwebserv-<(libbase_ver)',
-            ],
-          },
-          'all_dependent_settings': {
-            'defines': [ 'BUFFET_USE_WIFI_BOOTSTRAPPING' ],
-          },
-          'defines': [ 'BUFFET_USE_WIFI_BOOTSTRAPPING' ],
-          'sources': [
-            'webserv_client.cc',
-            'peerd_client.cc',
-          ],
-        }],
-      ],
-      'includes': ['../common-mk/generate-dbus-adaptors.gypi'],
-      'actions': [
-        {
-          'action_name': 'generate-buffet-proxies',
-          'variables': {
-            'dbus_service_config': 'dbus_bindings/dbus-service-config.json',
-            'proxy_output_file': 'include/buffet/dbus-proxies.h'
-          },
-          'sources': [
-            'dbus_bindings/com.android.Weave.Command.dbus-xml',
-            'dbus_bindings/com.android.Weave.Manager.dbus-xml',
-          ],
-          'includes': ['../common-mk/generate-dbus-proxies.gypi'],
-        },
-        {
-          # Import D-Bus bindings from shill.
-          'action_name': 'generate-shill-proxies',
-          'variables': {
-            'dbus_service_config': '../shill/dbus_bindings/dbus-service-config.json',
-            'proxy_output_file': 'include/shill/dbus-proxies.h'
-          },
-          'sources': [
-            '../shill/dbus_bindings/com.chromium.flimflam.Device.xml',
-            '../shill/dbus_bindings/com.chromium.flimflam.Manager.xml',
-            '../shill/dbus_bindings/com.chromium.flimflam.Service.xml',
-          ],
-          'includes': ['../common-mk/generate-dbus-proxies.gypi'],
-        },
-        {
-          # Import D-Bus bindings from apmanager.
-          'action_name': 'generate-apmanager-proxies',
-          'variables': {
-            'dbus_service_config': '../apmanager/dbus_bindings/dbus-service-config.json',
-            'proxy_output_file': 'include/apmanager/dbus-proxies.h'
-          },
-          'sources': [
-            '../apmanager/dbus_bindings/com.chromium.apmanager.Config.xml',
-            '../apmanager/dbus_bindings/com.chromium.apmanager.Device.xml',
-            '../apmanager/dbus_bindings/com.chromium.apmanager.Manager.xml',
-            '../apmanager/dbus_bindings/com.chromium.apmanager.Service.xml',
-          ],
-          'includes': ['../common-mk/generate-dbus-proxies.gypi'],
-        },
-      ],
-    },
-    {
-      'target_name': 'buffet',
-      'type': 'executable',
-      'dependencies': [
-        'buffet_common',
-      ],
-      'sources': [
-        'main.cc',
-      ],
-    },
-    {
-      'target_name': 'buffet_test_daemon',
-      'type': 'executable',
-      'sources': [
-        'test_daemon/main.cc',
-      ],
-    },
-    {
-      'target_name': 'buffet_client',
-      'type': 'executable',
-      'sources': [
-        'buffet_client.cc',
-      ],
-    },
-  ],
-  'conditions': [
-    ['USE_test == 1', {
-      'targets': [
-        {
-          'target_name': 'buffet_testrunner',
-          'type': 'executable',
-          'dependencies': [
-            'buffet_common',
-          ],
-          'variables': {
-            'deps': [
-              'libbrillo-test-<(libbase_ver)',
-              'libchrome-test-<(libbase_ver)',
-              'libweave-test-<(libbase_ver)',
-            ],
-          },
-          'includes': ['../common-mk/common_test.gypi'],
-          'sources': [
-            'buffet_config_unittest.cc',
-            'buffet_testrunner.cc',
-            'dbus_command_proxy_unittest.cc',
-            'dbus_conversion_unittest.cc',
-          ],
-        },
-      ],
-    }],
-  ],
-}
diff --git a/buffet/dbus_bindings/com.android.Weave.Command.dbus-xml b/buffet/dbus_bindings/com.android.Weave.Command.dbus-xml
deleted file mode 100644
index 3602135..0000000
--- a/buffet/dbus_bindings/com.android.Weave.Command.dbus-xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<node xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
-  <interface name="com.android.Weave.Command">
-    <method name="SetProgress">
-      <arg name="progress" type="a{sv}" direction="in"/>
-      <annotation name="org.chromium.DBus.Method.Kind" value="normal"/>
-    </method>
-    <method name="Complete">
-      <tp:docstring>
-        Mark the command as successfully completed and specifies the command
-        results to be returned to the caller.
-      </tp:docstring>
-      <arg name="results" type="a{sv}" direction="in"/>
-      <annotation name="org.chromium.DBus.Method.Kind" value="normal"/>
-    </method>
-    <method name="Abort">
-      <tp:docstring>
-        Mark the command as aborted. This tells the cloud that the device did
-        not successfully complete executing the command. The error information
-        is provided in |code| and |message| parameters.
-      </tp:docstring>
-      <arg name="code" type="s" direction="in"/>
-      <arg name="message" type="s" direction="in"/>
-      <annotation name="org.chromium.DBus.Method.Kind" value="normal"/>
-    </method>
-    <method name="Cancel">
-      <tp:docstring>
-        Mark the command as cancelled. Unlike Abort() this should be used when
-        the device detects a user request to cancel a command.
-      </tp:docstring>
-      <annotation name="org.chromium.DBus.Method.Kind" value="normal"/>
-    </method>
-    <property name="Name" type="s" access="read"/>
-    <property name="Id" type="s" access="read"/>
-    <property name="Component" type="s" access="read"/>
-    <property name="State" type="s" access="read"/>
-    <property name="Parameters" type="a{sv}" access="read"/>
-    <property name="Progress" type="a{sv}" access="read"/>
-    <property name="Results" type="a{sv}" access="read"/>
-    <property name="Origin" type="s" access="read">
-      <tp:docstring>
-        Specifies the origin of the command. This is a string containing
-        "cloud" or "local" indicating the method of delivery of the command.
-      </tp:docstring>
-    </property>
-  </interface>
-</node>
diff --git a/buffet/dbus_bindings/com.android.Weave.Manager.dbus-xml b/buffet/dbus_bindings/com.android.Weave.Manager.dbus-xml
deleted file mode 100644
index ecbb511..0000000
--- a/buffet/dbus_bindings/com.android.Weave.Manager.dbus-xml
+++ /dev/null
@@ -1,133 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<node name="/com/android/Weave/Manager"
-      xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
-  <interface name="com.android.Weave.Manager">
-    <tp:docstring>
-      The Manager is responsible for global state of Buffet.  It exposes
-      interfaces which affect the entire device such as device registration and
-      device state.
-    </tp:docstring>
-    <method name="RegisterDevice">
-      <arg name="ticket_id" type="s" direction="in"/>
-      <arg name="device_id" type="s" direction="out"/>
-      <annotation name="org.chromium.DBus.Method.Kind" value="async"/>
-    </method>
-    <method name="AddComponent">
-      <arg name="name" type="s" direction="in"/>
-      <arg name="traits" type="as" direction="in"/>
-      <annotation name="org.chromium.DBus.Method.Kind" value="async"/>
-    </method>
-    <method name="UpdateState">
-      <arg name="component" type="s" direction="in"/>
-      <arg name="property_set" type="a{sv}" direction="in"/>
-      <annotation name="org.chromium.DBus.Method.Kind" value="async"/>
-    </method>
-    <method name="AddCommand">
-      <arg name="json_command" type="s" direction="in"/>
-      <arg name="id" type="s" direction="out"/>
-      <annotation name="org.chromium.DBus.Method.Kind" value="async"/>
-    </method>
-    <method name="TestMethod">
-      <arg name="message" type="s" direction="in"/>
-      <arg name="echoed_message" type="s" direction="out"/>
-      <annotation name="org.chromium.DBus.Method.Kind" value="simple"/>
-    </method>
-    <property name="Status" type="s" access="read">
-      <tp:docstring>
-        State of Buffet's cloud registration.
-        Possible values include:
-          "unconfigured": Buffet has no credentials, either from an out of box
-                          state, or because device was unregistered.
-
-          "connecting": Buffet is registered and attempting to connect to the
-                        cloud.
-
-          "connected": Buffet is online and connected to the cloud. Note that
-                       only this state requires internet connectivity.
-
-          "invalid_credentials": Buffet has credentials, but they are no longer
-                                 valid.
-      </tp:docstring>
-    </property>
-    <property name="DeviceId" type="s" access="read">
-      <tp:docstring>
-        GCD ID if the device is registered or empty otherwise.
-      </tp:docstring>
-    </property>
-    <property name="Components" type="s" access="read">
-      <tp:docstring>
-        JSON with device component tree.
-      </tp:docstring>
-    </property>
-    <property name="Traits" type="s" access="read">
-      <tp:docstring>
-        JSON with device trait definitions.
-      </tp:docstring>
-    </property>
-    <property name="OemName" type="s" access="read">
-      <tp:docstring>
-        Name of the device maker.
-      </tp:docstring>
-    </property>
-    <property name="ModelName" type="s" access="read">
-      <tp:docstring>
-        Name of the device model.
-      </tp:docstring>
-    </property>
-    <property name="ModelId" type="s" access="read">
-      <tp:docstring>
-        Five character code assigned by the cloud registry of device models.
-      </tp:docstring>
-    </property>
-    <property name="Name" type="s" access="read">
-      <tp:docstring>
-        Human readable name of the device. Must not be empty.
-      </tp:docstring>
-    </property>
-    <property name="Description" type="s" access="read">
-      <tp:docstring>
-        Human readable description of the device.
-      </tp:docstring>
-    </property>
-    <property name="Location" type="s" access="read">
-      <tp:docstring>
-        Location of the device.
-      </tp:docstring>
-    </property>
-    <property name="GCDBootstrapState" type="s" access="read">
-      <tp:docstring>
-        Contains one of the following values describing the state of GCD
-        bootstrapping:
-          “disabled” - GCD registration has been disabled in the config file.
-          “offline” - GCD registration is unknown because the device is offline.
-          “connecting” - GCD registration is unknown because the device is still
-                         connecting to the cloud.
-          “waiting” - Waiting to be configured with GCD credentials.
-          “registering” - Registering the device with the GCD servers.
-          “online” - Device is online and registered with GCD servers.
-
-        Note: more values may be added later to this list.
-
-        Clients that wish to present a single linear bootstrapping flow to users
-        may treat GCD bootstrapping states as a suffix to WiFi bootstrapping
-        states.  If we have no cloud connectivity, we cannot possibly do GCD
-        registration/credential verification.
-      </tp:docstring>
-    </property>
-    <property name="PairingInfo" type="a{sv}" access="read">
-      <tp:docstring>
-        Describes the state of device pairing. While no pairing attempt is in
-        progress, this dictionary will be empty. When a client initiates a
-        pairing transaction via /privet/v3/pairing/start, dictionary will
-        contain the following keys:
-          “sessionId” - ID of the pairing session; generated by device
-          “pairingMode” - Selected type of pairing from /privet/v3/pairing/start
-                          (e.g. “pinCode” or “embeddedCode”)
-          “code” - The pin code or embedded code as appropriate to the
-                   “pairingMode” value.  See design document.
-                   This value will be a string.
-      </tp:docstring>
-    </property>
-  </interface>
-</node>
diff --git a/buffet/dbus_bindings/dbus-service-config.json b/buffet/dbus_bindings/dbus-service-config.json
deleted file mode 100644
index c5fa946..0000000
--- a/buffet/dbus_bindings/dbus-service-config.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "service_name": "com.android.Weave",
-  "object_manager": {
-    "name": "com.android.Weave.ObjectManager",
-    "object_path": "/com/android/Weave"
-  }
-}
diff --git a/buffet/dbus_command_dispatcher.cc b/buffet/dbus_command_dispatcher.cc
deleted file mode 100644
index d23d071..0000000
--- a/buffet/dbus_command_dispatcher.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2015 The Android Open Source Project
-//
-// 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 "buffet/dbus_command_dispatcher.h"
-
-#include <brillo/dbus/exported_object_manager.h>
-#include <weave/command.h>
-#include <weave/device.h>
-
-#include "buffet/dbus_command_proxy.h"
-#include "buffet/dbus_constants.h"
-
-using brillo::dbus_utils::AsyncEventSequencer;
-using brillo::dbus_utils::ExportedObjectManager;
-
-namespace buffet {
-
-DBusCommandDispacher::DBusCommandDispacher(
-    const base::WeakPtr<ExportedObjectManager>& object_manager,
-    weave::Device* device)
-    : object_manager_{object_manager} {
-  device->AddCommandHandler("", "",
-                            base::Bind(&DBusCommandDispacher::OnCommandAdded,
-                                       weak_ptr_factory_.GetWeakPtr()));
-}
-
-void DBusCommandDispacher::OnCommandAdded(
-    const std::weak_ptr<weave::Command>& cmd) {
-  auto command = cmd.lock();
-  if (!object_manager_ || !command)
-    return;
-  std::unique_ptr<DBusCommandProxy> proxy{new DBusCommandProxy(
-      object_manager_.get(), object_manager_->GetBus(), command,
-      buffet::dbus_constants::kCommandServicePathPrefix +
-          std::to_string(++next_id_))};
-  proxy->RegisterAsync(AsyncEventSequencer::GetDefaultCompletionAction());
-  // DBusCommandProxy::DBusCommandProxy() subscribe itself to weave::Command
-  // notifications. When weave::Command is being destroyed it sends
-  // ::OnCommandDestroyed() and DBusCommandProxy deletes itself.
-  proxy.release();
-}
-
-}  // namespace buffet
diff --git a/buffet/dbus_command_dispatcher.h b/buffet/dbus_command_dispatcher.h
deleted file mode 100644
index ea78520..0000000
--- a/buffet/dbus_command_dispatcher.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2015 The Android Open Source Project
-//
-// 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.
-
-#ifndef BUFFET_DBUS_COMMAND_DISPATCHER_H_
-#define BUFFET_DBUS_COMMAND_DISPATCHER_H_
-
-#include <map>
-#include <string>
-
-#include <base/macros.h>
-#include <base/memory/weak_ptr.h>
-
-namespace weave {
-class Command;
-class Device;
-}
-
-namespace brillo {
-namespace dbus_utils {
-class ExportedObjectManager;
-}  // namespace dbus_utils
-}  // namespace brillo
-
-namespace buffet {
-
-// Implements D-Bus dispatch of commands. When OnCommandAdded is called,
-// DBusCommandDispacher creates an instance of DBusCommandProxy object and
-// advertises it through ExportedObjectManager on D-Bus. Command handling
-// processes can watch the new D-Bus object appear and communicate with it to
-// update the command handling progress. Once command is handled,
-// DBusCommandProxy::Done() is called and the command is removed from the
-// command queue and D-Bus ExportedObjectManager.
-class DBusCommandDispacher final {
- public:
-  explicit DBusCommandDispacher(
-      const base::WeakPtr<brillo::dbus_utils::ExportedObjectManager>&
-          object_manager,
-      weave::Device* device);
-
- private:
-  void OnCommandAdded(const std::weak_ptr<weave::Command>& cmd);
-
-  base::WeakPtr<brillo::dbus_utils::ExportedObjectManager> object_manager_;
-  int next_id_{0};
-
-  // Default constructor is used in special circumstances such as for testing.
-  DBusCommandDispacher() = default;
-
-  base::WeakPtrFactory<DBusCommandDispacher> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(DBusCommandDispacher);
-};
-
-}  // namespace buffet
-
-#endif  // BUFFET_DBUS_COMMAND_DISPATCHER_H_
diff --git a/buffet/dbus_command_proxy.cc b/buffet/dbus_command_proxy.cc
deleted file mode 100644
index 011ba01..0000000
--- a/buffet/dbus_command_proxy.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2015 The Android Open Source Project
-//
-// 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 "buffet/dbus_command_proxy.h"
-
-#include <brillo/dbus/async_event_sequencer.h>
-#include <brillo/dbus/exported_object_manager.h>
-#include <weave/enum_to_string.h>
-
-#include "buffet/dbus_conversion.h"
-#include "buffet/weave_error_conversion.h"
-
-using brillo::dbus_utils::AsyncEventSequencer;
-using brillo::dbus_utils::ExportedObjectManager;
-
-namespace errors {
-namespace commands {
-const char kDomain[] = "weaved";
-const char kCommandDestroyed[] = "command_destroyed";
-}  // namespace commands
-}  // namespace errors
-
-namespace buffet {
-
-namespace {
-
-bool ReportDestroyedError(brillo::ErrorPtr* error) {
-  brillo::Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
-                       errors::commands::kCommandDestroyed,
-                       "Command has been destroyed");
-  return false;
-}
-
-}  // anonymous namespace
-
-DBusCommandProxy::DBusCommandProxy(ExportedObjectManager* object_manager,
-                                   const scoped_refptr<dbus::Bus>& bus,
-                                   const std::weak_ptr<weave::Command>& command,
-                                   std::string object_path)
-    : command_{command},
-      dbus_object_{object_manager, bus, dbus::ObjectPath{object_path}} {}
-
-void DBusCommandProxy::RegisterAsync(
-    const AsyncEventSequencer::CompletionAction& completion_callback) {
-  auto command = command_.lock();
-  if (!command)
-    return;
-
-  dbus_adaptor_.RegisterWithDBusObject(&dbus_object_);
-
-  // Set the initial property values before registering the DBus object.
-  dbus_adaptor_.SetName(command->GetName());
-  dbus_adaptor_.SetId(command->GetID());
-  dbus_adaptor_.SetComponent(command->GetComponent());
-  dbus_adaptor_.SetState(EnumToString(command->GetState()));
-  dbus_adaptor_.SetProgress(
-      DictionaryToDBusVariantDictionary(command->GetProgress()));
-  dbus_adaptor_.SetOrigin(EnumToString(command->GetOrigin()));
-  dbus_adaptor_.SetParameters(
-      DictionaryToDBusVariantDictionary(command->GetParameters()));
-  dbus_adaptor_.SetResults(
-      DictionaryToDBusVariantDictionary(command->GetResults()));
-
-  // Register the command DBus object and expose its methods and properties.
-  dbus_object_.RegisterAsync(completion_callback);
-}
-
-bool DBusCommandProxy::SetProgress(
-    brillo::ErrorPtr* error,
-    const brillo::VariantDictionary& progress) {
-  auto command = command_.lock();
-  if (!command)
-    return ReportDestroyedError(error);
-
-  LOG(INFO) << "Received call to Command<" << command->GetName()
-            << ">::SetProgress()";
-  auto dictionary = DictionaryFromDBusVariantDictionary(progress, error);
-  if (!dictionary)
-    return false;
-  weave::ErrorPtr weave_error;
-  if (!command->SetProgress(*dictionary, &weave_error)) {
-    ConvertError(*weave_error, error);
-    return false;
-  }
-  dbus_adaptor_.SetProgress(
-      DictionaryToDBusVariantDictionary(command->GetProgress()));
-  dbus_adaptor_.SetState(EnumToString(command->GetState()));
-  return true;
-}
-
-bool DBusCommandProxy::Complete(brillo::ErrorPtr* error,
-                                const brillo::VariantDictionary& results) {
-  auto command = command_.lock();
-  if (!command)
-    return ReportDestroyedError(error);
-
-  LOG(INFO) << "Received call to Command<" << command->GetName()
-            << ">::Complete()";
-  auto dictionary = DictionaryFromDBusVariantDictionary(results, error);
-  if (!dictionary)
-    return false;
-  weave::ErrorPtr weave_error;
-  if (!command->Complete(*dictionary, &weave_error)) {
-    ConvertError(*weave_error, error);
-    return false;
-  }
-  dbus_adaptor_.SetResults(
-      DictionaryToDBusVariantDictionary(command->GetResults()));
-  dbus_adaptor_.SetState(EnumToString(command->GetState()));
-  return true;
-}
-
-bool DBusCommandProxy::Abort(brillo::ErrorPtr* error,
-                             const std::string& code,
-                             const std::string& message) {
-  auto command = command_.lock();
-  if (!command)
-    return ReportDestroyedError(error);
-
-  LOG(INFO) << "Received call to Command<" << command->GetName()
-            << ">::Abort()";
-  weave::ErrorPtr cmd_error;
-  weave::Error::AddTo(&cmd_error, FROM_HERE, "command_error", code, message);
-  weave::ErrorPtr weave_error;
-  if (!command->Abort(cmd_error.get(), &weave_error)) {
-    ConvertError(*weave_error, error);
-    return false;
-  }
-  dbus_adaptor_.SetState(EnumToString(command->GetState()));
-  return true;
-}
-
-bool DBusCommandProxy::Cancel(brillo::ErrorPtr* error) {
-  auto command = command_.lock();
-  if (!command)
-    return ReportDestroyedError(error);
-
-  LOG(INFO) << "Received call to Command<" << command->GetName()
-            << ">::Cancel()";
-  weave::ErrorPtr weave_error;
-  if (!command->Cancel(&weave_error)) {
-    ConvertError(*weave_error, error);
-    return false;
-  }
-  dbus_adaptor_.SetState(EnumToString(command->GetState()));
-  return true;
-}
-
-}  // namespace buffet
diff --git a/buffet/dbus_command_proxy.h b/buffet/dbus_command_proxy.h
deleted file mode 100644
index 759c74a..0000000
--- a/buffet/dbus_command_proxy.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2015 The Android Open Source Project
-//
-// 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.
-
-#ifndef BUFFET_DBUS_COMMAND_PROXY_H_
-#define BUFFET_DBUS_COMMAND_PROXY_H_
-
-#include <string>
-
-#include <base/macros.h>
-#include <base/scoped_observer.h>
-#include <brillo/dbus/data_serialization.h>
-#include <brillo/dbus/dbus_object.h>
-#include <weave/command.h>
-
-#include "buffet/dbus_bindings/com.android.Weave.Command.h"
-
-namespace brillo {
-namespace dbus_utils {
-class ExportedObjectManager;
-}  // namespace dbus_utils
-}  // namespace brillo
-
-namespace buffet {
-
-class DBusCommandProxy : public com::android::Weave::CommandInterface {
- public:
-  DBusCommandProxy(brillo::dbus_utils::ExportedObjectManager* object_manager,
-                   const scoped_refptr<dbus::Bus>& bus,
-                   const std::weak_ptr<weave::Command>& command,
-                   std::string object_path);
-  ~DBusCommandProxy() override = default;
-
-  void RegisterAsync(
-      const brillo::dbus_utils::AsyncEventSequencer::CompletionAction&
-          completion_callback);
-
- private:
-  bool SetProgress(brillo::ErrorPtr* error,
-                   const brillo::VariantDictionary& progress) override;
-  bool Complete(brillo::ErrorPtr* error,
-                const brillo::VariantDictionary& results) override;
-  bool Abort(brillo::ErrorPtr* error,
-             const std::string& code,
-             const std::string& message) override;
-  bool Cancel(brillo::ErrorPtr* error) override;
-
-  std::weak_ptr<weave::Command> command_;
-  com::android::Weave::CommandAdaptor dbus_adaptor_{this};
-  brillo::dbus_utils::DBusObject dbus_object_;
-
-  friend class DBusCommandProxyTest;
-  friend class DBusCommandDispacherTest;
-  DISALLOW_COPY_AND_ASSIGN(DBusCommandProxy);
-};
-
-}  // namespace buffet
-
-#endif  // BUFFET_DBUS_COMMAND_PROXY_H_
diff --git a/buffet/dbus_command_proxy_unittest.cc b/buffet/dbus_command_proxy_unittest.cc
deleted file mode 100644
index 5225f11..0000000
--- a/buffet/dbus_command_proxy_unittest.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2015 The Android Open Source Project
-//
-// 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 "buffet/dbus_command_proxy.h"
-
-#include <functional>
-#include <memory>
-#include <vector>
-
-#include <dbus/mock_bus.h>
-#include <dbus/mock_exported_object.h>
-#include <dbus/property.h>
-#include <brillo/dbus/dbus_object.h>
-#include <brillo/dbus/dbus_object_test_helpers.h>
-#include <gtest/gtest.h>
-#include <weave/command.h>
-#include <weave/enum_to_string.h>
-#include <weave/test/mock_command.h>
-#include <weave/test/unittest_utils.h>
-
-#include "buffet/dbus_constants.h"
-
-namespace buffet {
-
-using ::testing::_;
-using ::testing::AnyNumber;
-using ::testing::Return;
-using ::testing::ReturnRef;
-using ::testing::ReturnRefOfCopy;
-using ::testing::StrictMock;
-
-using brillo::VariantDictionary;
-using brillo::dbus_utils::AsyncEventSequencer;
-using weave::test::CreateDictionaryValue;
-using weave::test::IsEqualValue;
-
-namespace {
-
-const char kTestCommandId[] = "cmd_1";
-
-MATCHER_P(EqualToJson, json, "") {
-  auto json_value = CreateDictionaryValue(json);
-  return IsEqualValue(*json_value, arg);
-}
-
-MATCHER_P2(ExpectError, code, message, "") {
-  return arg->GetCode() == code && arg->GetMessage() == message;
-}
-
-}  // namespace
-
-class DBusCommandProxyTest : public ::testing::Test {
- public:
-  void SetUp() override {
-    command_ = std::make_shared<StrictMock<weave::test::MockCommand>>();
-    // Set up a mock DBus bus object.
-    dbus::Bus::Options options;
-    options.bus_type = dbus::Bus::SYSTEM;
-    bus_ = new dbus::MockBus(options);
-    // By default, don't worry about threading assertions.
-    EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber());
-    EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber());
-
-    expected_result_dict_.SetInteger("height", 53);
-    expected_result_dict_.SetString("_jumpType", "_withKick");
-    EXPECT_CALL(*command_, GetID())
-        .WillOnce(ReturnRefOfCopy<std::string>(kTestCommandId));
-    // Use WillRepeatedly because GetName is used for logging.
-    EXPECT_CALL(*command_, GetName())
-        .WillRepeatedly(ReturnRefOfCopy<std::string>("robot.jump"));
-    EXPECT_CALL(*command_, GetComponent())
-        .WillRepeatedly(ReturnRefOfCopy<std::string>("myComponent"));
-    EXPECT_CALL(*command_, GetState())
-        .WillRepeatedly(Return(weave::Command::State::kQueued));
-    EXPECT_CALL(*command_, GetOrigin())
-        .WillOnce(Return(weave::Command::Origin::kLocal));
-    EXPECT_CALL(*command_, GetParameters())
-        .WillOnce(ReturnRef(expected_result_dict_));
-    EXPECT_CALL(*command_, GetProgress())
-        .WillRepeatedly(ReturnRef(empty_dict_));
-    EXPECT_CALL(*command_, GetResults())
-        .WillRepeatedly(ReturnRef(empty_dict_));
-
-    // Set up a mock ExportedObject to be used with the DBus command proxy.
-    std::string cmd_path = buffet::dbus_constants::kCommandServicePathPrefix;
-    cmd_path += kTestCommandId;
-    const dbus::ObjectPath kCmdObjPath(cmd_path);
-    // Use a mock exported object for the exported object manager.
-    mock_exported_object_command_ =
-        new dbus::MockExportedObject(bus_.get(), kCmdObjPath);
-    EXPECT_CALL(*bus_, GetExportedObject(kCmdObjPath))
-        .Times(AnyNumber())
-        .WillRepeatedly(Return(mock_exported_object_command_.get()));
-    EXPECT_CALL(*mock_exported_object_command_, ExportMethod(_, _, _, _))
-        .Times(AnyNumber());
-
-    proxy_.reset(new DBusCommandProxy{
-        nullptr, bus_, std::weak_ptr<weave::Command>{command_}, cmd_path});
-    GetCommandProxy()->RegisterAsync(
-        AsyncEventSequencer::GetDefaultCompletionAction());
-  }
-
-  void TearDown() override {
-    EXPECT_CALL(*mock_exported_object_command_, Unregister()).Times(1);
-    bus_ = nullptr;
-  }
-
-  DBusCommandProxy* GetCommandProxy() const { return proxy_.get(); }
-
-  com::android::Weave::CommandAdaptor* GetCommandAdaptor() const {
-    return &GetCommandProxy()->dbus_adaptor_;
-  }
-
-  com::android::Weave::CommandInterface* GetCommandInterface() const {
-    // DBusCommandProxy also implements CommandInterface.
-    return GetCommandProxy();
-  }
-
-  weave::Command::State GetCommandState() const {
-    weave::Command::State state;
-    EXPECT_TRUE(StringToEnum(GetCommandAdaptor()->GetState(), &state));
-    return state;
-  }
-
-  scoped_refptr<dbus::MockExportedObject> mock_exported_object_command_;
-  scoped_refptr<dbus::MockBus> bus_;
-  base::DictionaryValue empty_dict_;
-  base::DictionaryValue expected_result_dict_;
-
-  std::shared_ptr<StrictMock<weave::test::MockCommand>> command_;
-  std::unique_ptr<DBusCommandProxy> proxy_;
-};
-
-TEST_F(DBusCommandProxyTest, Init) {
-  VariantDictionary params = {
-      {"height", int32_t{53}}, {"_jumpType", std::string{"_withKick"}},
-  };
-  EXPECT_EQ(weave::Command::State::kQueued, GetCommandState());
-  EXPECT_EQ(params, GetCommandAdaptor()->GetParameters());
-  EXPECT_EQ(VariantDictionary{}, GetCommandAdaptor()->GetProgress());
-  EXPECT_EQ(VariantDictionary{}, GetCommandAdaptor()->GetResults());
-  EXPECT_EQ("robot.jump", GetCommandAdaptor()->GetName());
-  EXPECT_EQ("myComponent", GetCommandAdaptor()->GetComponent());
-  EXPECT_EQ(kTestCommandId, GetCommandAdaptor()->GetId());
-}
-
-TEST_F(DBusCommandProxyTest, SetProgress) {
-  EXPECT_CALL(*command_, SetProgress(EqualToJson("{'progress': 10}"), _))
-      .WillOnce(Return(true));
-  EXPECT_TRUE(
-      GetCommandInterface()->SetProgress(nullptr, {{"progress", int32_t{10}}}));
-}
-
-TEST_F(DBusCommandProxyTest, Complete) {
-  EXPECT_CALL(
-      *command_,
-      Complete(
-          EqualToJson("{'foo': 42, 'bar': 'foobar', 'resultList': [1, 2, 3]}"),
-          _))
-      .WillOnce(Return(true));
-  EXPECT_TRUE(GetCommandInterface()->Complete(
-      nullptr, VariantDictionary{{"foo", int32_t{42}},
-                                 {"bar", std::string{"foobar"}},
-                                 {"resultList", std::vector<int>{1, 2, 3}}}));
-}
-
-TEST_F(DBusCommandProxyTest, Abort) {
-  EXPECT_CALL(*command_, Abort(ExpectError("foo", "bar"), _))
-      .WillOnce(Return(true));
-  EXPECT_TRUE(GetCommandInterface()->Abort(nullptr, "foo", "bar"));
-}
-
-TEST_F(DBusCommandProxyTest, Cancel) {
-  EXPECT_CALL(*command_, Cancel(_)).WillOnce(Return(true));
-  EXPECT_TRUE(GetCommandInterface()->Cancel(nullptr));
-}
-
-}  // namespace buffet
diff --git a/buffet/dbus_constants.cc b/buffet/dbus_constants.cc
index 2a8b884..61eaf5c 100644
--- a/buffet/dbus_constants.cc
+++ b/buffet/dbus_constants.cc
@@ -20,43 +20,6 @@
 
 const char kServiceName[] = "com.android.Weave";
 const char kRootServicePath[] = "/com/android/Weave";
-const char kCommandServicePathPrefix[] = "/com/android/Weave/commands/";
-
-namespace avahi {
-
-const char kServiceName[] = "org.freedesktop.Avahi";
-
-const char kServerInterface[] = "org.freedesktop.Avahi.Server";
-const char kServerPath[] = "/";
-const char kServerMethodEntryGroupNew[] = "EntryGroupNew";
-const char kServerMethodServiceBrowserNew[] = "ServiceBrowserNew";
-const char kServerMethodServiceResolverNew[] = "ServiceResolverNew";
-const char kServerMethodGetHostName[] = "GetHostName";
-const char kServerMethodGetState[] = "GetState";
-const char kServerSignalStateChanged[] = "StateChanged";
-
-const char kGroupInterface[] = "org.freedesktop.Avahi.EntryGroup";
-const char kGroupMethodAddRecord[] = "AddRecord";
-const char kGroupMethodAddService[] = "AddService";
-const char kGroupMethodCommit[] = "Commit";
-const char kGroupMethodFree[] = "Free";
-const char kGroupMethodUpdateServiceTxt[] = "UpdateServiceTxt";
-const char kGroupMethodReset[]= "Reset";
-const char kGroupSignalStateChanged[] = "StateChanged";
-
-const char kServiceBrowserInterface[] = "org.freedesktop.Avahi.ServiceBrowser";
-const char kServiceBrowserMethodFree[] = "Free";
-const char kServiceBrowserSignalItemNew[] = "ItemNew";
-const char kServiceBrowserSignalItemRemove[] = "ItemRemove";
-const char kServiceBrowserSignalFailure[] = "Failure";
-
-const char kServiceResolverInterface[] =
-    "org.freedesktop.Avahi.ServiceResolver";
-const char kServiceResolverMethodFree[] = "Free";
-const char kServiceResolverSignalFound[] = "Found";
-const char kServiceResolverSignalFailure[] = "Failure";
-
-}  // namespace avahi
 
 }  // namespace dbus constants
 
diff --git a/buffet/dbus_constants.h b/buffet/dbus_constants.h
index bc74dac..ae91891 100644
--- a/buffet/dbus_constants.h
+++ b/buffet/dbus_constants.h
@@ -25,44 +25,6 @@
 // The object at this path implements the ObjectManager interface.
 extern const char kRootServicePath[];
 
-// D-Bus object path prefix for Command objects.
-extern const char kCommandServicePathPrefix[];
-
-namespace avahi {
-
-extern const char kServiceName[];
-
-extern const char kServerInterface[];
-extern const char kServerPath[];
-extern const char kServerMethodEntryGroupNew[];
-extern const char kServerMethodServiceBrowserNew[];
-extern const char kServerMethodServiceResolverNew[];
-extern const char kServerMethodGetHostName[];
-extern const char kServerMethodGetState[];
-extern const char kServerSignalStateChanged[];
-
-extern const char kGroupInterface[];
-extern const char kGroupMethodAddRecord[];
-extern const char kGroupMethodAddService[];
-extern const char kGroupMethodCommit[];
-extern const char kGroupMethodFree[];
-extern const char kGroupMethodReset[];
-extern const char kGroupSignalStateChanged[];
-
-extern const char kServiceBrowserInterface[];
-extern const char kServiceBrowserMethodFree[];
-extern const char kServiceBrowserSignalItemNew[];
-extern const char kServiceBrowserSignalItemRemove[];
-extern const char kServiceBrowserSignalFailure[];
-
-extern const char kServiceResolverInterface[];
-extern const char kServiceResolverMethodFree[];
-extern const char kGroupMethodUpdateServiceTxt[];
-extern const char kServiceResolverSignalFound[];
-extern const char kServiceResolverSignalFailure[];
-
-}  // namespace avahi
-
 }  // namespace dbus_constants
 
 }  // namespace buffet
diff --git a/buffet/etc/dbus-1/com.android.Weave.conf b/buffet/etc/dbus-1/com.android.Weave.conf
deleted file mode 100644
index c9f77e0..0000000
--- a/buffet/etc/dbus-1/com.android.Weave.conf
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE busconfig PUBLIC
- "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-<busconfig>
-  <policy user="root">
-    <allow send_destination="com.android.Weave" />
-  </policy>
-
-  <policy group="weaved">
-    <allow send_destination="com.android.Weave" />
-  </policy>
-
-  <policy user="weaved">
-    <allow own="com.android.Weave" />
-  </policy>
-
-  <policy user="webservd">
-    <allow send_destination="com.android.Weave"
-           send_interface="com.chromium.WebServer.RequestHandler"/>
-  </policy>
-</busconfig>
diff --git a/buffet/etc/init/buffet.conf b/buffet/etc/init/buffet.conf
deleted file mode 100644
index 7feef4a..0000000
--- a/buffet/etc/init/buffet.conf
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright 2015 The Android Open Source Project
-#
-# 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.
-
-description     "Brillo Buffet Service"
-author          "chromium-os-dev@chromium.org"
-
-start on starting system-services
-stop on stopping system-services
-respawn
-
-env BUFFET_LOG_LEVEL=0
-env BUFFET_ENABLE_XMPP=
-env BUFFET_STATE_PATH=
-env BUFFET_CONFIG_PATH=
-env BUFFET_ENABLE_PING=false
-env BUFFET_DEVICE_WHITELIST=
-env BUFFET_DISABLE_PRIVET=false
-env BUFFET_TEST_DEFINITIONS_PATH=
-env BUFFET_DISABLE_SECURITY=false
-env BUFFET_TEST_PRIVET_SSID=
-
-pre-start script
-  mkdir -m 0755 -p /var/lib/buffet
-  chown -R buffet:buffet /var/lib/buffet
-end script
-
-# Minijail actually forks off our desired process.
-expect fork
-
-exec minijail0 -i -g buffet -u buffet /usr/bin/buffet \
-    --v="${BUFFET_LOG_LEVEL}" \
-    --config_path="${BUFFET_CONFIG_PATH}" \
-    --state_path="${BUFFET_STATE_PATH}" \
-    --disable_security="${BUFFET_DISABLE_SECURITY}" \
-    --enable_ping="${BUFFET_ENABLE_PING}" \
-    --device_whitelist="${BUFFET_DEVICE_WHITELIST}" \
-    --disable_privet="${BUFFET_DISABLE_PRIVET}" \
-    --test_definitions_path="${BUFFET_TEST_DEFINITIONS_PATH}" \
-    --enable_xmpp="${BUFFET_ENABLE_XMPP}" \
-    --test_privet_ssid="${BUFFET_TEST_PRIVET_SSID}"
-
-# Wait for daemon to claim its D-Bus name before transitioning to started.
-post-start exec gdbus wait --system --timeout 30 org.chromium.Buffet
diff --git a/buffet/main.cc b/buffet/main.cc
index 58e24da..04a5134 100644
--- a/buffet/main.cc
+++ b/buffet/main.cc
@@ -15,8 +15,11 @@
 #include <string>
 
 #include <signal.h>
+#include <sysexits.h>
 
 #include <base/files/file_path.h>
+#include <binderwrapper/binder_wrapper.h>
+#include <brillo/binder_watcher.h>
 #include <brillo/daemons/dbus_daemon.h>
 #include <brillo/dbus/async_event_sequencer.h>
 #include <brillo/dbus/exported_object_manager.h>
@@ -27,6 +30,7 @@
 #include "buffet/buffet_config.h"
 #include "buffet/dbus_constants.h"
 #include "buffet/manager.h"
+#include "common/binder_constants.h"
 
 using brillo::dbus_utils::AsyncEventSequencer;
 using brillo::DBusServiceDaemon;
@@ -41,8 +45,19 @@
       : DBusServiceDaemon(kServiceName, kRootServicePath), options_{options} {}
 
  protected:
+  int OnInit() override {
+    android::BinderWrapper::Create();
+    if (!binder_watcher_.Init())
+      return EX_OSERR;
+
+    return brillo::DBusServiceDaemon::OnInit();
+  }
+
   void RegisterDBusObjectsAsync(AsyncEventSequencer* sequencer) override {
-    manager_.reset(new Manager(options_, object_manager_->AsWeakPtr()));
+    manager_ = new Manager{options_, bus_};
+    android::BinderWrapper::Get()->RegisterService(
+        weaved::binder::kWeaveServiceName,
+        android::IInterface::asBinder(manager_));
     manager_->Start(sequencer);
   }
 
@@ -50,8 +65,9 @@
 
  private:
   Manager::Options options_;
+  brillo::BinderWatcher binder_watcher_;
+  android::sp<buffet::Manager> manager_;
 
-  std::unique_ptr<buffet::Manager> manager_;
   DISALLOW_COPY_AND_ASSIGN(Daemon);
 };
 
diff --git a/buffet/manager.cc b/buffet/manager.cc
index 2e53c62..27610ec 100644
--- a/buffet/manager.cc
+++ b/buffet/manager.cc
@@ -26,10 +26,9 @@
 #include <base/json/json_writer.h>
 #include <base/message_loop/message_loop.h>
 #include <base/time/time.h>
+#include <binderwrapper/binder_wrapper.h>
 #include <cutils/properties.h>
 #include <brillo/bind_lambda.h>
-#include <brillo/dbus/async_event_sequencer.h>
-#include <brillo/dbus/exported_object_manager.h>
 #include <brillo/errors/error.h>
 #include <brillo/http/http_transport.h>
 #include <brillo/http/http_utils.h>
@@ -44,26 +43,21 @@
 #include "brillo/weaved_system_properties.h"
 #include "buffet/bluetooth_client.h"
 #include "buffet/buffet_config.h"
-#include "buffet/dbus_command_dispatcher.h"
-#include "buffet/dbus_conversion.h"
 #include "buffet/http_transport_client.h"
 #include "buffet/mdns_client.h"
 #include "buffet/shill_client.h"
 #include "buffet/weave_error_conversion.h"
 #include "buffet/webserv_client.h"
+#include "common/binder_utils.h"
 
 using brillo::dbus_utils::AsyncEventSequencer;
-using brillo::dbus_utils::DBusMethodResponse;
-using brillo::dbus_utils::ExportedObjectManager;
+using NotificationListener =
+    android::weave::IWeaveServiceManagerNotificationListener;
 
 namespace buffet {
 
 namespace {
 
-const char kPairingSessionIdKey[] = "sessionId";
-const char kPairingModeKey[] = "mode";
-const char kPairingCodeKey[] = "code";
-
 const char kErrorDomain[] = "buffet";
 const char kFileReadError[] = "file_read_error";
 
@@ -152,6 +146,20 @@
   }
 }
 
+// Updates the manager's state property if the new value is different from
+// the current value. In this case also adds the appropriate notification ID
+// to the array to record the state change for clients.
+void UpdateValue(Manager* manager,
+                 std::string Manager::* prop,
+                 const std::string& new_value,
+                 int notification,
+                 std::vector<int>* notification_ids) {
+  if (manager->*prop != new_value) {
+    manager->*prop = new_value;
+    notification_ids->push_back(notification);
+  }
+}
+
 }  // anonymous namespace
 
 class Manager::TaskRunner : public weave::provider::TaskRunner {
@@ -164,21 +172,23 @@
 };
 
 Manager::Manager(const Options& options,
-                 const base::WeakPtr<ExportedObjectManager>& object_manager)
-    : options_{options},
-      dbus_object_(object_manager.get(),
-                   object_manager->GetBus(),
-                   com::android::Weave::ManagerAdaptor::GetObjectPath()) {}
+                 const scoped_refptr<dbus::Bus>& bus)
+    : options_{options}, bus_{bus} {}
 
 Manager::~Manager() {
+  android::BinderWrapper* binder_wrapper = android::BinderWrapper::Get();
+  for (const auto& listener : notification_listeners_) {
+    binder_wrapper->UnregisterForDeathNotifications(
+        android::IInterface::asBinder(listener));
+  }
+  for (const auto& pair : services_) {
+    binder_wrapper->UnregisterForDeathNotifications(
+        android::IInterface::asBinder(pair.first));
+  }
 }
 
 void Manager::Start(AsyncEventSequencer* sequencer) {
   RestartWeave(sequencer);
-
-  dbus_adaptor_.RegisterWithDBusObject(&dbus_object_);
-  dbus_registration_handler_ =
-      sequencer->GetHandler("Manager.RegisterAsync() failed.", true);
 }
 
 void Manager::RestartWeave(AsyncEventSequencer* sequencer) {
@@ -187,7 +197,7 @@
   task_runner_.reset(new TaskRunner{});
   config_.reset(new BuffetConfig{options_.config_options});
   http_client_.reset(new HttpTransportClient);
-  shill_client_.reset(new ShillClient{dbus_object_.GetBus(),
+  shill_client_.reset(new ShillClient{bus_,
                                       options_.device_whitelist,
                                       !options_.xmpp_enabled});
   weave::provider::HttpServer* http_server{nullptr};
@@ -195,7 +205,7 @@
   if (!options_.disable_privet) {
     mdns_client_ = MdnsClient::CreateInstance();
     web_serv_client_.reset(new WebServClient{
-        dbus_object_.GetBus(), sequencer,
+        bus_, sequencer,
         base::Bind(&Manager::CreateDevice, weak_ptr_factory_.GetWeakPtr())});
     bluetooth_client_ = BluetoothClient::CreateInstance();
     http_server = web_serv_client_.get();
@@ -233,9 +243,6 @@
   device_->AddSettingsChangedCallback(
       base::Bind(&Manager::OnConfigChanged, weak_ptr_factory_.GetWeakPtr()));
 
-  command_dispatcher_.reset(
-      new DBusCommandDispacher{dbus_object_.GetObjectManager(), device_.get()});
-
   device_->AddTraitDefsChangedCallback(
       base::Bind(&Manager::OnTraitDefsChanged,
                  weak_ptr_factory_.GetWeakPtr()));
@@ -253,15 +260,10 @@
       base::Bind(&Manager::OnPairingStart, weak_ptr_factory_.GetWeakPtr()),
       base::Bind(&Manager::OnPairingEnd, weak_ptr_factory_.GetWeakPtr()));
 
-  auto handler = dbus_registration_handler_;
-  if (handler.is_null())
-    handler = AsyncEventSequencer::GetDefaultCompletionAction();
-  dbus_object_.RegisterAsync(handler);
-  dbus_registration_handler_.Reset();
+  CreateServicesForClients();
 }
 
 void Manager::Stop() {
-  command_dispatcher_.reset();
   device_.reset();
 #ifdef BUFFET_USE_WIFI_BOOTSTRAPPING
   web_serv_client_.reset();
@@ -273,139 +275,195 @@
   task_runner_.reset();
 }
 
-void Manager::RegisterDevice(DBusMethodResponsePtr<std::string> response,
-                             const std::string& ticket_id) {
-  LOG(INFO) << "Received call to Manager.RegisterDevice()";
-
-  device_->Register(ticket_id, base::Bind(&Manager::RegisterDeviceDone,
-                                          weak_ptr_factory_.GetWeakPtr(),
-                                          base::Passed(&response)));
-}
-
-void Manager::RegisterDeviceDone(DBusMethodResponsePtr<std::string> response,
-                                 weave::ErrorPtr error) {
-  if (error) {
-    brillo::ErrorPtr brillo_error;
-    ConvertError(*error, &brillo_error);
-    return response->ReplyWithError(brillo_error.get());
-  }
-  LOG(INFO) << "Device registered: " << device_->GetSettings().cloud_id;
-  response->Return(device_->GetSettings().cloud_id);
-}
-
-void Manager::AddComponent(DBusMethodResponsePtr<> response,
-                           const std::string& name,
-                           const std::vector<std::string>& traits) {
-  brillo::ErrorPtr brillo_error;
-  weave::ErrorPtr error;
-  if (!device_->AddComponent(name, traits, &error)) {
-    ConvertError(*error, &brillo_error);
-    return response->ReplyWithError(brillo_error.get());
-  }
-  response->Return();
-}
-
-void Manager::UpdateState(DBusMethodResponsePtr<> response,
-                          const std::string& component,
-                          const brillo::VariantDictionary& property_set) {
-  brillo::ErrorPtr brillo_error;
-  auto properties =
-      DictionaryFromDBusVariantDictionary(property_set, &brillo_error);
-  if (!properties)
-    return response->ReplyWithError(brillo_error.get());
-
-  weave::ErrorPtr error;
-  if (!device_->SetStateProperties(component, *properties, &error)) {
-    ConvertError(*error, &brillo_error);
-    return response->ReplyWithError(brillo_error.get());
-  }
-  response->Return();
-}
-
-void Manager::AddCommand(DBusMethodResponsePtr<std::string> response,
-                         const std::string& json_command) {
-  std::string error_message;
-  std::unique_ptr<base::Value> value(
-      base::JSONReader::ReadAndReturnError(json_command, base::JSON_PARSE_RFC,
-                                           nullptr, &error_message)
-          .release());
-  const base::DictionaryValue* command{nullptr};
-  if (!value || !value->GetAsDictionary(&command)) {
-    return response->ReplyWithError(FROM_HERE, brillo::errors::json::kDomain,
-                                    brillo::errors::json::kParseError,
-                                    error_message);
-  }
-
-  std::string id;
-  weave::ErrorPtr error;
-  if (!device_->AddCommand(*command, &id, &error)) {
-    brillo::ErrorPtr brillo_error;
-    ConvertError(*error, &brillo_error);
-    return response->ReplyWithError(brillo_error.get());
-  }
-
-  response->Return(id);
-}
-
-std::string Manager::TestMethod(const std::string& message) {
-  LOG(INFO) << "Received call to test method: " << message;
-  return message;
-}
-
 void Manager::OnTraitDefsChanged() {
-  const base::DictionaryValue& state = device_->GetTraits();
-  std::string json;
-  base::JSONWriter::WriteWithOptions(
-      state, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json);
-  dbus_adaptor_.SetTraits(json);
+  NotifyServiceManagerChange({NotificationListener::TRAITS});
 }
 
 void Manager::OnComponentTreeChanged() {
-  const base::DictionaryValue& state = device_->GetComponents();
-  std::string json;
-  base::JSONWriter::WriteWithOptions(
-      state, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json);
-  dbus_adaptor_.SetComponents(json);
+  NotifyServiceManagerChange({NotificationListener::COMPONENTS});
 }
 
 void Manager::OnGcdStateChanged(weave::GcdState state) {
-  std::string state_string = weave::EnumToString(state);
-  dbus_adaptor_.SetStatus(state_string);
-  property_set(weaved::system_properties::kState, state_string.c_str());
+  state_ = weave::EnumToString(state);
+  NotifyServiceManagerChange({NotificationListener::STATE});
+  property_set(weaved::system_properties::kState, state_.c_str());
 }
 
 void Manager::OnConfigChanged(const weave::Settings& settings) {
-  dbus_adaptor_.SetDeviceId(settings.cloud_id);
-  dbus_adaptor_.SetOemName(settings.oem_name);
-  dbus_adaptor_.SetModelName(settings.model_name);
-  dbus_adaptor_.SetModelId(settings.model_id);
-  dbus_adaptor_.SetName(settings.name);
-  dbus_adaptor_.SetDescription(settings.description);
-  dbus_adaptor_.SetLocation(settings.location);
+  std::vector<int> ids;
+  UpdateValue(this, &Manager::cloud_id_, settings.cloud_id,
+              NotificationListener::CLOUD_ID, &ids);
+  UpdateValue(this, &Manager::device_id_, settings.device_id,
+              NotificationListener::DEVICE_ID, &ids);
+  UpdateValue(this, &Manager::device_name_, settings.name,
+              NotificationListener::DEVICE_NAME, &ids);
+  UpdateValue(this, &Manager::device_description_, settings.description,
+              NotificationListener::DEVICE_DESCRIPTION, &ids);
+  UpdateValue(this, &Manager::device_location_, settings.location,
+              NotificationListener::DEVICE_LOCATION, &ids);
+  UpdateValue(this, &Manager::oem_name_, settings.oem_name,
+              NotificationListener::OEM_NAME, &ids);
+  UpdateValue(this, &Manager::model_id_, settings.model_id,
+              NotificationListener::MODEL_ID, &ids);
+  UpdateValue(this, &Manager::model_name_, settings.model_name,
+              NotificationListener::MODEL_NAME, &ids);
+  NotifyServiceManagerChange(ids);
 }
 
 void Manager::OnPairingStart(const std::string& session_id,
                              weave::PairingType pairing_type,
                              const std::vector<uint8_t>& code) {
-  // For now, just overwrite the exposed PairInfo with
-  // the most recent pairing attempt.
-  dbus_adaptor_.SetPairingInfo(brillo::VariantDictionary{
-      {kPairingSessionIdKey, session_id},
-      {kPairingModeKey, weave::EnumToString(pairing_type)},
-      {kPairingCodeKey, code},
-  });
+  // For now, just overwrite the exposed PairInfo with the most recent pairing
+  // attempt.
+  std::vector<int> ids;
+  UpdateValue(this, &Manager::pairing_session_id_, session_id,
+              NotificationListener::PAIRING_SESSION_ID, &ids);
+  UpdateValue(this, &Manager::pairing_mode_, EnumToString(pairing_type),
+              NotificationListener::PAIRING_MODE, &ids);
+  std::string pairing_code{code.begin(), code.end()};
+  UpdateValue(this, &Manager::pairing_code_, pairing_code,
+              NotificationListener::PAIRING_CODE, &ids);
+  NotifyServiceManagerChange(ids);
 }
 
 void Manager::OnPairingEnd(const std::string& session_id) {
-  auto exposed_pairing_attempt = dbus_adaptor_.GetPairingInfo();
-  auto it = exposed_pairing_attempt.find(kPairingSessionIdKey);
-  if (it == exposed_pairing_attempt.end()) {
+  if (pairing_session_id_ != session_id)
     return;
+  std::vector<int> ids;
+  UpdateValue(this, &Manager::pairing_session_id_, "",
+              NotificationListener::PAIRING_SESSION_ID, &ids);
+  UpdateValue(this, &Manager::pairing_mode_, "",
+              NotificationListener::PAIRING_MODE, &ids);
+  UpdateValue(this, &Manager::pairing_code_, "",
+              NotificationListener::PAIRING_CODE, &ids);
+  NotifyServiceManagerChange(ids);
+}
+
+android::binder::Status Manager::connect(
+    const android::sp<android::weave::IWeaveClient>& client) {
+  pending_clients_.push_back(client);
+  if (device_)
+    CreateServicesForClients();
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::registerNotificationListener(
+    const WeaveServiceManagerNotificationListener& listener) {
+  notification_listeners_.insert(listener);
+  android::BinderWrapper::Get()->RegisterForDeathNotifications(
+      android::IInterface::asBinder(listener),
+      base::Bind(&Manager::OnNotificationListenerDestroyed,
+                 weak_ptr_factory_.GetWeakPtr(), listener));
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getCloudId(android::String16* id) {
+  *id = weaved::binder_utils::ToString16(cloud_id_);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getDeviceId(android::String16* id) {
+  *id = weaved::binder_utils::ToString16(device_id_);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getDeviceName(android::String16* name) {
+  *name = weaved::binder_utils::ToString16(device_name_);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getDeviceDescription(
+    android::String16* description) {
+  *description = weaved::binder_utils::ToString16(device_description_);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getDeviceLocation(
+    android::String16* location) {
+  *location = weaved::binder_utils::ToString16(device_location_);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getOemName(android::String16* name) {
+  *name = weaved::binder_utils::ToString16(oem_name_);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getModelName(android::String16* name) {
+  *name = weaved::binder_utils::ToString16(model_name_);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getModelId(android::String16* id) {
+  *id = weaved::binder_utils::ToString16(model_id_);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getPairingSessionId(android::String16* id) {
+  *id = weaved::binder_utils::ToString16(pairing_session_id_);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getPairingMode(android::String16* mode) {
+  *mode = weaved::binder_utils::ToString16(pairing_mode_);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getPairingCode(android::String16* code) {
+  *code = weaved::binder_utils::ToString16(pairing_code_);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getState(android::String16* state) {
+  *state = weaved::binder_utils::ToString16(state_);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getTraits(android::String16* traits) {
+  *traits = weaved::binder_utils::ToString16(device_->GetTraits());
+  return android::binder::Status::ok();
+}
+
+android::binder::Status Manager::getComponents(android::String16* components) {
+  *components = weaved::binder_utils::ToString16(device_->GetComponents());
+  return android::binder::Status::ok();
+}
+
+void Manager::CreateServicesForClients() {
+  CHECK(device_);
+  // For safety, iterate over a copy of |pending_clients_| and clear the
+  // original vector before performing the iterations.
+  std::vector<android::sp<android::weave::IWeaveClient>> pending_clients_copy;
+  std::swap(pending_clients_copy, pending_clients_);
+  for (const auto& client : pending_clients_copy) {
+    android::sp<BinderWeaveService> service =
+        new BinderWeaveService{device_.get(), client};
+    services_.emplace(client, service);
+    client->onServiceConnected(service);
+    android::BinderWrapper::Get()->RegisterForDeathNotifications(
+        android::IInterface::asBinder(client),
+        base::Bind(&Manager::OnClientDisconnected,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   client));
   }
-  std::string exposed_session{it->second.TryGet<std::string>()};
-  if (exposed_session == session_id) {
-    dbus_adaptor_.SetPairingInfo(brillo::VariantDictionary{});
-  }
+}
+
+void Manager::OnClientDisconnected(
+    const android::sp<android::weave::IWeaveClient>& client) {
+  services_.erase(client);
+}
+
+void Manager::OnNotificationListenerDestroyed(
+    const WeaveServiceManagerNotificationListener& notification_listener) {
+  notification_listeners_.erase(notification_listener);
+}
+
+void Manager::NotifyServiceManagerChange(
+    const std::vector<int>& notification_ids) {
+  if (notification_ids.empty())
+    return;
+  for (const auto& listener : notification_listeners_)
+    listener->notifyServiceManagerChange(notification_ids);
 }
 
 }  // namespace buffet
diff --git a/buffet/manager.h b/buffet/manager.h
index 9522340..18e1aea 100644
--- a/buffet/manager.h
+++ b/buffet/manager.h
@@ -24,42 +24,26 @@
 #include <base/macros.h>
 #include <base/memory/weak_ptr.h>
 #include <base/values.h>
-#include <brillo/dbus/data_serialization.h>
-#include <brillo/dbus/dbus_object.h>
-#include <brillo/dbus/exported_property_set.h>
+#include <brillo/dbus/async_event_sequencer.h>
 #include <brillo/errors/error.h>
 #include <weave/device.h>
 
+#include "android/weave/BnWeaveServiceManager.h"
+#include "buffet/binder_weave_service.h"
 #include "buffet/buffet_config.h"
-#include "buffet/dbus_bindings/com.android.Weave.Manager.h"
-
-namespace brillo {
-namespace dbus_utils {
-class ExportedObjectManager;
-}  // namespace dbus_utils
-}  // namespace chromeos
 
 namespace buffet {
 
 class BluetoothClient;
-class DBusCommandDispacher;
 class HttpTransportClient;
 class MdnsClient;
 class ShillClient;
 class WebServClient;
 
-template<typename... Types>
-using DBusMethodResponsePtr =
-    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<Types...>>;
-
-template<typename... Types>
-using DBusMethodResponse =
-    brillo::dbus_utils::DBusMethodResponse<Types...>;
-
 // The Manager is responsible for global state of Buffet.  It exposes
 // interfaces which affect the entire device such as device registration and
 // device state.
-class Manager final : public com::android::Weave::ManagerInterface {
+class Manager final : public android::weave::BnWeaveServiceManager {
  public:
   struct Options {
     bool xmpp_enabled = true;
@@ -70,35 +54,39 @@
     BuffetConfig::Options config_options;
   };
 
-  explicit Manager(
-      const Options& options,
-      const base::WeakPtr<brillo::dbus_utils::ExportedObjectManager>&
-          object_manager);
-  ~Manager();
+  Manager(const Options& options, const scoped_refptr<dbus::Bus>& bus);
+  ~Manager() override;
 
   void Start(brillo::dbus_utils::AsyncEventSequencer* sequencer);
-
   void Stop();
 
  private:
   void RestartWeave(brillo::dbus_utils::AsyncEventSequencer* sequencer);
   void CreateDevice();
 
-  // DBus methods:
-  void RegisterDevice(DBusMethodResponsePtr<std::string> response,
-                      const std::string& ticket_id) override;
-  void AddComponent(DBusMethodResponsePtr<> response,
-                    const std::string& name,
-                    const std::vector<std::string>& traits) override;
-  void UpdateState(DBusMethodResponsePtr<> response,
-                   const std::string& component,
-                   const brillo::VariantDictionary& property_set) override;
-  void AddCommand(DBusMethodResponsePtr<std::string> response,
-                  const std::string& json_command) override;
-  std::string TestMethod(const std::string& message) override;
-
-  void StartPrivet(const Options& options,
-                   brillo::dbus_utils::AsyncEventSequencer* sequencer);
+  // Binder methods for IWeaveServiceManager:
+  using WeaveServiceManagerNotificationListener =
+      android::sp<android::weave::IWeaveServiceManagerNotificationListener>;
+  android::binder::Status connect(
+      const android::sp<android::weave::IWeaveClient>& client) override;
+  android::binder::Status registerNotificationListener(
+      const WeaveServiceManagerNotificationListener& listener) override;
+  android::binder::Status getDeviceId(android::String16* id) override;
+  android::binder::Status getCloudId(android::String16* id) override;
+  android::binder::Status getDeviceName(android::String16* name) override;
+  android::binder::Status getDeviceDescription(
+      android::String16* description) override;
+  android::binder::Status getDeviceLocation(
+      android::String16* location) override;
+  android::binder::Status getOemName(android::String16* name) override;
+  android::binder::Status getModelName(android::String16* name) override;
+  android::binder::Status getModelId(android::String16* id) override;
+  android::binder::Status getPairingSessionId(android::String16* id) override;
+  android::binder::Status getPairingMode(android::String16* mode) override;
+  android::binder::Status getPairingCode(android::String16* code) override;
+  android::binder::Status getState(android::String16* state) override;
+  android::binder::Status getTraits(android::String16* traits) override;
+  android::binder::Status getComponents(android::String16* components) override;
 
   void OnTraitDefsChanged();
   void OnComponentTreeChanged();
@@ -109,13 +97,15 @@
                       const std::vector<uint8_t>& code);
   void OnPairingEnd(const std::string& session_id);
 
-  void RegisterDeviceDone(DBusMethodResponsePtr<std::string> response,
-                          weave::ErrorPtr error);
+  void CreateServicesForClients();
+  void OnClientDisconnected(
+      const android::sp<android::weave::IWeaveClient>& client);
+  void OnNotificationListenerDestroyed(
+      const WeaveServiceManagerNotificationListener& notification_listener);
+  void NotifyServiceManagerChange(const std::vector<int>& notification_ids);
 
   Options options_;
-
-  com::android::Weave::ManagerAdaptor dbus_adaptor_{this};
-  brillo::dbus_utils::DBusObject dbus_object_;
+  scoped_refptr<dbus::Bus> bus_;
 
   class TaskRunner;
   std::unique_ptr<TaskRunner> task_runner_;
@@ -126,8 +116,25 @@
   std::unique_ptr<MdnsClient> mdns_client_;
   std::unique_ptr<WebServClient> web_serv_client_;
   std::unique_ptr<weave::Device> device_;
-  std::unique_ptr<DBusCommandDispacher> command_dispatcher_;
-  brillo::dbus_utils::AsyncEventSequencer::Handler dbus_registration_handler_;
+
+  std::vector<android::sp<android::weave::IWeaveClient>> pending_clients_;
+  std::map<android::sp<android::weave::IWeaveClient>,
+           android::sp<BinderWeaveService>> services_;
+  std::set<WeaveServiceManagerNotificationListener> notification_listeners_;
+
+  // State properties.
+  std::string cloud_id_;
+  std::string device_id_;
+  std::string device_name_;
+  std::string device_description_;
+  std::string device_location_;
+  std::string oem_name_;
+  std::string model_name_;
+  std::string model_id_;
+  std::string pairing_session_id_;
+  std::string pairing_mode_;
+  std::string pairing_code_;
+  std::string state_;
 
   base::WeakPtrFactory<Manager> weak_ptr_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(Manager);
diff --git a/common/binder_constants.cc b/common/binder_constants.cc
new file mode 100644
index 0000000..b17962b
--- /dev/null
+++ b/common/binder_constants.cc
@@ -0,0 +1,23 @@
+// Copyright 2016 The Android Open Source Project
+//
+// 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 "common/binder_constants.h"
+
+namespace weaved {
+namespace binder {
+
+const char kWeaveServiceName[] = "weave_service";
+
+}  // namespace binder
+}  // namespace weaved
diff --git a/common/binder_constants.h b/common/binder_constants.h
new file mode 100644
index 0000000..82935cd
--- /dev/null
+++ b/common/binder_constants.h
@@ -0,0 +1,26 @@
+// Copyright 2016 The Android Open Source Project
+//
+// 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.
+
+#ifndef COMMON_BINDER_CONSTANTS_H_
+#define COMMON_BINDER_CONSTANTS_H_
+
+namespace weaved {
+namespace binder {
+
+extern const char kWeaveServiceName[];
+
+}  // namespace binder
+}  // namespace weaved
+
+#endif  // COMMON_BINDER_CONSTANTS_H_
diff --git a/common/binder_utils.cc b/common/binder_utils.cc
new file mode 100644
index 0000000..6f66040
--- /dev/null
+++ b/common/binder_utils.cc
@@ -0,0 +1,65 @@
+// Copyright 2016 The Android Open Source Project
+//
+// 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 "common/binder_utils.h"
+
+#include <base/json/json_reader.h>
+#include <base/json/json_writer.h>
+
+namespace weaved {
+namespace binder_utils {
+
+android::binder::Status ToStatus(bool success, weave::ErrorPtr* error) {
+  if (success)
+    return android::binder::Status::ok();
+  return android::binder::Status::fromServiceSpecificError(
+      1, android::String8{error->get()->GetMessage().c_str()});
+}
+
+bool StatusToError(android::binder::Status status, brillo::ErrorPtr* error) {
+  if (status.isOk())
+    return true;
+  brillo::Error::AddTo(error, FROM_HERE, "binder",
+                       std::to_string(status.exceptionCode()),
+                       status.exceptionMessage().string());
+  return false;
+}
+
+android::String16 ToString16(const base::Value& value) {
+  std::string json;
+  base::JSONWriter::Write(value, &json);
+  return ToString16(json);
+}
+
+android::binder::Status ParseDictionary(
+    const android::String16& json,
+    std::unique_ptr<base::DictionaryValue>* dict) {
+  int error = 0;
+  std::string message;
+  std::unique_ptr<base::Value> value{
+      base::JSONReader::ReadAndReturnError(ToString(json), base::JSON_PARSE_RFC,
+                                           &error, &message)
+          .release()};
+  base::DictionaryValue* dict_value = nullptr;
+  if (!value || !value->GetAsDictionary(&dict_value)) {
+    return android::binder::Status::fromServiceSpecificError(
+        error, android::String8{message.c_str()});
+  }
+  dict->reset(dict_value);
+  value.release();  // |dict| now owns the object.
+  return android::binder::Status::ok();
+}
+
+}  // namespace binder_utils
+}  // namespace weaved
diff --git a/common/binder_utils.h b/common/binder_utils.h
new file mode 100644
index 0000000..65b462d
--- /dev/null
+++ b/common/binder_utils.h
@@ -0,0 +1,63 @@
+// Copyright 2016 The Android Open Source Project
+//
+// 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.
+
+#ifndef COMMON_BINDER_UTILS_H_
+#define COMMON_BINDER_UTILS_H_
+
+#include <memory>
+#include <string>
+
+#include <base/values.h>
+#include <binder/Status.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <weave/error.h>
+#include <brillo/errors/error.h>
+
+namespace weaved {
+namespace binder_utils {
+
+// Converts the result of weave API call into a binder Status object.
+// If |success| is true, return binder::Status::ok(), otherwise the method
+// constructs a service-specific failure status with an error message obtained
+// from the |error| object.
+android::binder::Status ToStatus(bool success, weave::ErrorPtr* error);
+
+// Converts a binder status code to a Brillo error object. Returns true if the
+// status was isOk(), otherwise returns false and provides error information
+// in the |error| object.
+bool StatusToError(android::binder::Status status, brillo::ErrorPtr* error);
+
+// Converts binder's UTF16 string into a regular UTF8-encoded standard string.
+inline std::string ToString(const android::String16& value) {
+  return android::String8{value}.string();
+}
+
+// Converts regular UTF8-encoded standard string into a binder's UTF16 string.
+inline android::String16 ToString16(const std::string& value) {
+  return android::String16{value.c_str()};
+}
+
+// Serializes a dictionary to a string for transferring over binder.
+android::String16 ToString16(const base::Value& value);
+
+// De-serializes a dictionary from a binder string.
+android::binder::Status ParseDictionary(
+    const android::String16& json,
+    std::unique_ptr<base::DictionaryValue>* dict);
+
+}  // namespace binder_utils
+}  // namespace weaved
+
+#endif  // COMMON_BINDER_UTILS_H_
diff --git a/buffet/dbus_conversion.cc b/common/data_conversion.cc
similarity index 88%
rename from buffet/dbus_conversion.cc
rename to common/data_conversion.cc
index 13f2c87..fd20ad4 100644
--- a/buffet/dbus_conversion.cc
+++ b/common/data_conversion.cc
@@ -12,15 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "buffet/dbus_conversion.h"
+#include "common/data_conversion.h"
 
-#include <set>
 #include <string>
 #include <vector>
 
 #include <brillo/type_name_undecorate.h>
 
-namespace buffet {
+namespace weaved {
 
 namespace {
 
@@ -54,7 +53,7 @@
   for (const base::Value* v : list) {
     const base::DictionaryValue* dict = nullptr;
     CHECK(v->GetAsDictionary(&dict));
-    result.push_back(DictionaryToDBusVariantDictionary(*dict));
+    result.push_back(details::DictionaryValueToVariantDictionary(*dict));
   }
   return result;
 }
@@ -87,7 +86,7 @@
     case base::Value::TYPE_DICTIONARY: {
       const base::DictionaryValue* dict = nullptr;
       CHECK(json.GetAsDictionary(&dict));
-      prop_value = DictionaryToDBusVariantDictionary(*dict);
+      prop_value = details::DictionaryValueToVariantDictionary(*dict);
       break;
     }
     case base::Value::TYPE_LIST: {
@@ -144,10 +143,13 @@
   return std::unique_ptr<base::Value>{new base::FundamentalValue{value}};
 }
 
-template <>
-std::unique_ptr<base::Value> CreateValue<std::string>(
-    const std::string& value,
-    brillo::ErrorPtr* error) {
+std::unique_ptr<base::Value> CreateValue(const std::string& value,
+                                         brillo::ErrorPtr* error) {
+  return std::unique_ptr<base::Value>{new base::StringValue{value}};
+}
+
+std::unique_ptr<base::Value> CreateValue(const char* value,
+                                         brillo::ErrorPtr* error) {
   return std::unique_ptr<base::Value>{new base::StringValue{value}};
 }
 
@@ -155,7 +157,7 @@
 std::unique_ptr<base::Value> CreateValue<brillo::VariantDictionary>(
     const brillo::VariantDictionary& value,
     brillo::ErrorPtr* error) {
-  return DictionaryFromDBusVariantDictionary(value, error);
+  return details::VariantDictionaryToDictionaryValue(value, error);
 }
 
 template <typename T>
@@ -209,6 +211,9 @@
   if (!TryCreateValue<std::string>(any, &result, error) || result)
     return result;
 
+  if (any.IsTypeCompatible<const char*>())
+    return CreateValue(any.Get<const char*>(), error);
+
   if (!TryCreateValue<brillo::VariantDictionary>(any, &result, error) ||
       result) {
     return result;
@@ -227,8 +232,9 @@
 
 }  // namespace
 
-// TODO(vitalybuka): Use in buffet_client.
-brillo::VariantDictionary DictionaryToDBusVariantDictionary(
+namespace details {
+
+brillo::VariantDictionary DictionaryValueToVariantDictionary(
     const base::DictionaryValue& object) {
   brillo::VariantDictionary result;
 
@@ -238,7 +244,7 @@
   return result;
 }
 
-std::unique_ptr<base::DictionaryValue> DictionaryFromDBusVariantDictionary(
+std::unique_ptr<base::DictionaryValue> VariantDictionaryToDictionaryValue(
     const brillo::VariantDictionary& object,
     brillo::ErrorPtr* error) {
   std::unique_ptr<base::DictionaryValue> result{new base::DictionaryValue};
@@ -253,4 +259,5 @@
   return result;
 }
 
-}  // namespace buffet
+}  // namespace details
+}  // namespace weaved
diff --git a/buffet/dbus_conversion.h b/common/data_conversion.h
similarity index 66%
rename from buffet/dbus_conversion.h
rename to common/data_conversion.h
index b71e823..accc520 100644
--- a/buffet/dbus_conversion.h
+++ b/common/data_conversion.h
@@ -12,25 +12,27 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef BUFFET_DBUS_CONVERSION_H_
-#define BUFFET_DBUS_CONVERSION_H_
+#ifndef COMMON_DATA_CONVERSION_H_
+#define COMMON_DATA_CONVERSION_H_
 
 #include <base/values.h>
 #include <brillo/any.h>
 #include <brillo/errors/error.h>
 #include <brillo/variant_dictionary.h>
 
-namespace buffet {
+namespace weaved {
+namespace details {
 
-// Converts DictionaryValue to D-Bus variant dictionary.
-brillo::VariantDictionary DictionaryToDBusVariantDictionary(
+// Converts DictionaryValue to variant dictionary.
+brillo::VariantDictionary DictionaryValueToVariantDictionary(
     const base::DictionaryValue& object);
 
-// Converts D-Bus variant dictionary to DictionaryValue.
-std::unique_ptr<base::DictionaryValue> DictionaryFromDBusVariantDictionary(
+// Converts variant dictionary to DictionaryValue.
+std::unique_ptr<base::DictionaryValue> VariantDictionaryToDictionaryValue(
     const brillo::VariantDictionary& object,
     brillo::ErrorPtr* error);
 
-}  // namespace buffet
+}  // namespace details
+}  // namespace weaved
 
-#endif  // BUFFET_DBUS_CONVERSION_H_
+#endif  // COMMON_DATA_CONVERSION_H_
diff --git a/buffet/dbus_conversion_unittest.cc b/common/data_conversion_unittest.cc
similarity index 69%
rename from buffet/dbus_conversion_unittest.cc
rename to common/data_conversion_unittest.cc
index 84db100..832fffb 100644
--- a/buffet/dbus_conversion_unittest.cc
+++ b/common/data_conversion_unittest.cc
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "buffet/dbus_conversion.h"
+#include "common/data_conversion.h"
 
 #include <limits>
 #include <memory>
@@ -26,7 +26,7 @@
 #include <gtest/gtest.h>
 #include <weave/test/unittest_utils.h>
 
-namespace buffet {
+namespace weaved {
 
 namespace {
 
@@ -35,14 +35,14 @@
 using weave::test::CreateDictionaryValue;
 using weave::test::IsEqualValue;
 
-brillo::VariantDictionary ToDBus(const base::DictionaryValue& object) {
-  return DictionaryToDBusVariantDictionary(object);
+brillo::VariantDictionary ToVariant(const base::DictionaryValue& object) {
+  return details::DictionaryValueToVariantDictionary(object);
 }
 
-std::unique_ptr<base::DictionaryValue> FromDBus(
+std::unique_ptr<base::DictionaryValue> FromVariant(
     const brillo::VariantDictionary& object) {
   brillo::ErrorPtr error;
-  auto result = DictionaryFromDBusVariantDictionary(object, &error);
+  auto result = details::VariantDictionaryToDictionaryValue(object, &error);
   EXPECT_TRUE(result || error);
   return result;
 }
@@ -133,64 +133,67 @@
 
 TEST(DBusConversionTest, DictionaryToDBusVariantDictionary) {
   EXPECT_EQ((VariantDictionary{{"bool", true}}),
-            ToDBus(*CreateDictionaryValue("{'bool': true}")));
+            ToVariant(*CreateDictionaryValue("{'bool': true}")));
   EXPECT_EQ((VariantDictionary{{"int", 5}}),
-            ToDBus(*CreateDictionaryValue("{'int': 5}")));
+            ToVariant(*CreateDictionaryValue("{'int': 5}")));
   EXPECT_EQ((VariantDictionary{{"double", 6.7}}),
-            ToDBus(*CreateDictionaryValue("{'double': 6.7}")));
+            ToVariant(*CreateDictionaryValue("{'double': 6.7}")));
   EXPECT_EQ((VariantDictionary{{"string", std::string{"abc"}}}),
-            ToDBus(*CreateDictionaryValue("{'string': 'abc'}")));
+            ToVariant(*CreateDictionaryValue("{'string': 'abc'}")));
   EXPECT_EQ((VariantDictionary{{"object", VariantDictionary{{"bool", true}}}}),
-            ToDBus(*CreateDictionaryValue("{'object': {'bool': true}}")));
+            ToVariant(*CreateDictionaryValue("{'object': {'bool': true}}")));
   EXPECT_EQ((VariantDictionary{{"emptyList", std::vector<Any>{}}}),
-            ToDBus(*CreateDictionaryValue("{'emptyList': []}")));
+            ToVariant(*CreateDictionaryValue("{'emptyList': []}")));
   EXPECT_EQ((VariantDictionary{{"intList", std::vector<int>{5}}}),
-            ToDBus(*CreateDictionaryValue("{'intList': [5]}")));
+            ToVariant(*CreateDictionaryValue("{'intList': [5]}")));
   EXPECT_EQ((VariantDictionary{
                 {"intListList", std::vector<Any>{std::vector<int>{5},
                                                  std::vector<int>{6, 7}}}}),
-            ToDBus(*CreateDictionaryValue("{'intListList': [[5], [6, 7]]}")));
+            ToVariant(*CreateDictionaryValue(
+                "{'intListList': [[5], [6, 7]]}")));
   EXPECT_EQ((VariantDictionary{{"objList",
                                 std::vector<VariantDictionary>{
                                     {{"string", std::string{"abc"}}}}}}),
-            ToDBus(*CreateDictionaryValue("{'objList': [{'string': 'abc'}]}")));
+            ToVariant(*CreateDictionaryValue(
+                "{'objList': [{'string': 'abc'}]}")));
 }
 
-TEST(DBusConversionTest, DictionaryFromDBusVariantDictionary) {
-  EXPECT_JSON_EQ("{'bool': true}", *FromDBus({{"bool", true}}));
-  EXPECT_JSON_EQ("{'int': 5}", *FromDBus({{"int", 5}}));
-  EXPECT_JSON_EQ("{'double': 6.7}", *FromDBus({{"double", 6.7}}));
+TEST(DBusConversionTest, VariantDictionaryToDictionaryValue) {
+  EXPECT_JSON_EQ("{'bool': true}", *FromVariant({{"bool", true}}));
+  EXPECT_JSON_EQ("{'int': 5}", *FromVariant({{"int", 5}}));
+  EXPECT_JSON_EQ("{'double': 6.7}", *FromVariant({{"double", 6.7}}));
   EXPECT_JSON_EQ("{'string': 'abc'}",
-                 *FromDBus({{"string", std::string{"abc"}}}));
+                 *FromVariant({{"string", std::string{"abc"}}}));
   EXPECT_JSON_EQ("{'object': {'bool': true}}",
-                 *FromDBus({{"object", VariantDictionary{{"bool", true}}}}));
+                 *FromVariant({{"object", VariantDictionary{{"bool", true}}}}));
   EXPECT_JSON_EQ("{'emptyList': []}",
-                 *FromDBus({{"emptyList", std::vector<bool>{}}}));
+                 *FromVariant({{"emptyList", std::vector<bool>{}}}));
   EXPECT_JSON_EQ("{'intList': [5]}",
-                 *FromDBus({{"intList", std::vector<int>{5}}}));
+                 *FromVariant({{"intList", std::vector<int>{5}}}));
   EXPECT_JSON_EQ(
       "{'intListList': [[5], [6, 7]]}",
-      *FromDBus({{"intListList", std::vector<Any>{std::vector<int>{5},
-                                                  std::vector<int>{6, 7}}}}));
+      *FromVariant({{"intListList",
+                   std::vector<Any>{std::vector<int>{5},
+                                    std::vector<int>{6, 7}}}}));
   EXPECT_JSON_EQ(
       "{'objList': [{'string': 'abc'}]}",
-      *FromDBus({{"objList", std::vector<VariantDictionary>{
-                                 {{"string", std::string{"abc"}}}}}}));
-  EXPECT_JSON_EQ("{'int': 5}", *FromDBus({{"int", Any{Any{5}}}}));
+      *FromVariant({{"objList", std::vector<VariantDictionary>{
+                                    {{"string", std::string{"abc"}}}}}}));
+  EXPECT_JSON_EQ("{'int': 5}", *FromVariant({{"int", Any{Any{5}}}}));
 }
 
-TEST(DBusConversionTest, DictionaryFromDBusVariantDictionary_Errors) {
-  EXPECT_FALSE(FromDBus({{"cString", "abc"}}));
-  EXPECT_FALSE(FromDBus({{"float", 1.0f}}));
-  EXPECT_FALSE(FromDBus({{"listList", std::vector<std::vector<int>>{}}}));
-  EXPECT_FALSE(FromDBus({{"any", Any{}}}));
-  EXPECT_FALSE(FromDBus({{"null", nullptr}}));
+TEST(DBusConversionTest, VariantDictionaryToDictionaryValueErrors) {
+  EXPECT_FALSE(FromVariant({{"cString", "abc"}}));
+  EXPECT_FALSE(FromVariant({{"float", 1.0f}}));
+  EXPECT_FALSE(FromVariant({{"listList", std::vector<std::vector<int>>{}}}));
+  EXPECT_FALSE(FromVariant({{"any", Any{}}}));
+  EXPECT_FALSE(FromVariant({{"null", nullptr}}));
 }
 
 TEST(DBusConversionTest, DBusRandomDictionaryConversion) {
   auto dict = CreateRandomDictionary(10000);
-  auto varian_dict = ToDBus(*dict);
-  auto dict_restored = FromDBus(varian_dict);
+  auto varian_dict = ToVariant(*dict);
+  auto dict_restored = FromVariant(varian_dict);
   EXPECT_PRED2(IsEqualValue, *dict, *dict_restored);
 }
 
diff --git a/libweaved/README.md b/libweaved/README.md
new file mode 100644
index 0000000..efc564b
--- /dev/null
+++ b/libweaved/README.md
@@ -0,0 +1,76 @@
+For system daemons which need to interface with the weave daemon (weaved), these
+daemons will need to link to **libweaved**.
+
+The `weaved::Service` class is an entry point into weave daemon interface.
+This class maintains an IPC connection to the daemon and allows clients to
+register weave command handlers and update the device state they are
+responsible for.
+
+In order to create an instance of `Service`, call asynchronous
+`Service::Connect` static method. This method initiates a connection to weaved
+and once established invokes the provided `callback`. When the callback is
+invoked, the connection to the weave daemon is available and the client should
+create their component, register command handlers and update the state.
+If connection is lost (e.g. the weave daemon exist), the provided weak
+pointer to the `Service` object becomes invalidated. As soon as weaved is
+restarted and the connection is restored, the `callback` is invoked again and
+the client can re-register command handlers, update the state again.
+
+A simple client daemon that works with weaved could be as follows:
+
+```
+class Daemon final : public brillo::Daemon {
+ public:
+  Daemon() = default;
+
+ protected:
+  int OnInit() override;
+
+ private:
+  void OnConnected(const std::weak_ptr<weaved::Service>& service);
+  void OnCommand1(std::unique_ptr<weaved::Command> command);
+  void UpdateDeviceState();
+
+  std::unique_ptr<weaved::Service::Token> weave_service_token_;
+  std::weak_ptr<weaved::Service> weave_service_;
+  brillo::BinderWatcher binder_watcher_;
+  base::WeakPtrFactory<Daemon> weak_ptr_factory_{this};
+  DISALLOW_COPY_AND_ASSIGN(Daemon);
+};
+
+int Daemon::OnInit() {
+  android::BinderWrapper::Create();
+  if (!binder_watcher_.Init())
+    return EX_OSERR;
+
+  weave_service_token_ = weaved::Service::Connect(
+      brillo::MessageLoop::current(),
+      base::Bind(&Daemon::OnConnected, weak_ptr_factory_.GetWeakPtr()));
+  return brillo::Daemon::OnInit();
+}
+
+void Daemon::OnConnected(const std::weak_ptr<weaved::Service>& service) {
+  weave_service_ = service;
+  auto weave_service = weave_service_.lock();
+  if (!weave_service)
+    return;
+
+  weave_service->AddComponent("myComponent", {"_myTrait"}, nullptr);
+  weave_service->AddCommandHandler(
+      "myComponent", "_myTrait.command1",
+      base::Bind(&Daemon::OnCommand1, base::Unretained(this)));
+  UpdateDeviceState();
+}
+
+void Daemon::UpdateDeviceState() {
+  auto weave_service = weave_service_.lock();
+  if (!weave_service)
+    return;
+
+  brillo::VariantDictionary state_change{
+    {"_myTrait.state1", 12},
+    {"_myTrait.state2", std::string{"foo"}},
+  };
+  weave_service->SetStateProperties("myComponent", state_change, nullptr);
+}
+```
\ No newline at end of file
diff --git a/libweaved/command.cc b/libweaved/command.cc
index caee8b0..9950673 100644
--- a/libweaved/command.cc
+++ b/libweaved/command.cc
@@ -1,42 +1,64 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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.
- */
+// Copyright 2015 The Android Open Source Project
+//
+// 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 "command.h"
+#include "libweaved/command.h"
 
-#include "buffet/dbus-proxies.h"
+#include "android/weave/IWeaveCommand.h"
+#include "common/binder_utils.h"
+#include "common/data_conversion.h"
+
+using weaved::binder_utils::ParseDictionary;
+using weaved::binder_utils::ToString;
+using weaved::binder_utils::ToString16;
+using weaved::binder_utils::StatusToError;
 
 namespace weaved {
 
-Command::Command(com::android::Weave::CommandProxyInterface* proxy)
-    : proxy_{proxy} {}
+Command::Command(const android::sp<android::weave::IWeaveCommand>& proxy)
+    : binder_proxy_{proxy} {}
 
-const std::string& Command::GetID() const {
-  return proxy_->id();
+Command::~Command() {}
+
+std::string Command::GetID() const {
+  std::string id;
+  android::String16 id16;
+  if (binder_proxy_->getId(&id16).isOk())
+    id.assign(ToString(id16));
+  return id;
 }
 
-const std::string& Command::GetName() const {
-  return proxy_->name();
+std::string Command::GetName() const {
+  std::string name;
+  android::String16 name16;
+  if (binder_proxy_->getId(&name16).isOk())
+    name.assign(ToString(name16));
+  return name;
 }
 
-const std::string& Command::GetComponent() const {
-  return proxy_->component();
+std::string Command::GetComponent() const {
+  std::string component;
+  android::String16 component16;
+  if (binder_proxy_->getId(&component16).isOk())
+    component.assign(ToString(component16));
+  return component;
 }
 
 Command::State Command::GetState() const {
-  std::string state = proxy_->state();
+  std::string state;
+  android::String16 state16;
+  if (binder_proxy_->getState(&state16).isOk())
+    state.assign(ToString(state16));
   if (state == "queued")
     return Command::State::kQueued;
   else if (state == "inProgress")
@@ -58,7 +80,10 @@
 }
 
 Command::Origin Command::GetOrigin() const {
-  std::string origin = proxy_->origin();
+  std::string origin;
+  android::String16 origin16;
+  if (binder_proxy_->getState(&origin16).isOk())
+    origin.assign(ToString(origin16));
   if (origin == "local")
     return Command::Origin::kLocal;
   else if (origin == "cloud")
@@ -67,28 +92,41 @@
   return Command::Origin::kLocal;
 }
 
-const brillo::VariantDictionary& Command::GetParameters() const {
-  return proxy_->parameters();
+brillo::VariantDictionary Command::GetParameters() const {
+  brillo::VariantDictionary params;
+  android::String16 params_string16;
+  if (binder_proxy_->getParameters(&params_string16).isOk()) {
+    std::unique_ptr<base::DictionaryValue> dict;
+    if (ParseDictionary(params_string16, &dict).isOk())
+      params = details::DictionaryValueToVariantDictionary(*dict);
+  }
+  return params;
 }
 
 bool Command::SetProgress(const brillo::VariantDictionary& progress,
                           brillo::ErrorPtr* error) {
-  return proxy_->SetProgress(progress, error);
+  auto dict = details::VariantDictionaryToDictionaryValue(progress, error);
+  return dict && StatusToError(binder_proxy_->setProgress(ToString16(*dict)),
+                               error);
 }
 
 bool Command::Complete(const brillo::VariantDictionary& results,
                        brillo::ErrorPtr* error) {
-  return proxy_->Complete(results, error);
+  auto dict = details::VariantDictionaryToDictionaryValue(results, error);
+  return dict && StatusToError(binder_proxy_->complete(ToString16(*dict)),
+                               error);
 }
 
 bool Command::Abort(const std::string& error_code,
                     const std::string& error_message,
                     brillo::ErrorPtr* error) {
-  return proxy_->Abort(error_code, error_message, error);
+  return StatusToError(binder_proxy_->abort(ToString16(error_code),
+                                            ToString16(error_message)),
+                       error);
 }
 
 bool Command::Cancel(brillo::ErrorPtr* error) {
-  return proxy_->Cancel(error);
+  return StatusToError(binder_proxy_->cancel(), error);
 }
 
 }  // namespace weave
diff --git a/libweaved/command.h b/libweaved/command.h
index a8332e5..2b69266 100644
--- a/libweaved/command.h
+++ b/libweaved/command.h
@@ -1,18 +1,16 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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.
- */
+// Copyright 2015 The Android Open Source Project
+//
+// 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.
 
 #ifndef LIBWEAVED_COMMAND_H_
 #define LIBWEAVED_COMMAND_H_
@@ -23,19 +21,17 @@
 #include <brillo/errors/error.h>
 #include <brillo/variant_dictionary.h>
 #include <libweaved/export.h>
+#include <utils/StrongPointer.h>
 
-namespace com {
 namespace android {
-namespace Weave {
-class CommandProxyInterface;
-}  // namespace Weave
+namespace weave {
+class IWeaveCommand;
+}  // namespace weave
 }  // namespace android
-}  // namespace com
-
 
 namespace weaved {
 
-class Device;
+class ServiceImpl;
 
 namespace detail {
 
@@ -76,14 +72,16 @@
 
   enum class Origin { kLocal, kCloud };
 
+  ~Command();
+
   // Returns the full command ID.
-  const std::string& GetID() const;
+  std::string GetID() const;
 
   // Returns the full name of the command.
-  const std::string& GetName() const;
+  std::string GetName() const;
 
   // Returns the name of the component this command was sent to.
-  const std::string& GetComponent() const;
+  std::string GetComponent() const;
 
   // Returns the command state.
   Command::State GetState() const;
@@ -92,7 +90,7 @@
   Command::Origin GetOrigin() const;
 
   // Returns the command parameters.
-  const brillo::VariantDictionary& GetParameters() const;
+  brillo::VariantDictionary GetParameters() const;
 
   // Helper function to get a command parameter of particular type T from the
   // command parameter list. Returns default value for type T (e.g. 0 for int or
@@ -130,11 +128,11 @@
   bool Cancel(brillo::ErrorPtr* error);
 
  protected:
-  Command(com::android::Weave::CommandProxyInterface* proxy);
+  explicit Command(const android::sp<android::weave::IWeaveCommand>& proxy);
 
  private:
-  friend class Device;
-  com::android::Weave::CommandProxyInterface* proxy_{nullptr};
+  friend class ServiceImpl;
+  android::sp<android::weave::IWeaveCommand> binder_proxy_;
 
   DISALLOW_COPY_AND_ASSIGN(Command);
 };
diff --git a/libweaved/device.cc b/libweaved/device.cc
deleted file mode 100644
index 5f396a7..0000000
--- a/libweaved/device.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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 "device.h"
-
-#include "buffet/dbus-proxies.h"
-
-using com::android::Weave::CommandProxyInterface;
-using com::android::Weave::ManagerProxyInterface;
-
-namespace weaved {
-
-Device::Device(const scoped_refptr<dbus::Bus>& bus,
-               const base::Closure& state_required_callback)
-    : bus_{bus}, state_required_callback_{state_required_callback} {
-  weaved_object_mgr_.reset(new com::android::Weave::ObjectManagerProxy{bus_});
-  weaved_object_mgr_->SetCommandAddedCallback(
-      base::Bind(&Device::OnCommandAdded, base::Unretained(this)));
-  weaved_object_mgr_->SetCommandRemovedCallback(
-      base::Bind(&Device::OnCommandRemoved, base::Unretained(this)));
-  weaved_object_mgr_->SetManagerAddedCallback(
-      base::Bind(&Device::OnManagerAdded, base::Unretained(this)));
-  weaved_object_mgr_->SetManagerRemovedCallback(
-      base::Bind(&Device::OnManagerRemoved, base::Unretained(this)));
-}
-
-Device::~Device() {
-}
-
-std::unique_ptr<Device> Device::CreateInstance(
-    const scoped_refptr<dbus::Bus>& bus,
-    const base::Closure& state_required_callback) {
-  return std::unique_ptr<Device>{new Device{bus, state_required_callback}};
-}
-
-void Device::AddComponent(const std::string& component,
-                          const std::vector<std::string>& traits) {
-  ComponentEntry entry;
-  entry.component = component;
-  entry.traits = traits;
-  components_.push_back(std::move(entry));
-  if (proxy_)
-    proxy_->AddComponent(component, traits, nullptr);
-}
-
-void Device::AddCommandHandler(const std::string& component,
-                               const std::string& command_name,
-                               const CommandHandlerCallback& callback) {
-  for (const auto& entry : command_handlers_) {
-    if (entry.command_name != command_name)
-      continue;
-    // The command names are the same, make sure we have different components.
-    // This means that both component names are not empty and are different.
-    CHECK(!component.empty() && !entry.component.empty() &&
-          component != entry.component)
-        << "Handler for " << component << ":" << command_name << " already set";
-  }
-  CommandHandlerEntry entry;
-  entry.component = component;
-  entry.command_name = command_name;
-  entry.callback = callback;
-
-  command_handlers_.push_back(std::move(entry));
-
-  // If there are any commands already received, call the handler immediately.
-  for (auto& pair : command_map_) {
-    if (pair.first->name() == command_name &&
-        (component.empty() || pair.first->component() == component)) {
-      if (!pair.second)
-        pair.second.reset(new Command{pair.first});
-      callback.Run(pair.second);
-    }
-  }
-}
-
-bool Device::SetStateProperties(const std::string& component,
-                                const brillo::VariantDictionary& dict,
-                                brillo::ErrorPtr* error) {
-  if (proxy_)
-    return proxy_->UpdateState(component, dict, error);
-
-  brillo::Error::AddTo(error, FROM_HERE, "weaved", "service_unavailable",
-                       "Process 'weaved' is unreachable");
-  return false;
-}
-
-bool Device::SetStateProperty(const std::string& component,
-                              const std::string& name,
-                              const brillo::Any& value,
-                              brillo::ErrorPtr* error) {
-  return SetStateProperties(component, brillo::VariantDictionary{{name, value}},
-                            error);
-}
-
-void Device::AddCommandHandler(const std::string& command_name,
-                               const CommandHandlerCallback& callback) {
-  AddCommandHandler("", command_name, callback);
-}
-
-bool Device::SetStateProperties(const brillo::VariantDictionary& dict,
-                                brillo::ErrorPtr* error) {
-  return SetStateProperties("", dict, error);
-}
-
-bool Device::SetStateProperty(const std::string& name,
-                              const brillo::Any& value,
-                              brillo::ErrorPtr* error) {
-  return SetStateProperty("", name, value, error);
-}
-
-void Device::OnCommandAdded(CommandProxyInterface* proxy) {
-  std::shared_ptr<Command>& command = command_map_[proxy];
-  const Device::CommandHandlerCallback* callback = FindHandlerForCommand(proxy);
-  if (!callback)
-    return;
-  if (!command)
-    command.reset(new Command{proxy});
-  callback->Run(command);
-}
-
-void Device::OnCommandRemoved(const dbus::ObjectPath& object_path) {
-  auto proxy = weaved_object_mgr_->GetCommandProxy(object_path);
-  if (!proxy)
-    return;
-  command_map_.erase(proxy);
-}
-
-void Device::OnManagerAdded(ManagerProxyInterface* proxy) {
-  proxy_ = proxy;
-  for (const auto& entry : components_)
-    proxy_->AddComponent(entry.component, entry.traits, nullptr);
-  state_required_callback_.Run();
-}
-
-void Device::OnManagerRemoved(const dbus::ObjectPath& object_path) {
-  proxy_ = nullptr;
-}
-
-const Device::CommandHandlerCallback* Device::FindHandlerForCommand(
-    com::android::Weave::CommandProxyInterface* proxy) const {
-  for (const auto& entry : command_handlers_) {
-    if (proxy->name() == entry.command_name &&
-        (entry.component.empty() || proxy->component() == entry.component)) {
-      return &entry.callback;
-    }
-  }
-  return nullptr;
-}
-
-
-}  // namespace weave
diff --git a/libweaved/device.h b/libweaved/device.h
deleted file mode 100644
index 376b656..0000000
--- a/libweaved/device.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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.
- */
-
-
-#ifndef LIBWEAVED_DEVICE_H_
-#define LIBWEAVED_DEVICE_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/callback.h>
-#include <base/macros.h>
-#include <base/memory/ref_counted.h>
-#include <brillo/any.h>
-#include <brillo/errors/error.h>
-#include <brillo/variant_dictionary.h>
-#include <libweaved/command.h>
-#include <libweaved/export.h>
-
-namespace com {
-namespace android {
-namespace Weave {
-class CommandProxyInterface;
-class ManagerProxyInterface;
-class ObjectManagerProxy;
-}  // namespace Weave
-}  // namespace android
-}  // namespace com
-
-namespace dbus {
-class Bus;
-class ObjectPath;
-}  // namespace dbus
-
-namespace weaved {
-
-class LIBWEAVED_EXPORT Device final {
- public:
-  ~Device();
-
-  static std::unique_ptr<Device> CreateInstance(
-      const scoped_refptr<dbus::Bus>& bus,
-      const base::Closure& state_required_callback);
-
-  // Callback type for AddCommandHandler.
-  using CommandHandlerCallback =
-      base::Callback<void(const std::weak_ptr<Command>& command)>;
-
-  void AddComponent(const std::string& component,
-                    const std::vector<std::string>& traits);
-
-  // Sets handler for new commands added to the queue.
-  // |command_name| is the full command name of the command to handle. e.g.
-  // "base.reboot". Each command can have no more than one handler.
-  void AddCommandHandler(const std::string& component,
-                         const std::string& command_name,
-                         const CommandHandlerCallback& callback);
-
-  bool SetStateProperties(const std::string& component,
-                          const brillo::VariantDictionary& dict,
-                          brillo::ErrorPtr* error);
-
-  // Sets value of the single property.
-  // |name| is full property name, including package name. e.g. "base.network".
-  bool SetStateProperty(const std::string& component,
-                        const std::string& name,
-                        const brillo::Any& value,
-                        brillo::ErrorPtr* error);
-
-  // Sets handler for new commands added to the queue.
-  // |command_name| is the full command name of the command to handle. e.g.
-  // "base.reboot". Each command can have no more than one handler.
-  LIBWEAVED_DEPRECATED void AddCommandHandler(
-      const std::string& command_name,
-      const CommandHandlerCallback& callback);
-
-  LIBWEAVED_DEPRECATED bool SetStateProperties(
-      const brillo::VariantDictionary& dict,
-      brillo::ErrorPtr* error);
-
-  // Sets value of the single property.
-  // |name| is full property name, including package name. e.g. "base.network".
-  LIBWEAVED_DEPRECATED bool SetStateProperty(const std::string& name,
-                                             const brillo::Any& value,
-                                             brillo::ErrorPtr* error);
-
- private:
-  Device(const scoped_refptr<dbus::Bus>& bus,
-         const base::Closure& state_required_callback);
-
-  void OnCommandAdded(com::android::Weave::CommandProxyInterface* proxy);
-  void OnCommandRemoved(const dbus::ObjectPath& object_path);
-
-  void OnManagerAdded(com::android::Weave::ManagerProxyInterface* proxy);
-  void OnManagerRemoved(const dbus::ObjectPath& object_path);
-
-  const CommandHandlerCallback* FindHandlerForCommand(
-      com::android::Weave::CommandProxyInterface* proxy) const;
-
-  std::unique_ptr<com::android::Weave::ObjectManagerProxy> weaved_object_mgr_;
-  com::android::Weave::ManagerProxyInterface* proxy_{nullptr};
-
-  using CommandMap = std::map<com::android::Weave::CommandProxyInterface*,
-                              std::shared_ptr<Command>>;
-  CommandMap command_map_;
-
-  struct CommandHandlerEntry {
-    std::string component;
-    std::string command_name;
-    CommandHandlerCallback callback;
-  };
-  std::vector<CommandHandlerEntry> command_handlers_;
-
-  struct ComponentEntry {
-    std::string component;
-    std::vector<std::string> traits;
-  };
-  std::vector<ComponentEntry> components_;
-
-  scoped_refptr<dbus::Bus> bus_;
-  base::Closure state_required_callback_;
-
-
-  DISALLOW_COPY_AND_ASSIGN(Device);
-};
-
-}  // namespace weave
-
-#endif  // LIBWEAVE_INCLUDE_WEAVE_DEVICE_H_
diff --git a/libweaved/service.cc b/libweaved/service.cc
new file mode 100644
index 0000000..83a404d
--- /dev/null
+++ b/libweaved/service.cc
@@ -0,0 +1,400 @@
+// Copyright 2016 The Android Open Source Project
+//
+// 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 "libweaved/service.h"
+
+#include <algorithm>
+
+#include <base/bind.h>
+#include <base/memory/weak_ptr.h>
+#include <binderwrapper/binder_wrapper.h>
+#include <brillo/message_loops/message_loop.h>
+
+#include "android/weave/BnWeaveClient.h"
+#include "android/weave/IWeaveCommand.h"
+#include "android/weave/IWeaveService.h"
+#include "android/weave/IWeaveServiceManager.h"
+#include "common/binder_constants.h"
+#include "common/binder_utils.h"
+#include "common/data_conversion.h"
+
+using weaved::binder_utils::StatusToError;
+using weaved::binder_utils::ToString;
+using weaved::binder_utils::ToString16;
+
+// The semantic of weaved connection is a bit complicated and that's why we have
+// the numerous classes defined here.
+// When the client wants to connect to weaved they would call Service::Connect
+// and provide a callback to be invoked when the connection is fully established
+// and ready to be used.
+//
+// Service::Connect() creates an instance of ServiceImpl class and sets the only
+// strong pointer into ServiceSubscription class which is returned to the client
+// as std::unqiue_ptr<Service::Subscription>. This allows us to hide the actual
+// service object from the client until the connection is fully ready to be
+// used, and at the same time give the client an exclusive ownership of the
+// connection. They are free to destroy the Subscription and abort the
+// connection at any point.
+//
+// At the same time an asynchronous process to establish a connection to weaved
+// over binder is initiated. ServiceImpl periodically tries to get hold of
+// IWeaveServiceManager binder object from binder service manager. Once this
+// succeeds, we know that weaved is running. We create a callback binder object,
+// WeaveClient, which implements IWeaveClient binder interface and pass it to
+// weaved in IWeaveServiceManager::connect() method. The weaved daemon keeps the
+// list of all the clients registered with it for two reasons:
+//    1. It watches each client for death notifications and cleans up the
+//       resources added by the client (e.g. weave components) when the client
+//       dies.
+//    2. It notifies the client of weaved being ready to talk to (by calling
+//       onServiceConnected callback) and when new weave commands are available
+//       for the client (via onCommand callback).
+// When weaved is fully initialized (which can take some time after the daemon
+// physically starts up), it invokes IWeaveClient::onServiceConnection on each
+// client and passes a unique copy of IWeaveService to each of the client.
+// The clients will use its own IWeaveService interface to further interact with
+// weaved. This allows weaved to distinguish binder calls from each client and
+// maintain the track record of which client adds each resource.
+
+// Once IWeaveClient::onServiceConnection is called, we have a fully-established
+// service connection to weaved and we invoke the client callback provided in
+// the original call to Service::Connect() and pass the weak pointer to the
+// service as an argument.
+
+// In case a connection to weaved is lost, the ServiceImpl class will be deleted
+// and any weak pointers to it the client may have will be invalidated.
+// A new instance of ServiceImpl is created and the strong reference in
+// ServiceSubscription is replace to the new instance. A new re-connection cycle
+// is started as if the client just invoked Service::Connect() again on the new
+// instance of ServiceImpl.
+
+namespace weaved {
+
+namespace {
+// An implementation for service subscription. This object keeps a reference to
+// the actual instance of weaved service object. This is generally the only hard
+// reference to the shared pointer to the service object. The client receives
+// a weak pointer only.
+class ServiceSubscription : public Service::Subscription {
+ public:
+  ServiceSubscription() = default;
+  ~ServiceSubscription() override = default;
+
+  void SetService(const std::shared_ptr<Service>& service) {
+    service_ = service;
+  }
+
+ private:
+  std::shared_ptr<Service> service_;
+  DISALLOW_COPY_AND_ASSIGN(ServiceSubscription);
+};
+
+}  // anonymous namespace
+
+class ServiceImpl;
+
+// Each system process wishing to expose functionality via weave establishes a
+// connection to weaved via Binder. The communication channel is two-way.
+// The client obtains a reference to weaved's android::weave::IWeaveService from
+// the system service manager, and registers an instance of
+// android::weave::IWeaveClient with weaved via IWeaveService.
+// WeaveClient is an implementation of android::weave::IWeaveClient binder
+// interface. Apart from providing callback methods (such as onCommand), it is
+// used by weaved to track the life-time of this particular client. If the
+// client exits, weaved automatically cleans up resources added by this client.
+class WeaveClient : public android::weave::BnWeaveClient {
+ public:
+  explicit WeaveClient(const std::weak_ptr<ServiceImpl>& service);
+
+ private:
+  // Implementation for IWeaveClient interface.
+  // A notification that the service binder is successfully instantiated and
+  // weaved daemon is ready to process incoming request for component creation,
+  // device state updates and so on.
+  android::binder::Status onServiceConnected(
+      const android::sp<android::weave::IWeaveService>& service) override;
+
+  // A callback invoked when a new command for which a handler was registered
+  // is added to the command queue.
+  android::binder::Status onCommand(
+      const android::String16& componentName,
+      const android::String16& commandName,
+      const android::sp<android::weave::IWeaveCommand>& command) override;
+
+  std::weak_ptr<ServiceImpl> service_;
+
+  base::WeakPtrFactory<WeaveClient> weak_ptr_factory_{this};
+  DISALLOW_COPY_AND_ASSIGN(WeaveClient);
+};
+
+// ServiceImpl is a concrete implementation of weaved::Service interface.
+// This object is a wrapper around android::weave::IWeaveService binder
+// interface to weaved daemon.
+// This class is created as soon as Service::Connect() is called and it
+// initiates connection attempts to IWeaveService binder. Only when the
+// connection is successful and we receive callback notification from weaved
+// that the service is ready, we invoke the client-provided callback and pass
+// a weak pointer to Service fro the client to talk to weaved.
+class ServiceImpl : public std::enable_shared_from_this<ServiceImpl>,
+                    public Service {
+ public:
+  // A constructor. Client code never creates this instance directly, but rather
+  // uses Service::Connect which is responsible for creating a instance of this
+  // class.
+  ServiceImpl(android::BinderWrapper* binder_wrapper,
+              brillo::MessageLoop* message_loop,
+              ServiceSubscription* service_subscription,
+              const ConnectionCallback& connection_callback);
+  ~ServiceImpl() override;
+
+  // Service interface methods.
+  bool AddComponent(const std::string& component,
+                    const std::vector<std::string>& traits,
+                    brillo::ErrorPtr* error) override;
+  void AddCommandHandler(const std::string& component,
+                         const std::string& command_name,
+                         const CommandHandlerCallback& callback) override;
+  bool SetStateProperties(const std::string& component,
+                          const brillo::VariantDictionary& dict,
+                          brillo::ErrorPtr* error) override;
+  bool SetStateProperty(const std::string& component,
+                        const std::string& name,
+                        const brillo::Any& value,
+                        brillo::ErrorPtr* error) override;
+
+  // Helper method called from Service::Connect() to initiate binder connection
+  // to weaved. This message just posts a task to the message loop to invoke
+  // TryConnecting() method.
+  void BeginConnect();
+
+  // A callback method for WeaveClient::onServiceConnected().
+  void OnServiceConnected(
+      const android::sp<android::weave::IWeaveService>& service);
+
+  // A callback method for WeaveClient::onCommand().
+  void OnCommand(const std::string& component_name,
+                 const std::string& command_name,
+                 const android::sp<android::weave::IWeaveCommand>& command);
+
+ private:
+  // Connects to weaved daemon over binder if the service manager is available
+  // and weaved daemon itself is ready to accept connections. If not, schedules
+  // another retry after a delay (1 second).
+  void TryConnecting();
+
+  // A callback for weaved connection termination. When binder service manager
+  // notifies client of weaved binder object destruction (e.g. weaved quits),
+  // this callback is invoked and initiates re-connection process.
+  void OnWeaveServiceDisconnected();
+
+  android::BinderWrapper* binder_wrapper_;
+  brillo::MessageLoop* message_loop_;
+  ServiceSubscription* service_subscription_;
+  ConnectionCallback connection_callback_;
+  android::sp<android::weave::IWeaveService> weave_service_;
+
+  struct CommandHandlerEntry {
+    std::string component;
+    std::string command_name;
+    CommandHandlerCallback callback;
+  };
+  std::vector<CommandHandlerEntry> command_handlers_;
+
+  base::WeakPtrFactory<ServiceImpl> weak_ptr_factory_{this};
+  DISALLOW_COPY_AND_ASSIGN(ServiceImpl);
+};
+
+WeaveClient::WeaveClient(const std::weak_ptr<ServiceImpl>& service)
+    : service_{service} {}
+
+android::binder::Status WeaveClient::onServiceConnected(
+    const android::sp<android::weave::IWeaveService>& service) {
+  LOG(INFO) << "Weave service connection established successfully";
+  auto service_proxy = service_.lock();
+  if (service_proxy)
+    service_proxy->OnServiceConnected(service);
+  return android::binder::Status::ok();
+}
+
+android::binder::Status WeaveClient::onCommand(
+    const android::String16& componentName,
+    const android::String16& commandName,
+    const android::sp<android::weave::IWeaveCommand>& command) {
+  auto service_proxy = service_.lock();
+  if (service_proxy) {
+    service_proxy->OnCommand(ToString(componentName), ToString(commandName),
+                             command);
+  } else {
+    command->abort(android::String16{"service_unavailable"},
+                   android::String16{"Command handler is unavailable"});
+  }
+  return android::binder::Status::ok();
+}
+
+ServiceImpl::ServiceImpl(android::BinderWrapper* binder_wrapper,
+                         brillo::MessageLoop* message_loop,
+                         ServiceSubscription* service_subscription,
+                         const ConnectionCallback& connection_callback)
+    : binder_wrapper_{binder_wrapper},
+      message_loop_{message_loop},
+      service_subscription_{service_subscription},
+      connection_callback_{connection_callback} {
+}
+
+ServiceImpl::~ServiceImpl() {
+  if (weave_service_.get()) {
+    android::sp<android::IBinder> binder =
+        android::IInterface::asBinder(weave_service_);
+    binder_wrapper_->UnregisterForDeathNotifications(binder);
+  }
+}
+
+bool ServiceImpl::AddComponent(const std::string& component,
+                               const std::vector<std::string>& traits,
+                               brillo::ErrorPtr* error) {
+  CHECK(weave_service_.get());
+  std::vector<android::String16> trait_list;
+  auto to_string16 = [](const std::string& name) {
+    return android::String16{name.c_str()};
+  };
+  std::transform(traits.begin(), traits.end(), std::back_inserter(trait_list),
+                 to_string16);
+  return StatusToError(weave_service_->addComponent(to_string16(component),
+                                                    trait_list),
+                       error);
+}
+
+void ServiceImpl::AddCommandHandler(const std::string& component,
+                                    const std::string& command_name,
+                                    const CommandHandlerCallback& callback) {
+  CHECK(!component.empty() && !command_name.empty());
+  CHECK(weave_service_.get());
+
+  CommandHandlerEntry entry;
+  entry.component = component;
+  entry.command_name = command_name;
+  entry.callback = callback;
+  command_handlers_.push_back(std::move(entry));
+
+  auto status = weave_service_->registerCommandHandler(
+      android::String16{component.c_str()},
+      android::String16{command_name.c_str()});
+  CHECK(status.isOk());
+}
+
+bool ServiceImpl::SetStateProperties(const std::string& component,
+                                     const brillo::VariantDictionary& dict,
+                                     brillo::ErrorPtr* error) {
+  CHECK(!component.empty());
+  CHECK(weave_service_.get());
+  auto properties = details::VariantDictionaryToDictionaryValue(dict, error);
+  if (!properties)
+    return false;
+  return StatusToError(weave_service_->updateState(ToString16(component),
+                                                   ToString16(*properties)),
+                       error);
+}
+
+bool ServiceImpl::SetStateProperty(const std::string& component,
+                                   const std::string& name,
+                                   const brillo::Any& value,
+                                   brillo::ErrorPtr* error) {
+  return SetStateProperties(component, brillo::VariantDictionary{{name, value}},
+                            error);
+}
+
+void ServiceImpl::BeginConnect() {
+  message_loop_->PostTask(FROM_HERE,
+                          base::Bind(&ServiceImpl::TryConnecting,
+                                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ServiceImpl::OnServiceConnected(
+    const android::sp<android::weave::IWeaveService>& service) {
+  weave_service_ = service;
+  connection_callback_.Run(shared_from_this());
+  // Call this last in case the binder object is already gone and the death
+  // notification callback (OnWeaveServiceDisconnected) is invoked immediately.
+  // In this case, the instance of ServiceImpl will get destroyed before
+  // RegisterForDeathNotifications returns.
+  binder_wrapper_->RegisterForDeathNotifications(
+      android::IInterface::asBinder(service),
+      base::Bind(&ServiceImpl::OnWeaveServiceDisconnected,
+                 weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ServiceImpl::OnCommand(
+    const std::string& component_name,
+    const std::string& command_name,
+    const android::sp<android::weave::IWeaveCommand>& command) {
+  VLOG(2) << "Weave command received for component '" << component_name << "': "
+          << command_name;
+  for (const auto& entry : command_handlers_) {
+    if (entry.component == component_name &&
+        entry.command_name == command_name) {
+      std::unique_ptr<Command> command_instance{new Command{command}};
+      return entry.callback.Run(std::move(command_instance));
+    }
+  }
+  LOG(WARNING) << "Unexpected command notification. Command = " << command_name
+               << ", component = " << component_name;
+}
+
+void ServiceImpl::TryConnecting() {
+  LOG(INFO) << "Connecting to weave service over binder";
+  android::sp<android::IBinder> binder =
+      binder_wrapper_->GetService(weaved::binder::kWeaveServiceName);
+  if (!binder.get()) {
+    LOG(INFO) << "Weave service is not available yet. Will try again later";
+    message_loop_->PostDelayedTask(FROM_HERE,
+                                   base::Bind(&ServiceImpl::TryConnecting,
+                                              weak_ptr_factory_.GetWeakPtr()),
+                                   base::TimeDelta::FromSeconds(1));
+    return;
+  }
+
+  auto service_manager =
+      android::interface_cast<android::weave::IWeaveServiceManager>(binder);
+  android::sp<WeaveClient> weave_client = new WeaveClient{shared_from_this()};
+  service_manager->connect(weave_client);
+}
+
+void ServiceImpl::OnWeaveServiceDisconnected() {
+  weave_service_.clear();
+  // Need to create a new instance of service to invalidate existing weak
+  // pointers.
+  auto service = std::make_shared<ServiceImpl>(
+      binder_wrapper_, message_loop_, service_subscription_,
+      connection_callback_);
+  service->BeginConnect();
+  // The subscription object owns this instance.
+  // Calling SetService() will destroy |this|.
+  service_subscription_->SetService(service);
+  // Do not call any methods or use resources of ServiceImpl after this point
+  // because the object is destroyed now.
+}
+
+std::unique_ptr<Service::Subscription> Service::Connect(
+    brillo::MessageLoop* message_loop,
+    const ConnectionCallback& callback) {
+  std::unique_ptr<ServiceSubscription> subscription{new ServiceSubscription};
+  auto service = std::make_shared<ServiceImpl>(
+      android::BinderWrapper::GetOrCreateInstance(), message_loop,
+      subscription.get(), callback);
+  subscription->SetService(service);
+  service->BeginConnect();
+  return std::move(subscription);
+}
+
+}  // namespace weaved
diff --git a/libweaved/service.h b/libweaved/service.h
new file mode 100644
index 0000000..7ae6824
--- /dev/null
+++ b/libweaved/service.h
@@ -0,0 +1,122 @@
+// Copyright 2016 The Android Open Source Project
+//
+// 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.
+
+#ifndef LIBWEAVED_SERVICE_H_
+#define LIBWEAVED_SERVICE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <base/callback.h>
+#include <base/compiler_specific.h>
+#include <base/macros.h>
+#include <brillo/errors/error.h>
+#include <libweaved/command.h>
+#include <libweaved/export.h>
+
+namespace brillo {
+class MessageLoop;
+}  // namespace brillo
+
+namespace weaved {
+
+// A weaved service is an abstract interface representing an instance of weave
+// services for a particular client daemon. Apart from providing an API to
+// weaved process, it manages resources specific for an instance of the client.
+// For example, when a client exits, it removes any resources (e.g. components)
+// that were added by this client from the weaved's component tree.
+class LIBWEAVED_EXPORT Service {
+ public:
+  // Callback type for AddCommandHandler.
+  using CommandHandlerCallback =
+      base::Callback<void(std::unique_ptr<Command> command)>;
+
+  Service() = default;
+  virtual ~Service() = default;
+
+  // Adds a new component instance to device.
+  // |component| is a component name being added.
+  // |traits| is a list of trait names this component supports.
+  virtual bool AddComponent(const std::string& component,
+                            const std::vector<std::string>& traits,
+                            brillo::ErrorPtr* error) = 0;
+
+  // Sets handler for new commands added to the queue for a given |component|.
+  // |command_name| is the full name of the command to handle, including the
+  // name of the trait, e.g. "base.reboot".
+  // Each command can have no more than one handler.
+  virtual void AddCommandHandler(const std::string& component,
+                                 const std::string& command_name,
+                                 const CommandHandlerCallback& callback) = 0;
+
+  // Sets a number of state properties for a given |component|.
+  // |dict| is a dictionary containing property-name/property-value pairs.
+  virtual bool SetStateProperties(const std::string& component,
+                                  const brillo::VariantDictionary& dict,
+                                  brillo::ErrorPtr* error) = 0;
+
+  // Sets value of the single property.
+  // |name| is full property name, including trait name. e.g. "base.network".
+  virtual bool SetStateProperty(const std::string& component,
+                                const std::string& name,
+                                const brillo::Any& value,
+                                brillo::ErrorPtr* error) = 0;
+
+  // Service creation functionality.
+  // Subscription is a base class for an object responsible for life-time
+  // management for the service. The service instance is kept alive for as long
+  // as the service connection is alive. See comments for Service::Connect for
+  // more details.
+  class Subscription {
+   public:
+    virtual ~Subscription() = default;
+
+   protected:
+    Subscription() = default;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(Subscription);
+  };
+
+  using ConnectionCallback =
+      base::Callback<void(const std::weak_ptr<Service>& service)>;
+
+  // Creates an instance of weaved service asynchronously. This not only creates
+  // the service class instance but also establishes an RPC connection to
+  // weaved daemon. Upon connection having been established, a |callback| is
+  // invoked and an instance of Service is passed to it as an argument.
+  // The service instance provided to the callback is a weak pointer to the
+  // actual service which may be destroyed at any time if RPC connection to
+  // weaved is lost. If this happens, a connection is re-established and the
+  // |callback| is called again with a new instance of the service.
+  // Therefore, if locking the |service| produces nullptr, this means that the
+  // service got disconnected, so no further action can be taken. Since the
+  // |callback| will be invoked with the new service instance when connection
+  // is re-established, it's a good idea to update the device state on each
+  // invocation of the callback (along with registering command handlers, etc).
+  // IMPORTANT: Keep the returned subscription object around for as long as the
+  // service is needed. As soon as the subscription is destroyed, the connection
+  // to weaved is terminated and the service instance is discarded.
+  static std::unique_ptr<Subscription> Connect(
+      brillo::MessageLoop* message_loop,
+      const ConnectionCallback& callback) WARN_UNUSED_RESULT;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Service);
+};
+
+}  // namespace weaved
+
+#endif  // LIBWEAVED_SERVICE_H_