Add pgood signal handler.

Pgood indicate if host is on, which will be used to handle the time
mode/owner changes.

Change-Id: I7be4f7300aca3d1adc118eb3eb447c1e3734c89f
Signed-off-by: Lei YU <mine260309@gmail.com>
diff --git a/manager.cpp b/manager.cpp
index c4732f4..5a3d928 100644
--- a/manager.cpp
+++ b/manager.cpp
@@ -22,6 +22,17 @@
     rules::path("/org/openbmc/settings/host0") +
     rules::interface("org.freedesktop.DBus.Properties");
 
+const auto MATCH_PGOOD_CHANGE =
+    rules::type::signal() +
+    rules::member("PropertiesChanged") +
+    rules::path("/org/openbmc/control/power0") +
+    rules::interface("org.freedesktop.DBus.Properties");
+
+// TODO: consider put the get properties related functions into a common place
+constexpr auto POWER_SERVICE = "org.openbmc.control.Power";
+constexpr auto POWER_PATH = "/org/openbmc/control/power0";
+constexpr auto POWER_INTERFACE = POWER_SERVICE;
+constexpr auto PGOOD_STR = "pgood";
 }
 
 namespace phosphor
@@ -44,10 +55,12 @@
 
 Manager::Manager(sdbusplus::bus::bus& bus)
     : bus(bus),
-      propertyChangeMatch(bus, MATCH_PROPERTY_CHANGE, onPropertyChanged, this)
+      propertyChangeMatch(bus, MATCH_PROPERTY_CHANGE, onPropertyChanged, this),
+      pgoodChangeMatch(bus, MATCH_PGOOD_CHANGE, onPgoodChanged, this)
 {
     setCurrentTimeMode(getSettings(PROPERTY_TIME_MODE));
     setCurrentTimeOwner(getSettings(PROPERTY_TIME_OWNER));
+    checkHostOn();
 }
 
 void Manager::addListener(PropertyChangeListner* listener)
@@ -59,12 +72,30 @@
     listeners.insert(listener);
 }
 
+void Manager::checkHostOn()
+{
+    sdbusplus::message::variant<int> pgood = 0;
+    auto method = bus.new_method_call(POWER_SERVICE,
+                                      POWER_PATH,
+                                      PROPERTY_INTERFACE,
+                                      METHOD_GET);
+    method.append(PROPERTY_INTERFACE, PGOOD_STR);
+    auto reply = bus.call(method);
+    if (reply)
+    {
+        reply.read(pgood);
+    }
+
+    hostOn = static_cast<bool>(pgood.get<int>());
+}
+
 void Manager::onPropertyChanged(const std::string& key,
                                 const std::string& value)
 {
     // TODO: Check pgood
     // If it's off, notify listners;
-    // If it's on, hold the values and store in persistent storage.
+    // If it's on, hold the values and store in persistent storage
+    // as requested time mode/owner.
     // And when pgood turns back to off, notify the listners.
 
     // TODO: Check dhcp_ntp
@@ -92,7 +123,7 @@
                                sd_bus_error* retError)
 {
     using properties = std::map < std::string,
-          sdbusplus::message::variant<int, std::string >>;
+          sdbusplus::message::variant<std::string> >;
     auto m = sdbusplus::message::message(msg);
     // message type: sa{sv}as
     std::string ignore;
@@ -109,6 +140,34 @@
     return 0;
 }
 
+void Manager::onPgoodChanged(bool pgood)
+{
+    hostOn = pgood;
+    // TODO: if host is off, check requested time_mode/owner:
+    // and notify the listeners if any.
+}
+
+int Manager::onPgoodChanged(sd_bus_message* msg,
+                            void* userData,
+                            sd_bus_error* retError)
+{
+    using properties = std::map < std::string,
+          sdbusplus::message::variant<int> >;
+    auto m = sdbusplus::message::message(msg);
+    // message type: sa{sv}as
+    std::string ignore;
+    properties props;
+    m.read(ignore, props);
+    for (const auto& item : props)
+    {
+        if (item.first == PGOOD_STR)
+        {
+            static_cast<Manager*>(userData)
+                ->onPgoodChanged(static_cast<bool>(item.second.get<int>()));
+        }
+    }
+    return 0;
+}
 
 void Manager::setCurrentTimeMode(const std::string& mode)
 {