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     try
73     {
74         bool isNtp =
75             (value == "xyz.openbmc_project.Time.Synchronization.Method.NTP");
76         auto method =
77             bus.new_method_call(SYSTEMD_TIME_SERVICE, SYSTEMD_TIME_PATH,
78                                 SYSTEMD_TIME_INTERFACE, METHOD_SET_NTP);
79         method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable
80                                      // 'false' meaning no policy-kit
81 
82         bus.call_noreply(method);
83         lg2::info("Updated NTP setting: {ENABLED}", "ENABLED", isNtp);
84     }
85     catch (const sdbusplus::exception_t& ex)
86     {
87         lg2::error("Failed to update NTP setting: {ERROR}", "ERROR", ex);
88     }
89 }
90 
91 bool Manager::setCurrentTimeMode(const std::string& mode)
92 {
93     try
94     {
95         auto newMode = utils::strToMode(mode);
96         if (newMode != timeMode)
97         {
98             lg2::info("Time mode has been changed to {MODE}", "MODE", newMode);
99             timeMode = newMode;
100             return true;
101         }
102     }
103     catch (const sdbusplus::exception_t& ex)
104     {
105         lg2::error("Failed to convert mode from string: {ERROR}", "ERROR", ex);
106     }
107 
108     return false;
109 }
110 
111 void Manager::onTimeModeChanged(const std::string& mode)
112 {
113     // When time_mode is updated, update the NTP setting
114     updateNtpSetting(mode);
115 }
116 
117 std::string Manager::getSetting(const char* path, const char* interface,
118                                 const char* setting) const
119 {
120     try
121     {
122         std::string settingManager = utils::getService(bus, path, interface);
123         return utils::getProperty<std::string>(bus, settingManager.c_str(),
124                                                path, interface, setting);
125     }
126     catch (const std::exception& ex)
127     {
128         lg2::error(
129             "Failed to get property: {ERROR}, path: {PATH}, interface: {INTERFACE}, name: {NAME}",
130             "ERROR", ex, "PATH", path, "INTERFACE", interface, "NAME", setting);
131         return {};
132     }
133 }
134 
135 } // namespace time
136 } // namespace phosphor
137