1 #include "manager.hpp"
2 
3 #include "utils.hpp"
4 
5 #include <assert.h>
6 
7 #include <phosphor-logging/lg2.hpp>
8 
9 namespace rules = sdbusplus::bus::match::rules;
10 
11 namespace // anonymous
12 {
13 
14 constexpr auto SYSTEMD_TIME_SERVICE = "org.freedesktop.timedate1";
15 constexpr auto SYSTEMD_TIME_PATH = "/org/freedesktop/timedate1";
16 constexpr auto SYSTEMD_TIME_INTERFACE = "org.freedesktop.timedate1";
17 constexpr auto METHOD_SET_NTP = "SetNTP";
18 } // namespace
19 
20 namespace phosphor
21 {
22 namespace time
23 {
24 
25 Manager::Manager(sdbusplus::bus_t& bus) : bus(bus), settings(bus)
26 {
27     using namespace sdbusplus::bus::match::rules;
28     settingsMatches.emplace_back(
29         bus, propertiesChanged(settings.timeSyncMethod, settings::timeSyncIntf),
30         std::bind(std::mem_fn(&Manager::onSettingsChanged), this,
31                   std::placeholders::_1));
32 
33     // Check the settings daemon to process the new settings
34     auto mode = getSetting(settings.timeSyncMethod.c_str(),
35                            settings::timeSyncIntf, PROPERTY_TIME_MODE);
36 
37     onPropertyChanged(PROPERTY_TIME_MODE, mode);
38 }
39 
40 void Manager::onPropertyChanged(const std::string& key,
41                                 const std::string& value)
42 {
43     assert(key == PROPERTY_TIME_MODE);
44 
45     // Notify listeners
46     setCurrentTimeMode(value);
47     onTimeModeChanged(value);
48 }
49 
50 int Manager::onSettingsChanged(sdbusplus::message_t& msg)
51 {
52     using Interface = std::string;
53     using Property = std::string;
54     using Value = std::string;
55     using Properties = std::map<Property, std::variant<Value>>;
56 
57     Interface interface;
58     Properties properties;
59 
60     msg.read(interface, properties);
61 
62     for (const auto& p : properties)
63     {
64         onPropertyChanged(p.first, std::get<std::string>(p.second));
65     }
66 
67     return 0;
68 }
69 
70 void Manager::updateNtpSetting(const std::string& value)
71 {
72     bool isNtp =
73         (value == "xyz.openbmc_project.Time.Synchronization.Method.NTP");
74     auto method = bus.new_method_call(SYSTEMD_TIME_SERVICE, SYSTEMD_TIME_PATH,
75                                       SYSTEMD_TIME_INTERFACE, METHOD_SET_NTP);
76     method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
77                                  // 'false' meaning no policy-kit
78 
79     try
80     {
81         bus.call_noreply(method);
82         lg2::info("Updated NTP setting: {ENABLED}", "ENABLED", isNtp);
83     }
84     catch (const sdbusplus::exception_t& ex)
85     {
86         lg2::error("Failed to update NTP setting: {ERROR}", "ERROR", ex);
87     }
88 }
89 
90 bool Manager::setCurrentTimeMode(const std::string& mode)
91 {
92     auto newMode = utils::strToMode(mode);
93     if (newMode != timeMode)
94     {
95         lg2::info("Time mode has been changed to {MODE}", "MODE", newMode);
96         timeMode = newMode;
97         return true;
98     }
99     else
100     {
101         return false;
102     }
103 }
104 
105 void Manager::onTimeModeChanged(const std::string& mode)
106 {
107     // When time_mode is updated, update the NTP setting
108     updateNtpSetting(mode);
109 }
110 
111 std::string Manager::getSetting(const char* path, const char* interface,
112                                 const char* setting) const
113 {
114     std::string settingManager = utils::getService(bus, path, interface);
115     return utils::getProperty<std::string>(bus, settingManager.c_str(), path,
116                                            interface, setting);
117 }
118 
119 } // namespace time
120 } // namespace phosphor
121