Update Plymouth when updating pending firmware

Some updates take some time to deploy, so we need to update the UI to avoid the
user thinking it's just hung.
This commit is contained in:
Richard Hughes 2019-03-21 21:22:25 +00:00
parent 19e56866f6
commit 1dfc367ba2

View File

@ -16,6 +16,81 @@
#include "fu-plugin-private.h" #include "fu-plugin-private.h"
#include "fu-util-common.h" #include "fu-util-common.h"
struct FuUtilPrivate {
gchar *splash_cmd;
GTimer *splash_timer;
};
static gboolean
fu_offline_set_splash_progress (FuUtilPrivate *priv, guint percentage, GError **error)
{
g_autofree gchar *msg = NULL;
g_autofree gchar *str = NULL;
g_autoptr(GSubprocess) subprocess = NULL;
/* call into plymouth if installed */
if (priv->splash_cmd == NULL)
return TRUE;
/* TRANSLATORS: this is the message we send plymouth to advise
* of the new percentage completion when installing firmware */
msg = g_strdup_printf ("%s - %u%%", _("Installing Firmware"), percentage);
str = g_strdup_printf ("%u", percentage);
subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_NONE, error,
priv->splash_cmd, "update",
"--status", msg,
"--progress", str, NULL);
if (subprocess == NULL)
return FALSE;
return g_subprocess_wait (subprocess, NULL, error);
}
static gboolean
fu_offline_set_splash_mode (FuUtilPrivate *priv, const gchar *mode, GError **error)
{
g_autofree gchar *mode_str = NULL;
g_autoptr(GSubprocess) subprocess = NULL;
/* call into plymouth if installed */
if (priv->splash_cmd == NULL)
return TRUE;
mode_str = g_strdup_printf ("--%s", mode);
subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_NONE, error,
priv->splash_cmd,
"change-mode", mode_str, NULL);
if (subprocess == NULL)
return FALSE;
return g_subprocess_wait (subprocess, NULL, error);
}
static void
fu_offline_client_notify_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
{
FuUtilPrivate *priv = (FuUtilPrivate *) user_data;
FwupdClient *client = FWUPD_CLIENT (object);
/* rate limit to 1 second */
if (g_timer_elapsed (priv->splash_timer, NULL) < 1.f ||
fwupd_client_get_percentage (client) < 5)
return;
fu_offline_set_splash_progress (priv, fwupd_client_get_percentage (client), NULL);
g_timer_reset (priv->splash_timer);
}
static void
fu_util_private_free (FuUtilPrivate *priv)
{
if (priv->splash_timer != NULL)
g_timer_destroy (priv->splash_timer);
g_free (priv->splash_cmd);
g_free (priv);
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuUtilPrivate, fu_util_private_free)
#pragma clang diagnostic pop
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
@ -26,6 +101,7 @@ main (int argc, char *argv[])
g_autoptr(FwupdClient) client = NULL; g_autoptr(FwupdClient) client = NULL;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) results = NULL; g_autoptr(GPtrArray) results = NULL;
g_autoptr(FuUtilPrivate) priv = g_new0 (FuUtilPrivate, 1);
setlocale (LC_ALL, ""); setlocale (LC_ALL, "");
@ -50,6 +126,10 @@ main (int argc, char *argv[])
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* find plymouth, but not an error if not found */
priv->splash_cmd = g_find_program_in_path ("plymouth");
priv->splash_timer = g_timer_new ();
/* ensure D-Bus errors are registered */ /* ensure D-Bus errors are registered */
fwupd_error_quark (); fwupd_error_quark ();
@ -65,6 +145,8 @@ main (int argc, char *argv[])
/* connect to the daemon */ /* connect to the daemon */
client = fwupd_client_new (); client = fwupd_client_new ();
g_signal_connect (client, "notify::percentage",
G_CALLBACK (fu_offline_client_notify_cb), priv);
if (!fwupd_client_connect (client, NULL, &error)) { if (!fwupd_client_connect (client, NULL, &error)) {
/* TRANSLATORS: we could not talk to the fwupd daemon */ /* TRANSLATORS: we could not talk to the fwupd daemon */
g_printerr ("%s: %s\n", _("Failed to connect to daemon"), g_printerr ("%s: %s\n", _("Failed to connect to daemon"),
@ -72,6 +154,14 @@ main (int argc, char *argv[])
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* set up splash */
if (!fu_offline_set_splash_mode (priv, "updates", &error)) {
/* TRANSLATORS: we could not talk to plymouth */
g_printerr ("%s: %s\n", _("Failed to set splash mode"),
error->message);
return EXIT_FAILURE;
}
/* apply each update */ /* apply each update */
for (guint i = 0; i < results->len; i++) { for (guint i = 0; i < results->len; i++) {
FwupdDevice *dev = g_ptr_array_index (results, i); FwupdDevice *dev = g_ptr_array_index (results, i);
@ -131,6 +221,7 @@ main (int argc, char *argv[])
} }
/* reboot */ /* reboot */
fu_offline_set_splash_mode (priv, "reboot", NULL);
if (!fu_util_update_reboot (&error)) { if (!fu_util_update_reboot (&error)) {
/* TRANSLATORS: we could not reboot for some reason */ /* TRANSLATORS: we could not reboot for some reason */
g_printerr ("%s: %s\n", _("Failed to reboot"), error->message); g_printerr ("%s: %s\n", _("Failed to reboot"), error->message);