buffet: Add device state D-Bus property

This is part of Privet protocol, device should export state over HTTP.
Other daemons may also need this information.
In particular privetd may read availability of local discovery form
there.

BUG=brillo:427
TEST=`FEATURES=test emerge-gizmo buffet`

Change-Id: I2688a1e2f02e25952459badeeaf9dbd4ca84cf55
Reviewed-on: https://chromium-review.googlesource.com/273524
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
Tested-by: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/buffet/dbus_bindings/org.chromium.Buffet.Manager.xml b/buffet/dbus_bindings/org.chromium.Buffet.Manager.xml
index 73d3547..9a3b9c2 100644
--- a/buffet/dbus_bindings/org.chromium.Buffet.Manager.xml
+++ b/buffet/dbus_bindings/org.chromium.Buffet.Manager.xml
@@ -103,6 +103,11 @@
         JSON with command definitions of the devices.
       </tp:docstring>
     </property>
+    <property name="State" type="s" access="read">
+      <tp:docstring>
+        JSON with state of the devices.
+      </tp:docstring>
+    </property>
     <property name="OemName" type="s" access="read">
       <tp:docstring>
         Name of the device maker.
diff --git a/buffet/manager.cc b/buffet/manager.cc
index 96319c0..c69dfdd 100644
--- a/buffet/manager.cc
+++ b/buffet/manager.cc
@@ -60,6 +60,8 @@
                             test_definitions_path);
   state_change_queue_.reset(new StateChangeQueue(kMaxStateChangeQueueSize));
   state_manager_ = std::make_shared<StateManager>(state_change_queue_.get());
+  state_manager_->AddOnChangedCallback(
+      base::Bind(&Manager::OnStateChanged, weak_ptr_factory_.GetWeakPtr()));
   state_manager_->Startup();
 
   std::unique_ptr<BuffetConfig> config{new BuffetConfig{state_path}};
@@ -233,12 +235,11 @@
 }
 
 void Manager::OnCommandDefsChanged() {
-  chromeos::ErrorPtr error;
   // Limit only to commands that are visible to the local clients.
   auto commands = command_manager_->GetCommandDictionary().GetCommandsAsJson(
       [](const buffet::CommandDefinition* def) {
         return def->GetVisibility().local;
-      }, true, &error);
+      }, true, nullptr);
   CHECK(commands);
   std::string json;
   base::JSONWriter::WriteWithOptions(commands.get(),
@@ -246,6 +247,15 @@
   dbus_adaptor_.SetCommandDefs(json);
 }
 
+void Manager::OnStateChanged() {
+  auto state = state_manager_->GetStateValuesAsJson(nullptr);
+  CHECK(state);
+  std::string json;
+  base::JSONWriter::WriteWithOptions(
+      state.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &json);
+  dbus_adaptor_.SetState(json);
+}
+
 void Manager::OnRegistrationChanged(RegistrationStatus status) {
   dbus_adaptor_.SetStatus(StatusToString(status));
 }
diff --git a/buffet/manager.h b/buffet/manager.h
index b15d7b0..2acb73e 100644
--- a/buffet/manager.h
+++ b/buffet/manager.h
@@ -87,6 +87,7 @@
   std::string TestMethod(const std::string& message) override;
 
   void OnCommandDefsChanged();
+  void OnStateChanged();
   void OnRegistrationChanged(RegistrationStatus status);
   void OnConfigChanged(const BuffetConfig& config);