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 systemdTimeService = "org.freedesktop.timedate1"; 15 constexpr auto systemdTimePath = "/org/freedesktop/timedate1"; 16 constexpr auto systemdTimeInterface = "org.freedesktop.timedate1"; 17 constexpr auto methodSetNtp = "SetNTP"; 18 } // namespace 19 20 namespace phosphor 21 { 22 namespace time 23 { 24 25 PHOSPHOR_LOG2_USING; 26 27 Manager::Manager(sdbusplus::bus_t& bus) : bus(bus), settings(bus) 28 { 29 using namespace sdbusplus::bus::match::rules; 30 settingsMatches.emplace_back( 31 bus, propertiesChanged(settings.timeSyncMethod, settings::timeSyncIntf), 32 [&](sdbusplus::message_t& m) { onSettingsChanged(m); }); 33 34 // Check the settings daemon to process the new settings 35 auto mode = getSetting(settings.timeSyncMethod.c_str(), 36 settings::timeSyncIntf, propertyTimeMode); 37 38 onPropertyChanged(propertyTimeMode, mode); 39 } 40 41 void Manager::onPropertyChanged(const std::string& key, 42 const std::string& value) 43 { 44 assert(key == propertyTimeMode); 45 46 // Notify listeners 47 setCurrentTimeMode(value); 48 onTimeModeChanged(value); 49 } 50 51 int Manager::onSettingsChanged(sdbusplus::message_t& msg) 52 { 53 using Interface = std::string; 54 using Property = std::string; 55 using Value = std::string; 56 using Properties = std::map<Property, std::variant<Value>>; 57 58 Interface interface; 59 Properties properties; 60 61 msg.read(interface, properties); 62 63 for (const auto& p : properties) 64 { 65 onPropertyChanged(p.first, std::get<std::string>(p.second)); 66 } 67 68 return 0; 69 } 70 71 void Manager::updateNtpSetting(const std::string& value) 72 { 73 try 74 { 75 bool isNtp = 76 (value == "xyz.openbmc_project.Time.Synchronization.Method.NTP"); 77 auto method = bus.new_method_call(systemdTimeService, systemdTimePath, 78 systemdTimeInterface, methodSetNtp); 79 method.append(isNtp, false); // isNtp: 'true/false' means Enable/Disable 80 // 'false' meaning no policy-kit 81 82 bus.call_noreply(method); 83 info("Updated NTP setting: {ENABLED}", "ENABLED", isNtp); 84 } 85 catch (const sdbusplus::exception_t& ex) 86 { 87 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 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 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 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