aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk113
-rw-r--r--brillo/android/weave/IWeaveClient.aidl27
-rw-r--r--brillo/android/weave/IWeaveCommand.aidl35
-rw-r--r--brillo/android/weave/IWeaveService.aidl23
-rw-r--r--brillo/android/weave/IWeaveServiceManager.aidl41
-rw-r--r--brillo/android/weave/IWeaveServiceManagerNotificationListener.aidl36
-rw-r--r--buffet/binder_command_proxy.cc182
-rw-r--r--buffet/binder_command_proxy.h62
-rw-r--r--buffet/binder_command_proxy_unittest.cc163
-rw-r--r--buffet/binder_weave_service.cc90
-rw-r--r--buffet/binder_weave_service.h72
-rw-r--r--buffet/buffet.gyp162
-rw-r--r--buffet/dbus_bindings/com.android.Weave.Command.dbus-xml48
-rw-r--r--buffet/dbus_bindings/com.android.Weave.Manager.dbus-xml133
-rw-r--r--buffet/dbus_bindings/dbus-service-config.json7
-rw-r--r--buffet/dbus_command_dispatcher.cc54
-rw-r--r--buffet/dbus_command_dispatcher.h67
-rw-r--r--buffet/dbus_command_proxy.cc160
-rw-r--r--buffet/dbus_command_proxy.h69
-rw-r--r--buffet/dbus_command_proxy_unittest.cc189
-rw-r--r--buffet/dbus_constants.cc37
-rw-r--r--buffet/dbus_constants.h38
-rw-r--r--buffet/etc/dbus-1/com.android.Weave.conf21
-rw-r--r--buffet/etc/init/buffet.conf54
-rw-r--r--buffet/main.cc20
-rw-r--r--buffet/manager.cc344
-rw-r--r--buffet/manager.h103
-rw-r--r--common/binder_constants.cc23
-rw-r--r--common/binder_constants.h26
-rw-r--r--common/binder_utils.cc65
-rw-r--r--common/binder_utils.h63
-rw-r--r--common/data_conversion.cc (renamed from buffet/dbus_conversion.cc)35
-rw-r--r--common/data_conversion.h (renamed from buffet/dbus_conversion.h)20
-rw-r--r--common/data_conversion_unittest.cc (renamed from buffet/dbus_conversion_unittest.cc)75
-rw-r--r--libweaved/README.md76
-rw-r--r--libweaved/command.cc108
-rw-r--r--libweaved/command.h56
-rw-r--r--libweaved/device.cc164
-rw-r--r--libweaved/device.h144
-rw-r--r--libweaved/service.cc400
-rw-r--r--libweaved/service.h122
41 files changed, 2002 insertions, 1725 deletions
diff --git a/Android.mk b/Android.mk
index baf3bd5..10d7ba3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -30,7 +30,6 @@ buffetCommonCppFlags := \
buffetCommonCIncludes := \
$(LOCAL_PATH)/.. \
- $(LOCAL_PATH)/dbus-proxies \
external/cros/system_api \
external/gtest/include \
@@ -38,7 +37,10 @@ buffetSharedLibraries := \
libapmanager-client \
libavahi-common \
libavahi-client \
+ libbinder \
+ libbinderwrapper \
libbrillo \
+ libbrillo-binder \
libbrillo-dbus \
libbrillo-http \
libbrillo-stream \
@@ -47,6 +49,7 @@ buffetSharedLibraries := \
libcutils \
libdbus \
libshill-client \
+ libutils \
libweave \
libwebserv \
@@ -58,10 +61,38 @@ buffetSharedLibraries += \
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_CFLAGS := $(buffetCommonCFlags)
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 @@ LOCAL_SRC_FILES := \
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 @@ endif
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_CPPFLAGS := $(buffetCommonCppFlags)
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 @@ LOCAL_SRC_FILES := \
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_CFLAGS := $(buffetCommonCFlags)
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 @@ LOCAL_SHARED_LIBRARIES := \
$(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 @@ namespace dbus_constants {
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 @@ extern const char kServiceName[];
// 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 @@ class Daemon final : public DBusServiceDaemon {
: 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 @@ class Daemon final : public DBusServiceDaemon {
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 @@ void LoadStateDefaults(const BuffetConfig::Options& options,
}
}
+// 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 @@ class Manager::TaskRunner : public weave::provider::TaskRunner {
};
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 @@ void Manager::RestartWeave(AsyncEventSequencer* sequencer) {
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 @@ void Manager::RestartWeave(AsyncEventSequencer* sequencer) {
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 @@ void Manager::CreateDevice() {
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 @@ void Manager::CreateDevice() {
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 @@ void Manager::Stop() {
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 @@ class Manager final : public com::android::Weave::ManagerInterface {
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 @@ class Manager final : public com::android::Weave::ManagerInterface {
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 @@ class Manager final : public com::android::Weave::ManagerInterface {
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
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 @@ brillo::Any DictListToAny(const base::ListValue& list) {
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 @@ brillo::Any ValueToAny(const base::Value& json) {
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 @@ std::unique_ptr<base::Value> CreateValue(const T& value,
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 @@ template <>
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 @@ std::unique_ptr<base::Value> CreateValue<brillo::Any>(
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 @@ std::unique_ptr<base::Value> CreateValue<brillo::Any>(
} // 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 @@ brillo::VariantDictionary DictionaryToDBusVariantDictionary(
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 @@ std::unique_ptr<base::DictionaryValue> DictionaryFromDBusVariantDictionary(
return result;
}
-} // namespace buffet
+} // namespace details
+} // namespace weaved
diff --git a/buffet/dbus_conversion.h b/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
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 brillo::VariantDictionary;
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 @@ std::unique_ptr<base::Value> CreateRandomValue(int children) {
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.
- */
-
-#include "command.h"
-
-#include "buffet/dbus-proxies.h"
+// 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 "libweaved/command.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} {}
+
+Command::~Command() {}
-const std::string& Command::GetID() const {
- return proxy_->id();
+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::State Command::GetState() const {
}
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 @@ Command::Origin Command::GetOrigin() const {
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 @@ class LIBWEAVED_EXPORT Command final {
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 @@ class LIBWEAVED_EXPORT Command final {
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 @@ class LIBWEAVED_EXPORT Command final {
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_