mirror of
https://git.proxmox.com/git/fwupd
synced 2025-05-23 23:05:39 +00:00

A series of changes are made to the powerd skeleton plugin in order to reach two goals: ensuring that it handles cases correctly, given certain information about the battery and/or certain return types and that it successfully retrieves battery information from powerd to be used later. Logic is then added to ensure updates are only performed when that battery level is at or above the minimum threshold. Then logic is added that checks if the device being updating requires AC power. Along with this, specific error statements are added for each scenario where an update is blocked. To address the next goal, within fu_plugin_startup(), a GDBus connection is established. However, instead of a direct connection to powerd, the connection is changed to link to the general system bus with g_bus_get_sync(). From there, a proxy is created to represent the connection to powerd. A test call is made for the name of the service that the proxy represents to check for successful communication. Then, in fu_plugin_update_prepare(), the existing proxy is called and in the call, the "GetBatteryState" is passed to make a method call method. The response is filled into a GVariant, whose entries are initialized in new variables to use for battery checks. And checks are added to make sure every step was successful.
138 lines
3.4 KiB
C
138 lines
3.4 KiB
C
/*
|
|
* Copyright (C) 2021 Twain Byrnes <binarynewts@google.com>
|
|
* Copyright (C) 2021 George Popoola <gpopoola@google.com>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <fwupdplugin.h>
|
|
|
|
#define MINIMUM_BATTERY_PERCENTAGE_FALLBACK 10
|
|
|
|
struct FuPluginData {
|
|
GDBusProxy *proxy; /* nullable */
|
|
};
|
|
|
|
void
|
|
fu_plugin_init (FuPlugin *plugin)
|
|
{
|
|
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
|
|
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
|
|
}
|
|
|
|
void
|
|
fu_plugin_destroy (FuPlugin *plugin)
|
|
{
|
|
FuPluginData *data = fu_plugin_get_data (plugin);
|
|
if (data->proxy != NULL)
|
|
g_object_unref (data->proxy);
|
|
}
|
|
|
|
gboolean
|
|
fu_plugin_startup (FuPlugin *plugin, GError **error)
|
|
{
|
|
FuPluginData *data = fu_plugin_get_data (plugin);
|
|
g_autoptr(GDBusConnection) connection = NULL;
|
|
g_autofree gchar *name_owner = NULL;
|
|
|
|
/* establishing DBus connection and proxy for method call to powerd */
|
|
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
|
|
|
|
if (connection == NULL) {
|
|
g_prefix_error (error,
|
|
"Connection with system was not established: ");
|
|
return FALSE;
|
|
}
|
|
|
|
data->proxy = g_dbus_proxy_new_sync (connection,
|
|
G_DBUS_PROXY_FLAGS_NONE,
|
|
NULL,
|
|
"org.chromium.PowerManager",
|
|
"/org/chromium/PowerManager",
|
|
"org.chromium.PowerManager",
|
|
NULL,
|
|
error);
|
|
|
|
if (data->proxy == NULL) {
|
|
g_prefix_error (
|
|
error,
|
|
"Failed to establish proxy for power manager server: ");
|
|
return FALSE;
|
|
}
|
|
|
|
name_owner = g_dbus_proxy_get_name_owner (data->proxy);
|
|
if (name_owner == NULL) {
|
|
g_set_error (error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_NOT_SUPPORTED,
|
|
"No service that owns the name for %s",
|
|
g_dbus_proxy_get_name (data->proxy));
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
fu_plugin_update_prepare (FuPlugin *plugin,
|
|
FwupdInstallFlags flags,
|
|
FuDevice *device,
|
|
GError **error)
|
|
{
|
|
FuPluginData *data = fu_plugin_get_data (plugin);
|
|
guint32 power_type = 0;
|
|
guint32 current_status = 0;
|
|
gdouble current_percentage = 0;
|
|
g_autoptr(GVariant) powerd_response = NULL;
|
|
|
|
/* making method call to "GetBatteryState" through the proxy */
|
|
powerd_response = g_dbus_proxy_call_sync (data->proxy,
|
|
"GetBatteryState",
|
|
NULL,
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
-1,
|
|
NULL,
|
|
error);
|
|
|
|
if (powerd_response == NULL) {
|
|
g_prefix_error (
|
|
error,
|
|
"Battery information from powerd was not loaded "
|
|
"successfully: ");
|
|
return FALSE;
|
|
}
|
|
|
|
/* parsing data in powerd_response and inputting it into battery-check
|
|
* conditions */
|
|
g_variant_get (powerd_response,
|
|
"(uud)",
|
|
&power_type,
|
|
¤t_status,
|
|
¤t_percentage);
|
|
|
|
/* blocking updates if there is no AC power or if battery
|
|
* percentage is too low
|
|
*/
|
|
if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_REQUIRE_AC) &&
|
|
current_status == FU_BATTERY_STATE_DISCHARGING) {
|
|
g_set_error (error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_AC_POWER_REQUIRED,
|
|
"Cannot install update without external power "
|
|
"unless forced ");
|
|
return FALSE;
|
|
}
|
|
|
|
if (current_percentage < MINIMUM_BATTERY_PERCENTAGE_FALLBACK) {
|
|
g_set_error (error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_BATTERY_LEVEL_TOO_LOW,
|
|
"Cannot install update when system battery "
|
|
"is not at least %i%% unless forced",
|
|
MINIMUM_BATTERY_PERCENTAGE_FALLBACK);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|