usb: Update the RequestedActivation property

Subscribe to the add software interface, when an update is detected,
call back the updateActivation method and verify whether it needs
to be updated. If necessary:
1. Set ApplyTime to OnReset to prevent the bmc from restarting
   immediately after the update.
2. Change the RequestedActivation attribute value and start to update
   the image bmc.

Tested: Manually start the phopshor-usb-manager daemon, and saw that
the bmc upgrade file(*.tar) has been copied to /tmp/images and
the update has been triggered, and bmc has not been restarted
immediately.

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: Ic650e34f8ec61d3c826332d28275db90f9ef348e
diff --git a/usb/usb_manager.cpp b/usb/usb_manager.cpp
index b002dbd..ed831dd 100644
--- a/usb/usb_manager.cpp
+++ b/usb/usb_manager.cpp
@@ -46,5 +46,79 @@
     return false;
 }
 
+void USBManager::setApplyTime()
+{
+    utils::PropertyValue value =
+        "xyz.openbmc_project.Software.ApplyTime.RequestedApplyTimes.OnReset";
+    constexpr auto objectPath = "/xyz/openbmc_project/software/apply_time";
+    constexpr auto interface = "xyz.openbmc_project.Software.ApplyTime";
+    constexpr auto propertyName = "RequestedApplyTime";
+    try
+    {
+        utils::setProperty(bus, objectPath, interface, propertyName, value);
+    }
+    catch (const std::exception& e)
+    {
+        lg2::error("Failed to set RequestedApplyTime property, ERROR:{ERROR}",
+                   "ERROR", e.what());
+    }
+}
+
+void USBManager::setRequestedActivation(const std::string& path)
+{
+    utils::PropertyValue value =
+        "xyz.openbmc_project.Software.Activation.RequestedActivations.Active";
+    constexpr auto interface = "xyz.openbmc_project.Software.Activation";
+    constexpr auto propertyName = "RequestedActivation";
+    try
+    {
+        utils::setProperty(bus, path, interface, propertyName, value);
+    }
+    catch (const std::exception& e)
+    {
+        lg2::error("Failed to set RequestedActivation property, ERROR:{ERROR}",
+                   "ERROR", e.what());
+    }
+
+    return;
+}
+
+void USBManager::updateActivation(sdbusplus::message::message& msg)
+{
+    std::map<std::string, std::map<std::string, std::variant<std::string>>>
+        interfaces;
+    sdbusplus::message::object_path path;
+    msg.read(path, interfaces);
+
+    constexpr auto imageInterface = "xyz.openbmc_project.Software.Activation";
+    constexpr auto readyPro =
+        "xyz.openbmc_project.Software.Activation.Activations.Ready";
+    for (auto& interface : interfaces)
+    {
+        if (interface.first != imageInterface)
+        {
+            continue;
+        }
+
+        try
+        {
+            auto propVal =
+                utils::getProperty(bus, path.str, imageInterface, "Activation");
+            const auto& imageProp = std::get<std::string>(propVal);
+            if (imageProp == readyPro && isUSBCodeUpdate)
+            {
+                setApplyTime();
+                setRequestedActivation(path.str);
+                event.exit(0);
+            }
+        }
+        catch (const std::exception& e)
+        {
+            lg2::error("Failed in getting Activation status, ERROR:{ERROR}",
+                       "ERROR", e.what());
+        }
+    }
+}
+
 } // namespace usb
-} // namespace phosphor
\ No newline at end of file
+} // namespace phosphor