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