Implement HostEpoch set time logic

1. When setting host epoch, follow below logic:

        Mode  | Owner | Set Host Time
        ----- | ----- | -------------
        NTP   | BMC   | Not allowed
        NTP   | HOST  | Not allowed
        NTP   | SPLIT | OK, and just save offset
        NTP   | BOTH  | Not allowed
        MANUAL| BMC   | Not allowed
        MANUAL| HOST  | OK, and set time to BMC
        MANUAL| SPLIT | OK, and just save offset
        MANUAL| BOTH  | OK, and set time to BMC

2. If owner is SPLIT and BMC time is changed, update the offset accordinly;
3. Use timerfd to get notified on BMC time change, and update host time
diff accordingly;
4. Add unit test cases.

Change-Id: I2d60a821f7da9b689c579ae7ab672cc37967322c
Signed-off-by: Lei YU <mine260309@gmail.com>
diff --git a/bmc_epoch.hpp b/bmc_epoch.hpp
index 8c841a7..228a39d 100644
--- a/bmc_epoch.hpp
+++ b/bmc_epoch.hpp
@@ -1,12 +1,17 @@
 #pragma once
 
+#include "bmc_time_change_listener.hpp"
 #include "epoch_base.hpp"
 
+#include <chrono>
+
 namespace phosphor
 {
 namespace time
 {
 
+using namespace std::chrono;
+
 /** @class BmcEpoch
  *  @brief OpenBMC BMC EpochTime implementation.
  *  @details A concrete implementation for xyz.openbmc_project.Time.EpochTime
@@ -18,6 +23,7 @@
         friend class TestBmcEpoch;
         BmcEpoch(sdbusplus::bus::bus& bus,
                  const char* objPath);
+        ~BmcEpoch();
 
         /**
          * @brief Get value of Elapsed property
@@ -33,6 +39,55 @@
          * @return The updated elapsed microseconds since UTC
          **/
         uint64_t elapsed(uint64_t value) override;
+
+        /** @brief Set the listner for bmc time change
+         *
+         * @param[in] listener - The pointer to the listener
+         */
+        void setBmcTimeChangeListener(BmcTimeChangeListener* listener);
+
+    private:
+        /** @brief The fd for time change event */
+        int timeFd = -1;
+
+        /** @brief Initialize timerFd related resource */
+        void initialize();
+
+        /** @brief Notify the listeners that bmc time is changed
+         *
+         * @param[in] time - The epoch time in microseconds to notify
+         */
+        void notifyBmcTimeChange(const microseconds& time);
+
+        /** @brief The callback function on system time change
+         *
+         * @param[in] es - Source of the event
+         * @param[in] fd - File descriptor of the timer
+         * @param[in] revents - Not used
+         * @param[in] userdata - User data pointer
+         */
+        static int onTimeChange(sd_event_source* es, int fd,
+                                uint32_t revents, void* userdata);
+
+        /** @brief The reference of sdbusplus bus */
+        sdbusplus::bus::bus& bus;
+
+        /** @brief The deleter of sd_event_source */
+        std::function<void(sd_event_source*)> sdEventSourceDeleter =
+            [] (sd_event_source* p) {
+                if (p)
+                {
+                    sd_event_source_unref(p);
+                }
+            };
+        using SdEventSource = std::unique_ptr<sd_event_source,
+                                              decltype(sdEventSourceDeleter)>;
+
+        /** @brief The event source on system time change */
+        SdEventSource timeChangeEventSource {nullptr, sdEventSourceDeleter};
+
+        /** @brief The listener for bmc time change */
+        BmcTimeChangeListener* timeChangeListener = nullptr;
 };
 
 } // namespace time