Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Copyright (c) 2014-2016, 2020-2021 Bastien Nocera <hadess@hadess.net> | ||
3 | * Copyright (c) 2021 David Redondo <kde@david-redondo.de> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 3 as published by | ||
7 | * the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #define G_LOG_DOMAIN "Core" | ||
12 | |||
13 | #include "config.h" | ||
14 | |||
15 | #include <glib-unix.h> | ||
16 | #include <locale.h> | ||
17 | #include <polkit/polkit.h> | ||
18 | #include <stdlib.h> | ||
19 | #include <stdio.h> | ||
20 | |||
21 | #include "power-profiles-daemon-resources.h" | ||
22 | #include "power-profiles-daemon.h" | ||
23 | #include "ppd-driver-cpu.h" | ||
24 | #include "ppd-driver-platform.h" | ||
25 | #include "ppd-action.h" | ||
26 | #include "ppd-enums.h" | ||
27 | |||
28 | #define POWER_PROFILES_DBUS_NAME "org.freedesktop.UPower.PowerProfiles" | ||
29 | #define POWER_PROFILES_DBUS_PATH "/org/freedesktop/UPower/PowerProfiles" | ||
30 | #define POWER_PROFILES_IFACE_NAME POWER_PROFILES_DBUS_NAME | ||
31 | |||
32 | #define POWER_PROFILES_LEGACY_DBUS_NAME "net.hadess.PowerProfiles" | ||
33 | #define POWER_PROFILES_LEGACY_DBUS_PATH "/net/hadess/PowerProfiles" | ||
34 | #define POWER_PROFILES_LEGACY_IFACE_NAME POWER_PROFILES_LEGACY_DBUS_NAME | ||
35 | |||
36 | #define POWER_PROFILES_POLICY_NAMESPACE "org.freedesktop.UPower.PowerProfiles" | ||
37 | |||
38 | #define POWER_PROFILES_RESOURCES_PATH "/org/freedesktop/UPower/PowerProfiles" | ||
39 | |||
40 | #define UPOWER_DBUS_NAME "org.freedesktop.UPower" | ||
41 | #define UPOWER_DBUS_PATH "/org/freedesktop/UPower" | ||
42 | #define UPOWER_DBUS_INTERFACE "org.freedesktop.UPower" | ||
43 | |||
44 | #define UPOWER_DBUS_DISPLAY_DEVICE_PATH "/org/freedesktop/UPower/devices/DisplayDevice" | ||
45 | #define UPOWER_DBUS_DEVICE_INTERFACE "org.freedesktop.UPower.Device" | ||
46 | |||
47 | #define LOGIND_DBUS_NAME "org.freedesktop.login1" | ||
48 | #define LOGIND_DBUS_PATH "/org/freedesktop/login1" | ||
49 | #define LOGIND_DBUS_INTERFACE "org.freedesktop.login1.Manager" | ||
50 | |||
51 | #ifndef POLKIT_HAS_AUTOPOINTERS | ||
52 | /* FIXME: Remove this once we're fine to depend on polkit 0.114 */ | ||
53 | G_DEFINE_AUTOPTR_CLEANUP_FUNC (PolkitAuthorizationResult, g_object_unref) | ||
54 | G_DEFINE_AUTOPTR_CLEANUP_FUNC (PolkitSubject, g_object_unref) | ||
55 | #endif | ||
56 | |||
57 | typedef struct { | ||
58 | GOptionGroup *group; | ||
59 | GLogLevelFlags log_level; | ||
60 | gboolean replace; | ||
61 | gboolean disable_upower; | ||
62 | gboolean disable_logind; | ||
63 | GStrv blocked_drivers; | ||
64 | GStrv blocked_actions; | ||
65 | } DebugOptions; | ||
66 | |||
67 | typedef struct { | ||
68 | GMainLoop *main_loop; | ||
69 | GDBusConnection *connection; | ||
70 | GCancellable *cancellable; | ||
71 | guint name_id; | ||
72 | guint legacy_name_id; | ||
73 | gboolean was_started; | ||
74 | int ret; | ||
75 | |||
76 | GKeyFile *config; | ||
77 | char *config_path; | ||
78 | |||
79 | PolkitAuthority *auth; | ||
80 | |||
81 | PpdProfile active_profile; | ||
82 | PpdProfile selected_profile; | ||
83 | GPtrArray *probed_drivers; | ||
84 | PpdDriverCpu *cpu_driver; | ||
85 | PpdDriverPlatform *platform_driver; | ||
86 | GPtrArray *actions; | ||
87 | GHashTable *profile_holds; | ||
88 | |||
89 | GDBusProxy *upower_proxy; | ||
90 | GDBusProxy *upower_display_proxy; | ||
91 | gulong upower_watch_id; | ||
92 | gulong upower_display_watch_id; | ||
93 | gulong upower_properties_id; | ||
94 | gulong upower_display_properties_id; | ||
95 | PpdPowerChangedReason power_changed_reason; | ||
96 | |||
97 | guint logind_sleep_signal_id; | ||
98 | |||
99 | DebugOptions *debug_options; | ||
100 | } PpdApp; | ||
101 | |||
102 | typedef struct { | ||
103 | PpdProfile profile; | ||
104 | char *reason; | ||
105 | char *application_id; | ||
106 | char *requester; | ||
107 | char *requester_iface; | ||
108 | } ProfileHold; | ||
109 | |||
110 | static void | ||
111 | 132 | debug_options_free(DebugOptions *options) | |
112 | { | ||
113 | 132 | g_strfreev (options->blocked_drivers); | |
114 | 132 | g_strfreev (options->blocked_actions); | |
115 | 132 | g_free (options); | |
116 | 132 | } | |
117 | ✗ | G_DEFINE_AUTOPTR_CLEANUP_FUNC (DebugOptions, debug_options_free) | |
118 | |||
119 | static void | ||
120 | 40 | profile_hold_free (ProfileHold *hold) | |
121 | { | ||
122 |
1/2✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
|
40 | if (hold == NULL) |
123 | return; | ||
124 | 40 | g_free (hold->reason); | |
125 | 40 | g_free (hold->application_id); | |
126 | 40 | g_free (hold->requester); | |
127 | 40 | g_free (hold->requester_iface); | |
128 | 40 | g_free (hold); | |
129 | } | ||
130 | |||
131 | static PpdApp *ppd_app = NULL; | ||
132 | |||
133 | static void stop_profile_drivers (PpdApp *data); | ||
134 | static void start_profile_drivers (PpdApp *data); | ||
135 | static void upower_battery_set_power_changed_reason (PpdApp *, PpdPowerChangedReason); | ||
136 | |||
137 | /* profile drivers and actions */ | ||
138 | #include "ppd-action-trickle-charge.h" | ||
139 | #include "ppd-action-amdgpu-panel-power.h" | ||
140 | #include "ppd-action-amdgpu-dpm.h" | ||
141 | #include "ppd-driver-placeholder.h" | ||
142 | #include "ppd-driver-platform-profile.h" | ||
143 | #include "ppd-driver-intel-pstate.h" | ||
144 | #include "ppd-driver-amd-pstate.h" | ||
145 | #include "ppd-driver-fake.h" | ||
146 | |||
147 | typedef GType (*GTypeGetFunc) (void); | ||
148 | |||
149 | static GTypeGetFunc objects[] = { | ||
150 | /* Hardware specific profile drivers */ | ||
151 | ppd_driver_fake_get_type, | ||
152 | ppd_driver_platform_profile_get_type, | ||
153 | ppd_driver_intel_pstate_get_type, | ||
154 | ppd_driver_amd_pstate_get_type, | ||
155 | |||
156 | /* Generic profile driver */ | ||
157 | ppd_driver_placeholder_get_type, | ||
158 | |||
159 | /* Actions */ | ||
160 | ppd_action_trickle_charge_get_type, | ||
161 | ppd_action_amdgpu_panel_power_get_type, | ||
162 | ppd_action_amdgpu_dpm_get_type, | ||
163 | }; | ||
164 | |||
165 | typedef enum { | ||
166 | PROP_ACTIVE_PROFILE = 1 << 0, | ||
167 | PROP_INHIBITED = 1 << 1, | ||
168 | PROP_PROFILES = 1 << 2, | ||
169 | PROP_ACTIONS = 1 << 3, | ||
170 | PROP_DEGRADED = 1 << 4, | ||
171 | PROP_ACTIVE_PROFILE_HOLDS = 1 << 5, | ||
172 | PROP_VERSION = 1 << 6, | ||
173 | } PropertiesMask; | ||
174 | |||
175 | #define PROP_ALL (PROP_ACTIVE_PROFILE | \ | ||
176 | PROP_INHIBITED | \ | ||
177 | PROP_PROFILES | \ | ||
178 | PROP_ACTIONS | \ | ||
179 | PROP_DEGRADED | \ | ||
180 | PROP_ACTIVE_PROFILE_HOLDS | \ | ||
181 | PROP_VERSION) | ||
182 | |||
183 | static gboolean | ||
184 | 8972 | driver_profile_support (PpdDriver *driver, | |
185 | PpdProfile profile) | ||
186 | { | ||
187 |
2/2✓ Branch 1 taken 5426 times.
✓ Branch 2 taken 3546 times.
|
8972 | if (!PPD_IS_DRIVER (driver)) |
188 | return FALSE; | ||
189 | 5426 | return (ppd_driver_get_profiles (driver) & profile) != 0; | |
190 | } | ||
191 | |||
192 | static gboolean | ||
193 | 2306 | get_profile_available (PpdApp *data, | |
194 | PpdProfile profile) | ||
195 | { | ||
196 |
4/4✓ Branch 1 taken 1772 times.
✓ Branch 2 taken 534 times.
✓ Branch 3 taken 1410 times.
✓ Branch 4 taken 362 times.
|
4078 | return driver_profile_support (PPD_DRIVER (data->cpu_driver), profile) || |
197 | 1772 | driver_profile_support (PPD_DRIVER (data->platform_driver), profile); | |
198 | } | ||
199 | |||
200 | static const char * | ||
201 | 1607 | get_active_profile (PpdApp *data) | |
202 | { | ||
203 | 1607 | return ppd_profile_to_str (data->active_profile); | |
204 | } | ||
205 | |||
206 | static char * | ||
207 | 482 | get_performance_degraded (PpdApp *data) | |
208 | { | ||
209 | 482 | const gchar *cpu_degraded = NULL; | |
210 | 482 | const gchar *platform_degraded = NULL; | |
211 | |||
212 |
2/2✓ Branch 1 taken 208 times.
✓ Branch 2 taken 274 times.
|
482 | if (driver_profile_support (PPD_DRIVER (data->platform_driver), PPD_PROFILE_PERFORMANCE)) |
213 | 208 | platform_degraded = ppd_driver_get_performance_degraded (PPD_DRIVER (data->platform_driver)); | |
214 | |||
215 |
2/2✓ Branch 1 taken 150 times.
✓ Branch 2 taken 332 times.
|
482 | if (driver_profile_support (PPD_DRIVER (data->cpu_driver), PPD_PROFILE_PERFORMANCE)) |
216 | 150 | cpu_degraded = ppd_driver_get_performance_degraded (PPD_DRIVER (data->cpu_driver)); | |
217 | |||
218 |
2/2✓ Branch 0 taken 444 times.
✓ Branch 1 taken 38 times.
|
482 | if (!cpu_degraded && !platform_degraded) |
219 | 444 | return g_strdup (""); | |
220 | |||
221 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 26 times.
|
38 | if (!cpu_degraded) |
222 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
24 | return g_strdup (platform_degraded); |
223 | |||
224 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 6 times.
|
26 | if (!platform_degraded) |
225 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
40 | return g_strdup (cpu_degraded); |
226 | |||
227 | 6 | return g_strjoin (",", cpu_degraded, platform_degraded, NULL); | |
228 | } | ||
229 | |||
230 | static GVariant * | ||
231 | 682 | get_profiles_variant (PpdApp *data) | |
232 | { | ||
233 | 682 | GVariantBuilder builder; | |
234 | 682 | guint i; | |
235 | |||
236 | 682 | g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); | |
237 | |||
238 |
2/2✓ Branch 1 taken 2046 times.
✓ Branch 2 taken 682 times.
|
3410 | for (i = 0; i < NUM_PROFILES; i++) { |
239 | 2046 | PpdDriver *platform_driver = PPD_DRIVER (data->platform_driver); | |
240 | 2046 | PpdDriver *cpu_driver = PPD_DRIVER (data->cpu_driver); | |
241 | 2046 | PpdProfile profile = 1 << i; | |
242 | 2046 | GVariantBuilder asv_builder; | |
243 | 2046 | gboolean cpu, platform; | |
244 | 2046 | const gchar *driver = NULL; | |
245 | |||
246 | /* check if any of the drivers support */ | ||
247 |
2/2✓ Branch 1 taken 356 times.
✓ Branch 2 taken 1690 times.
|
2046 | if (!get_profile_available (data, profile)) |
248 | 356 | continue; | |
249 | |||
250 | 1690 | g_variant_builder_init (&asv_builder, G_VARIANT_TYPE ("a{sv}")); | |
251 | 1690 | g_variant_builder_add (&asv_builder, "{sv}", "Profile", | |
252 | 1690 | g_variant_new_string (ppd_profile_to_str (profile))); | |
253 | 1690 | cpu = driver_profile_support (cpu_driver, profile); | |
254 | 1690 | platform = driver_profile_support (platform_driver, profile); | |
255 |
2/2✓ Branch 0 taken 462 times.
✓ Branch 1 taken 1228 times.
|
1690 | if (cpu) |
256 | 462 | g_variant_builder_add (&asv_builder, "{sv}", "CpuDriver", | |
257 | 462 | g_variant_new_string (ppd_driver_get_driver_name (cpu_driver))); | |
258 |
2/2✓ Branch 0 taken 1560 times.
✓ Branch 1 taken 130 times.
|
1690 | if (platform) |
259 | 1560 | g_variant_builder_add (&asv_builder, "{sv}", "PlatformDriver", | |
260 | 1560 | g_variant_new_string (ppd_driver_get_driver_name (platform_driver))); | |
261 | |||
262 | /* compatibility with older API */ | ||
263 |
2/2✓ Branch 0 taken 1358 times.
✓ Branch 1 taken 332 times.
|
1690 | if (cpu && platform) |
264 | driver = "multiple"; | ||
265 |
2/2✓ Branch 0 taken 130 times.
✓ Branch 1 taken 1228 times.
|
1358 | else if (cpu) |
266 | 130 | driver = ppd_driver_get_driver_name (cpu_driver); | |
267 |
1/2✓ Branch 0 taken 1228 times.
✗ Branch 1 not taken.
|
1228 | else if (platform) |
268 | 1228 | driver = ppd_driver_get_driver_name (platform_driver); | |
269 | |||
270 |
1/2✓ Branch 0 taken 1358 times.
✗ Branch 1 not taken.
|
1358 | if (driver) |
271 | 1690 | g_variant_builder_add (&asv_builder, "{sv}", "Driver", | |
272 | g_variant_new_string (driver)); | ||
273 | |||
274 | 1690 | g_variant_builder_add (&builder, "a{sv}", &asv_builder); | |
275 | } | ||
276 | |||
277 | 682 | return g_variant_builder_end (&builder); | |
278 | } | ||
279 | |||
280 | static GVariant * | ||
281 | 448 | get_actions_variant (PpdApp *data) | |
282 | { | ||
283 | 448 | GVariantBuilder builder; | |
284 | 448 | guint i; | |
285 | |||
286 | 448 | g_variant_builder_init (&builder, G_VARIANT_TYPE ("as")); | |
287 | |||
288 |
2/2✓ Branch 1 taken 518 times.
✓ Branch 2 taken 448 times.
|
1414 | for (i = 0; i < data->actions->len; i++) { |
289 | 518 | PpdAction *action = g_ptr_array_index (data->actions, i); | |
290 | |||
291 | 518 | g_variant_builder_add (&builder, "s", ppd_action_get_action_name (action)); | |
292 | } | ||
293 | |||
294 | 448 | return g_variant_builder_end (&builder); | |
295 | } | ||
296 | |||
297 | static GVariant * | ||
298 | 604 | get_profile_holds_variant (PpdApp *data) | |
299 | { | ||
300 | 604 | GVariantBuilder builder; | |
301 | 604 | GHashTableIter iter; | |
302 | 604 | gpointer value; | |
303 | |||
304 | 604 | g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); | |
305 | 604 | g_hash_table_iter_init (&iter, data->profile_holds); | |
306 | |||
307 |
2/2✓ Branch 2 taken 118 times.
✓ Branch 3 taken 604 times.
|
722 | while (g_hash_table_iter_next (&iter, NULL, &value)) { |
308 | 118 | GVariantBuilder asv_builder; | |
309 | 118 | ProfileHold *hold = value; | |
310 | |||
311 | 118 | g_variant_builder_init (&asv_builder, G_VARIANT_TYPE ("a{sv}")); | |
312 | 118 | g_variant_builder_add (&asv_builder, "{sv}", "ApplicationId", | |
313 | 118 | g_variant_new_string (hold->application_id)); | |
314 | 118 | g_variant_builder_add (&asv_builder, "{sv}", "Profile", | |
315 | 118 | g_variant_new_string (ppd_profile_to_str (hold->profile))); | |
316 | 118 | g_variant_builder_add (&asv_builder, "{sv}", "Reason", g_variant_new_string (hold->reason)); | |
317 | |||
318 | 118 | g_variant_builder_add (&builder, "a{sv}", &asv_builder); | |
319 | } | ||
320 | |||
321 | 604 | return g_variant_builder_end (&builder); | |
322 | } | ||
323 | |||
324 | static void | ||
325 | 584 | send_dbus_event_iface (PpdApp *data, | |
326 | PropertiesMask mask, | ||
327 | const gchar *iface, | ||
328 | const gchar *path) | ||
329 | { | ||
330 | 584 | GVariantBuilder props_builder; | |
331 | 584 | GVariant *props_changed = NULL; | |
332 | |||
333 |
1/2✓ Branch 0 taken 584 times.
✗ Branch 1 not taken.
|
584 | g_return_if_fail (data->connection); |
334 | |||
335 |
1/2✓ Branch 0 taken 584 times.
✗ Branch 1 not taken.
|
584 | if (mask == 0) |
336 | return; | ||
337 | |||
338 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 584 times.
|
584 | g_return_if_fail ((mask & PROP_ALL) != 0); |
339 | |||
340 | 584 | g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}")); | |
341 | |||
342 |
2/2✓ Branch 0 taken 544 times.
✓ Branch 1 taken 40 times.
|
584 | if (mask & PROP_ACTIVE_PROFILE) { |
343 | 1088 | g_variant_builder_add (&props_builder, "{sv}", "ActiveProfile", | |
344 | 544 | g_variant_new_string (get_active_profile (data))); | |
345 | } | ||
346 |
2/2✓ Branch 0 taken 268 times.
✓ Branch 1 taken 316 times.
|
584 | if (mask & PROP_INHIBITED) { |
347 | 268 | g_variant_builder_add (&props_builder, "{sv}", "PerformanceInhibited", | |
348 | g_variant_new_string ("")); | ||
349 | } | ||
350 |
2/2✓ Branch 0 taken 292 times.
✓ Branch 1 taken 292 times.
|
584 | if (mask & PROP_DEGRADED) { |
351 | 292 | gchar *degraded = get_performance_degraded (data); | |
352 | 292 | g_variant_builder_add (&props_builder, "{sv}", "PerformanceDegraded", | |
353 | 292 | g_variant_new_take_string (g_steal_pointer (°raded))); | |
354 | } | ||
355 |
2/2✓ Branch 0 taken 268 times.
✓ Branch 1 taken 316 times.
|
584 | if (mask & PROP_PROFILES) { |
356 | 268 | g_variant_builder_add (&props_builder, "{sv}", "Profiles", | |
357 | get_profiles_variant (data)); | ||
358 | } | ||
359 |
2/2✓ Branch 0 taken 268 times.
✓ Branch 1 taken 316 times.
|
584 | if (mask & PROP_ACTIONS) { |
360 | 268 | g_variant_builder_add (&props_builder, "{sv}", "Actions", | |
361 | get_actions_variant (data)); | ||
362 | } | ||
363 |
2/2✓ Branch 0 taken 424 times.
✓ Branch 1 taken 160 times.
|
584 | if (mask & PROP_ACTIVE_PROFILE_HOLDS) { |
364 | 424 | g_variant_builder_add (&props_builder, "{sv}", "ActiveProfileHolds", | |
365 | get_profile_holds_variant (data)); | ||
366 | } | ||
367 |
2/2✓ Branch 0 taken 268 times.
✓ Branch 1 taken 316 times.
|
584 | if (mask & PROP_VERSION) { |
368 | 268 | g_variant_builder_add (&props_builder, "{sv}", "Version", | |
369 | g_variant_new_string (VERSION)); | ||
370 | } | ||
371 | |||
372 | 584 | props_changed = g_variant_new ("(s@a{sv}@as)", iface, | |
373 | g_variant_builder_end (&props_builder), | ||
374 | g_variant_new_strv (NULL, 0)); | ||
375 | |||
376 | 584 | g_dbus_connection_emit_signal (data->connection, | |
377 | NULL, | ||
378 | path, | ||
379 | "org.freedesktop.DBus.Properties", | ||
380 | "PropertiesChanged", | ||
381 | props_changed, NULL); | ||
382 | } | ||
383 | |||
384 | static void | ||
385 | 292 | send_dbus_event (PpdApp *data, | |
386 | PropertiesMask mask) | ||
387 | { | ||
388 | 292 | send_dbus_event_iface (data, mask, | |
389 | POWER_PROFILES_IFACE_NAME, | ||
390 | POWER_PROFILES_DBUS_PATH); | ||
391 | 292 | send_dbus_event_iface (data, mask, | |
392 | POWER_PROFILES_LEGACY_IFACE_NAME, | ||
393 | POWER_PROFILES_LEGACY_DBUS_PATH); | ||
394 | 292 | } | |
395 | |||
396 | static void | ||
397 | 70 | save_configuration (PpdApp *data) | |
398 | { | ||
399 | 140 | g_autoptr(GError) error = NULL; | |
400 | |||
401 |
2/2✓ Branch 1 taken 26 times.
✓ Branch 2 taken 44 times.
|
70 | if (PPD_IS_DRIVER_CPU (data->cpu_driver)) { |
402 | 26 | g_key_file_set_string (data->config, "State", "CpuDriver", | |
403 | 26 | ppd_driver_get_driver_name (PPD_DRIVER (data->cpu_driver))); | |
404 | } | ||
405 | |||
406 |
1/2✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
|
70 | if (PPD_IS_DRIVER_PLATFORM (data->platform_driver)) { |
407 | 70 | g_key_file_set_string (data->config, "State", "PlatformDriver", | |
408 | 70 | ppd_driver_get_driver_name (PPD_DRIVER (data->platform_driver))); | |
409 | } | ||
410 | |||
411 | 70 | g_key_file_set_string (data->config, "State", "Profile", | |
412 | 70 | ppd_profile_to_str (data->active_profile)); | |
413 | |||
414 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 70 times.
|
70 | if (!g_key_file_save_to_file (data->config, data->config_path, &error)) |
415 | ✗ | g_warning ("Could not save configuration file '%s': %s", data->config_path, error->message); | |
416 | 70 | } | |
417 | |||
418 | static gboolean | ||
419 | 134 | apply_configuration (PpdApp *data) | |
420 | { | ||
421 | 268 | g_autofree char *platform_driver = NULL; | |
422 | 134 | g_autofree char *profile_str = NULL; | |
423 | 134 | g_autofree char *cpu_driver = NULL; | |
424 | 134 | PpdProfile profile; | |
425 | |||
426 | 134 | cpu_driver = g_key_file_get_string (data->config, "State", "CpuDriver", NULL); | |
427 |
4/4✓ Branch 1 taken 40 times.
✓ Branch 2 taken 94 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 38 times.
|
174 | if (PPD_IS_DRIVER_CPU (data->cpu_driver) && |
428 | 40 | g_strcmp0 (ppd_driver_get_driver_name (PPD_DRIVER (data->cpu_driver)), cpu_driver) != 0) | |
429 | return FALSE; | ||
430 | |||
431 | 96 | platform_driver = g_key_file_get_string (data->config, "State", "PlatformDriver", NULL); | |
432 | |||
433 |
3/4✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 90 times.
✓ Branch 4 taken 6 times.
|
192 | if (PPD_IS_DRIVER_PLATFORM (data->platform_driver) && |
434 | 96 | g_strcmp0 (ppd_driver_get_driver_name (PPD_DRIVER (data->platform_driver)), platform_driver) != 0) | |
435 | return FALSE; | ||
436 | |||
437 | 6 | profile_str = g_key_file_get_string (data->config, "State", "Profile", NULL); | |
438 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (profile_str == NULL) |
439 | return FALSE; | ||
440 | |||
441 | 6 | profile = ppd_profile_from_str (profile_str); | |
442 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (profile == PPD_PROFILE_UNSET) { |
443 | ✗ | g_debug ("Resetting invalid configuration profile '%s'", profile_str); | |
444 | ✗ | g_key_file_remove_key (data->config, "State", "Profile", NULL); | |
445 | ✗ | return FALSE; | |
446 | } | ||
447 | |||
448 | 6 | g_debug ("Applying profile '%s' from configuration file", profile_str); | |
449 | 6 | data->active_profile = profile; | |
450 | 6 | return TRUE; | |
451 | } | ||
452 | |||
453 | static void | ||
454 | 132 | load_configuration (PpdApp *data) | |
455 | { | ||
456 | 264 | g_autoptr(GError) error = NULL; | |
457 | |||
458 |
2/2✓ Branch 1 taken 130 times.
✓ Branch 2 taken 2 times.
|
132 | if (g_getenv ("UMOCKDEV_DIR") != NULL) |
459 | 130 | data->config_path = g_build_filename (g_getenv ("UMOCKDEV_DIR"), "ppd_test_conf.ini", NULL); | |
460 | else | ||
461 | 2 | data->config_path = g_strdup ("/var/lib/power-profiles-daemon/state.ini"); | |
462 | 132 | data->config = g_key_file_new (); | |
463 |
2/2✓ Branch 1 taken 124 times.
✓ Branch 2 taken 8 times.
|
132 | if (!g_key_file_load_from_file (data->config, data->config_path, G_KEY_FILE_KEEP_COMMENTS, &error)) |
464 | 124 | g_debug ("Could not load configuration file '%s': %s", data->config_path, error->message); | |
465 | 132 | } | |
466 | |||
467 | static void | ||
468 | 270 | actions_activate_profile (GPtrArray *actions, | |
469 | PpdProfile profile) | ||
470 | { | ||
471 | 270 | guint i; | |
472 | |||
473 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
|
270 | g_return_if_fail (actions != NULL); |
474 | |||
475 |
2/2✓ Branch 0 taken 300 times.
✓ Branch 1 taken 270 times.
|
570 | for (i = 0; i < actions->len; i++) { |
476 | 300 | g_autoptr(GError) error = NULL; | |
477 | 300 | PpdAction *action; | |
478 | |||
479 | 300 | action = g_ptr_array_index (actions, i); | |
480 | |||
481 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 300 times.
|
300 | if (!ppd_action_activate_profile (action, profile, &error)) |
482 | ✗ | g_warning ("Failed to activate action '%s' to profile %s: %s", | |
483 | ppd_profile_to_str (profile), | ||
484 | ppd_action_get_action_name (action), | ||
485 | error->message); | ||
486 | } | ||
487 | } | ||
488 | |||
489 | static gboolean | ||
490 | 278 | activate_target_profile (PpdApp *data, | |
491 | PpdProfile target_profile, | ||
492 | PpdProfileActivationReason reason, | ||
493 | GError **error) | ||
494 | { | ||
495 | 278 | PpdProfile current_profile = data->active_profile; | |
496 | |||
497 | 278 | g_info ("Setting active profile '%s' for reason '%s' (current: '%s')", | |
498 | ppd_profile_to_str (target_profile), | ||
499 | ppd_profile_activation_reason_to_str (reason), | ||
500 | ppd_profile_to_str (current_profile)); | ||
501 | |||
502 | /* Try CPU first */ | ||
503 |
4/4✓ Branch 1 taken 72 times.
✓ Branch 2 taken 206 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 66 times.
|
350 | if (driver_profile_support (PPD_DRIVER (data->cpu_driver), target_profile) && |
504 | 72 | !ppd_driver_activate_profile (PPD_DRIVER (data->cpu_driver), | |
505 | target_profile, reason, error)) { | ||
506 | 12 | g_prefix_error (error, "Failed to activate CPU driver '%s': ", | |
507 | 6 | ppd_driver_get_driver_name (PPD_DRIVER (data->cpu_driver))); | |
508 | 6 | return FALSE; | |
509 | } | ||
510 | |||
511 | /* Then try platform */ | ||
512 |
4/4✓ Branch 1 taken 262 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 260 times.
|
534 | if (driver_profile_support (PPD_DRIVER (data->platform_driver), target_profile) && |
513 | 262 | !ppd_driver_activate_profile (PPD_DRIVER (data->platform_driver), | |
514 | target_profile, reason, error)) { | ||
515 | 2 | g_autoptr(GError) recovery_error = NULL; | |
516 | |||
517 | 2 | g_prefix_error (error, "Failed to activate platform driver '%s': ", | |
518 | 2 | ppd_driver_get_driver_name (PPD_DRIVER (data->platform_driver))); | |
519 | |||
520 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (!PPD_IS_DRIVER (data->cpu_driver)) |
521 | return FALSE; | ||
522 | |||
523 | 2 | g_debug ("Reverting CPU driver '%s' to profile '%s'", | |
524 | ppd_driver_get_driver_name (PPD_DRIVER (data->cpu_driver)), | ||
525 | ppd_profile_to_str (current_profile)); | ||
526 | |||
527 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if (!ppd_driver_activate_profile (PPD_DRIVER (data->cpu_driver), |
528 | current_profile, PPD_PROFILE_ACTIVATION_REASON_INTERNAL, | ||
529 | &recovery_error)) { | ||
530 | ✗ | g_warning ("Failed to revert CPU driver '%s': %s", | |
531 | ppd_driver_get_driver_name (PPD_DRIVER (data->cpu_driver)), | ||
532 | recovery_error->message); | ||
533 | } | ||
534 | |||
535 | 2 | return FALSE; | |
536 | } | ||
537 | |||
538 | 270 | actions_activate_profile (data->actions, target_profile); | |
539 | |||
540 | 270 | data->active_profile = target_profile; | |
541 | |||
542 | 270 | if (reason == PPD_PROFILE_ACTIVATION_REASON_USER || | |
543 |
2/2✓ Branch 0 taken 70 times.
✓ Branch 1 taken 200 times.
|
270 | reason == PPD_PROFILE_ACTIVATION_REASON_INTERNAL) |
544 | 70 | save_configuration (data); | |
545 | |||
546 | return TRUE; | ||
547 | } | ||
548 | |||
549 | static void | ||
550 | 40 | release_hold_notify (PpdApp *data, | |
551 | ProfileHold *hold, | ||
552 | guint cookie) | ||
553 | { | ||
554 | 40 | const char *req_path = POWER_PROFILES_DBUS_PATH; | |
555 | |||
556 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 2 taken 28 times.
|
40 | if (g_strcmp0 (hold->requester_iface, POWER_PROFILES_LEGACY_IFACE_NAME) == 0) |
557 | 12 | req_path = POWER_PROFILES_LEGACY_DBUS_PATH; | |
558 | |||
559 | 40 | g_dbus_connection_emit_signal (data->connection, hold->requester, req_path, | |
560 | 40 | hold->requester_iface, "ProfileReleased", | |
561 | g_variant_new ("(u)", cookie), NULL); | ||
562 | 40 | } | |
563 | |||
564 | static void | ||
565 | 138 | release_all_profile_holds (PpdApp *data) | |
566 | { | ||
567 | 138 | GHashTableIter iter; | |
568 | 138 | gpointer key, value; | |
569 | |||
570 | 138 | g_hash_table_iter_init (&iter, data->profile_holds); | |
571 |
2/2✓ Branch 2 taken 4 times.
✓ Branch 3 taken 138 times.
|
142 | while (g_hash_table_iter_next (&iter, &key, &value)) { |
572 | 4 | ProfileHold *hold = value; | |
573 | 4 | guint cookie = GPOINTER_TO_UINT (key); | |
574 | |||
575 | 4 | release_hold_notify (data, hold, cookie); | |
576 | 4 | g_bus_unwatch_name (cookie); | |
577 | } | ||
578 | 138 | g_hash_table_remove_all (data->profile_holds); | |
579 | 138 | } | |
580 | |||
581 | static gboolean | ||
582 | 86 | set_active_profile (PpdApp *data, | |
583 | const char *profile, | ||
584 | GError **error) | ||
585 | { | ||
586 | 86 | PpdProfile target_profile; | |
587 | 86 | guint mask = PROP_ACTIVE_PROFILE; | |
588 | |||
589 | 86 | target_profile = ppd_profile_from_str (profile); | |
590 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 84 times.
|
86 | if (target_profile == PPD_PROFILE_UNSET) { |
591 | 2 | g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, | |
592 | "Invalid profile name '%s'", profile); | ||
593 | 2 | return FALSE; | |
594 | } | ||
595 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 80 times.
|
84 | if (!get_profile_available (data, target_profile)) { |
596 | 4 | g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, | |
597 | "Cannot switch to unavailable profile '%s'", profile); | ||
598 | 4 | return FALSE; | |
599 | } | ||
600 | |||
601 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 74 times.
|
80 | if (target_profile == data->active_profile) |
602 | return TRUE; | ||
603 | |||
604 | 74 | g_debug ("Transitioning active profile from '%s' to '%s' by user request", | |
605 | ppd_profile_to_str (data->active_profile), profile); | ||
606 | |||
607 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 72 times.
|
74 | if (g_hash_table_size (data->profile_holds) != 0 ) { |
608 | 2 | g_debug ("Releasing active profile holds"); | |
609 | 2 | release_all_profile_holds (data); | |
610 | 2 | mask |= PROP_ACTIVE_PROFILE_HOLDS; | |
611 | } | ||
612 | |||
613 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 68 times.
|
74 | if (!activate_target_profile (data, target_profile, PPD_PROFILE_ACTIVATION_REASON_USER, error)) |
614 | return FALSE; | ||
615 | 68 | data->selected_profile = target_profile; | |
616 | 68 | send_dbus_event (data, mask); | |
617 | |||
618 | 68 | return TRUE; | |
619 | } | ||
620 | |||
621 | static PpdProfile | ||
622 | 44 | effective_hold_profile (PpdApp *data) | |
623 | { | ||
624 | 44 | GHashTableIter iter; | |
625 | 44 | gpointer value; | |
626 | 44 | PpdProfile profile = PPD_PROFILE_UNSET; | |
627 | |||
628 | 44 | g_hash_table_iter_init (&iter, data->profile_holds); | |
629 |
2/2✓ Branch 2 taken 48 times.
✓ Branch 3 taken 30 times.
|
78 | while (g_hash_table_iter_next (&iter, NULL, &value)) { |
630 | 48 | ProfileHold *hold = value; | |
631 | |||
632 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 14 times.
|
48 | if (hold->profile == PPD_PROFILE_POWER_SAVER) { |
633 | profile = PPD_PROFILE_POWER_SAVER; | ||
634 | break; | ||
635 | } | ||
636 | profile = hold->profile; | ||
637 | } | ||
638 | 44 | return profile; | |
639 | } | ||
640 | |||
641 | static void | ||
642 | 12 | driver_performance_degraded_changed_cb (GObject *gobject, | |
643 | GParamSpec *pspec, | ||
644 | gpointer user_data) | ||
645 | { | ||
646 | 12 | PpdApp *data = user_data; | |
647 | 12 | PpdDriver *driver = PPD_DRIVER (gobject); | |
648 | 12 | const char *prop_str = pspec->name; | |
649 | |||
650 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
|
12 | if (g_strcmp0 (prop_str, "performance-degraded") != 0) { |
651 | ✗ | g_warning ("Ignoring '%s' property change on profile driver '%s'", | |
652 | prop_str, ppd_driver_get_driver_name (driver)); | ||
653 | ✗ | return; | |
654 | } | ||
655 | |||
656 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
|
12 | if (!(ppd_driver_get_profiles (driver) & PPD_PROFILE_PERFORMANCE)) { |
657 | ✗ | g_warning ("Ignored 'performance-degraded' change on non-performance driver '%s'", | |
658 | ppd_driver_get_driver_name (driver)); | ||
659 | ✗ | return; | |
660 | } | ||
661 | |||
662 | 12 | send_dbus_event (data, PROP_DEGRADED); | |
663 | } | ||
664 | |||
665 | static void | ||
666 | 2 | driver_profile_changed_cb (PpdDriver *driver, | |
667 | PpdProfile new_profile, | ||
668 | gpointer user_data) | ||
669 | { | ||
670 | 2 | PpdApp *data = user_data; | |
671 | |||
672 | 2 | g_debug ("Driver '%s' switched internally to profile '%s' (current: '%s')", | |
673 | ppd_driver_get_driver_name (driver), | ||
674 | ppd_profile_to_str (new_profile), | ||
675 | ppd_profile_to_str (data->active_profile)); | ||
676 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (new_profile == data->active_profile) |
677 | return; | ||
678 | |||
679 | 2 | activate_target_profile (data, new_profile, PPD_PROFILE_ACTIVATION_REASON_INTERNAL, NULL); | |
680 | 2 | send_dbus_event (data, PROP_ACTIVE_PROFILE); | |
681 | } | ||
682 | |||
683 | static void | ||
684 | 36 | release_profile_hold (PpdApp *data, | |
685 | guint cookie) | ||
686 | { | ||
687 | 36 | guint mask = PROP_ACTIVE_PROFILE_HOLDS; | |
688 | 36 | ProfileHold *hold; | |
689 | 36 | PpdProfile hold_profile, next_profile; | |
690 | |||
691 | 36 | hold = g_hash_table_lookup (data->profile_holds, GUINT_TO_POINTER (cookie)); | |
692 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
|
36 | if (!hold) { |
693 | ✗ | g_debug ("No hold with cookie %d", cookie); | |
694 | ✗ | return; | |
695 | } | ||
696 | |||
697 | 36 | g_bus_unwatch_name (cookie); | |
698 | 36 | hold_profile = hold->profile; | |
699 | 36 | release_hold_notify (data, hold, cookie); | |
700 | 36 | g_hash_table_remove (data->profile_holds, GUINT_TO_POINTER (cookie)); | |
701 | |||
702 |
2/2✓ Branch 1 taken 28 times.
✓ Branch 2 taken 8 times.
|
36 | if (g_hash_table_size (data->profile_holds) == 0 && |
703 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | hold_profile != data->selected_profile) { |
704 | 28 | g_debug ("No profile holds anymore going back to last manually activated profile"); | |
705 | 28 | activate_target_profile (data, data->selected_profile, PPD_PROFILE_ACTIVATION_REASON_PROGRAM_HOLD, NULL); | |
706 | 28 | mask |= PROP_ACTIVE_PROFILE; | |
707 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | } else if (hold_profile == data->active_profile) { |
708 | 4 | next_profile = effective_hold_profile (data); | |
709 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (next_profile != PPD_PROFILE_UNSET && |
710 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | next_profile != data->active_profile) { |
711 | 4 | g_debug ("Next profile is %s", ppd_profile_to_str (next_profile)); | |
712 | 4 | activate_target_profile (data, next_profile, PPD_PROFILE_ACTIVATION_REASON_PROGRAM_HOLD, NULL); | |
713 | 4 | mask |= PROP_ACTIVE_PROFILE; | |
714 | } | ||
715 | } | ||
716 | |||
717 | 36 | send_dbus_event (data, mask); | |
718 | } | ||
719 | |||
720 | static void | ||
721 | ✗ | holder_disappeared (GDBusConnection *connection, | |
722 | const gchar *name, | ||
723 | gpointer user_data) | ||
724 | { | ||
725 | ✗ | PpdApp *data = user_data; | |
726 | ✗ | GHashTableIter iter; | |
727 | ✗ | gpointer key, value; | |
728 | ✗ | GPtrArray *cookies; | |
729 | ✗ | guint i; | |
730 | |||
731 | ✗ | cookies = g_ptr_array_new (); | |
732 | ✗ | g_hash_table_iter_init (&iter, data->profile_holds); | |
733 | ✗ | while (g_hash_table_iter_next (&iter, &key, (gpointer *) &value)) { | |
734 | ✗ | guint cookie = GPOINTER_TO_UINT (key); | |
735 | ✗ | ProfileHold *hold = value; | |
736 | |||
737 | ✗ | if (g_strcmp0 (hold->requester, name) != 0) | |
738 | ✗ | continue; | |
739 | |||
740 | ✗ | g_debug ("Holder %s with cookie %u disappeared, adding to list", name, cookie); | |
741 | ✗ | g_ptr_array_add (cookies, GUINT_TO_POINTER (cookie)); | |
742 | } | ||
743 | |||
744 | ✗ | for (i = 0; i < cookies->len; i++) { | |
745 | ✗ | guint cookie = GPOINTER_TO_UINT (cookies->pdata[i]); | |
746 | ✗ | g_debug ("Removing profile hold for cookie %u", cookie); | |
747 | ✗ | release_profile_hold (data, cookie); | |
748 | } | ||
749 | ✗ | g_ptr_array_free (cookies, TRUE); | |
750 | ✗ | } | |
751 | |||
752 | static void | ||
753 | 42 | hold_profile (PpdApp *data, | |
754 | GVariant *parameters, | ||
755 | GDBusMethodInvocation *invocation) | ||
756 | { | ||
757 | 42 | const char *profile_name; | |
758 | 42 | const char *reason; | |
759 | 42 | const char *application_id; | |
760 | 42 | PpdProfile profile; | |
761 | 42 | ProfileHold *hold; | |
762 | 42 | guint watch_id; | |
763 | 42 | guint mask; | |
764 | |||
765 | 42 | g_variant_get (parameters, "(&s&s&s)", &profile_name, &reason, &application_id); | |
766 | 42 | profile = ppd_profile_from_str (profile_name); | |
767 | 42 | if (profile != PPD_PROFILE_PERFORMANCE && | |
768 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
|
42 | profile != PPD_PROFILE_POWER_SAVER) { |
769 | ✗ | g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, | |
770 | "Only profiles 'performance' and 'power-saver' can be a hold profile"); | ||
771 | 2 | return; | |
772 | } | ||
773 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 40 times.
|
42 | if (!get_profile_available (data, profile)) { |
774 | 2 | g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, | |
775 | "Cannot hold profile '%s' as it is not available", | ||
776 | profile_name); | ||
777 | 2 | return; | |
778 | } | ||
779 | |||
780 | 40 | hold = g_new0 (ProfileHold, 1); | |
781 | 40 | hold->profile = profile; | |
782 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | hold->reason = g_strdup (reason); |
783 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | hold->application_id = g_strdup (application_id); |
784 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
|
40 | hold->requester = g_strdup (g_dbus_method_invocation_get_sender (invocation)); |
785 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
|
40 | hold->requester_iface = g_strdup (g_dbus_method_invocation_get_interface_name (invocation)); |
786 | |||
787 | 40 | g_debug ("%s (%s) requesting to hold profile '%s', reason: '%s'", application_id, | |
788 | hold->requester, profile_name, reason); | ||
789 | 40 | watch_id = g_bus_watch_name_on_connection (data->connection, hold->requester, | |
790 | G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, | ||
791 | holder_disappeared, data, NULL); | ||
792 | 40 | g_hash_table_insert (data->profile_holds, GUINT_TO_POINTER (watch_id), hold); | |
793 | 40 | g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", watch_id)); | |
794 | 40 | mask = PROP_ACTIVE_PROFILE_HOLDS; | |
795 | |||
796 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | if (profile != data->active_profile) { |
797 | 40 | PpdProfile target_profile = effective_hold_profile (data); | |
798 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
|
40 | if (target_profile != PPD_PROFILE_UNSET && |
799 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
|
40 | target_profile != data->active_profile) { |
800 | 36 | activate_target_profile (data, target_profile, PPD_PROFILE_ACTIVATION_REASON_PROGRAM_HOLD, NULL); | |
801 | 36 | mask |= PROP_ACTIVE_PROFILE; | |
802 | } | ||
803 | } | ||
804 | |||
805 | 40 | send_dbus_event (data, mask); | |
806 | } | ||
807 | |||
808 | static void | ||
809 | 36 | release_profile (PpdApp *data, | |
810 | GVariant *parameters, | ||
811 | GDBusMethodInvocation *invocation) | ||
812 | { | ||
813 | 36 | guint cookie; | |
814 | 36 | g_variant_get (parameters, "(u)", &cookie); | |
815 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
|
36 | if (!g_hash_table_contains (data->profile_holds, GUINT_TO_POINTER (cookie))) { |
816 | ✗ | g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, | |
817 | "No hold with cookie %d", cookie); | ||
818 | ✗ | return; | |
819 | } | ||
820 | 36 | release_profile_hold (data, cookie); | |
821 | 36 | g_dbus_method_invocation_return_value (invocation, NULL); | |
822 | } | ||
823 | |||
824 | static gboolean | ||
825 | 132 | check_action_permission (PpdApp *data, | |
826 | const char *sender, | ||
827 | const char *action, | ||
828 | GError **error) | ||
829 | { | ||
830 | 264 | g_autoptr(GError) local_error = NULL; | |
831 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | g_autoptr(PolkitAuthorizationResult) result = NULL; |
832 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_autoptr(PolkitSubject) subject = NULL; |
833 | |||
834 | 132 | subject = polkit_system_bus_name_new (sender); | |
835 | 132 | result = polkit_authority_check_authorization_sync (data->auth, | |
836 | subject, | ||
837 | action, | ||
838 | NULL, | ||
839 | POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE, | ||
840 | NULL, &local_error); | ||
841 |
3/4✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 128 times.
|
264 | if (result == NULL || |
842 | 132 | !polkit_authorization_result_get_is_authorized (result)) | |
843 | { | ||
844 | 4 | g_set_error (error, G_DBUS_ERROR, | |
845 | G_DBUS_ERROR_ACCESS_DENIED, | ||
846 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | "Not Authorized: %s", local_error ? local_error->message : action); |
847 | 4 | return FALSE; | |
848 | } | ||
849 | |||
850 | return TRUE; | ||
851 | |||
852 | } | ||
853 | |||
854 | static GVariant * | ||
855 | 2365 | handle_get_property (GDBusConnection *connection, | |
856 | const gchar *sender, | ||
857 | const gchar *object_path, | ||
858 | const gchar *interface_name, | ||
859 | const gchar *property_name, | ||
860 | GError **error, | ||
861 | gpointer user_data) | ||
862 | { | ||
863 | 2365 | PpdApp *data = user_data; | |
864 | |||
865 |
1/2✓ Branch 0 taken 2365 times.
✗ Branch 1 not taken.
|
2365 | g_return_val_if_fail (data->connection, NULL); |
866 | |||
867 |
2/2✓ Branch 1 taken 1063 times.
✓ Branch 2 taken 1302 times.
|
2365 | if (g_strcmp0 (property_name, "ActiveProfile") == 0) |
868 | 1063 | return g_variant_new_string (get_active_profile (data)); | |
869 |
2/2✓ Branch 1 taken 168 times.
✓ Branch 2 taken 1134 times.
|
1302 | if (g_strcmp0 (property_name, "PerformanceInhibited") == 0) |
870 | 168 | return g_variant_new_string (""); | |
871 |
2/2✓ Branch 1 taken 414 times.
✓ Branch 2 taken 720 times.
|
1134 | if (g_strcmp0 (property_name, "Profiles") == 0) |
872 | 414 | return get_profiles_variant (data); | |
873 |
2/2✓ Branch 1 taken 180 times.
✓ Branch 2 taken 540 times.
|
720 | if (g_strcmp0 (property_name, "Actions") == 0) |
874 | 180 | return get_actions_variant (data); | |
875 |
2/2✓ Branch 1 taken 190 times.
✓ Branch 2 taken 350 times.
|
540 | if (g_strcmp0 (property_name, "PerformanceDegraded") == 0) { |
876 | 190 | gchar *degraded = get_performance_degraded (data); | |
877 | 190 | return g_variant_new_take_string (g_steal_pointer (°raded)); | |
878 | } | ||
879 |
2/2✓ Branch 1 taken 180 times.
✓ Branch 2 taken 170 times.
|
350 | if (g_strcmp0 (property_name, "ActiveProfileHolds") == 0) |
880 | 180 | return get_profile_holds_variant (data); | |
881 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 170 times.
|
170 | if (g_strcmp0 (property_name, "Version") == 0) |
882 | 170 | return g_variant_new_string (VERSION); | |
883 | return NULL; | ||
884 | } | ||
885 | |||
886 | static gboolean | ||
887 | 88 | handle_set_property (GDBusConnection *connection, | |
888 | const gchar *sender, | ||
889 | const gchar *object_path, | ||
890 | const gchar *interface_name, | ||
891 | const gchar *property_name, | ||
892 | GVariant *value, | ||
893 | GError **error, | ||
894 | gpointer user_data) | ||
895 | { | ||
896 | 88 | PpdApp *data = user_data; | |
897 | 88 | const char *profile; | |
898 | |||
899 |
1/2✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
|
88 | g_return_val_if_fail (data->connection, FALSE); |
900 | |||
901 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
|
88 | if (g_strcmp0 (property_name, "ActiveProfile") != 0) { |
902 | ✗ | g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, | |
903 | "No such property: %s", property_name); | ||
904 | ✗ | return FALSE; | |
905 | } | ||
906 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 86 times.
|
88 | if (!check_action_permission (data, sender, |
907 | POWER_PROFILES_POLICY_NAMESPACE ".switch-profile", | ||
908 | error)) | ||
909 | return FALSE; | ||
910 | |||
911 | 86 | g_variant_get (value, "&s", &profile); | |
912 | 86 | return set_active_profile (data, profile, error); | |
913 | } | ||
914 | |||
915 | static void | ||
916 | 80 | handle_method_call (GDBusConnection *connection, | |
917 | const gchar *sender, | ||
918 | const gchar *object_path, | ||
919 | const gchar *interface_name, | ||
920 | const gchar *method_name, | ||
921 | GVariant *parameters, | ||
922 | GDBusMethodInvocation *invocation, | ||
923 | gpointer user_data) | ||
924 | { | ||
925 | 80 | PpdApp *data = user_data; | |
926 |
1/2✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
|
80 | g_return_if_fail (data->connection); |
927 | |||
928 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 56 times.
|
80 | if (!g_str_equal (interface_name, POWER_PROFILES_IFACE_NAME) && |
929 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | !g_str_equal (interface_name, POWER_PROFILES_LEGACY_IFACE_NAME)) { |
930 | ✗ | g_dbus_method_invocation_return_error (invocation,G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_INTERFACE, | |
931 | "Unknown interface %s", interface_name); | ||
932 | ✗ | return; | |
933 | } | ||
934 | |||
935 |
2/2✓ Branch 1 taken 44 times.
✓ Branch 2 taken 36 times.
|
80 | if (g_strcmp0 (method_name, "HoldProfile") == 0) { |
936 | 44 | g_autoptr(GError) local_error = NULL; | |
937 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 42 times.
|
44 | if (!check_action_permission (data, |
938 | 44 | g_dbus_method_invocation_get_sender (invocation), | |
939 | POWER_PROFILES_POLICY_NAMESPACE ".hold-profile", | ||
940 | &local_error)) { | ||
941 | 2 | g_dbus_method_invocation_return_gerror (invocation, local_error); | |
942 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | return; |
943 | } | ||
944 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
|
42 | hold_profile (data, parameters, invocation); |
945 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 | } else if (g_strcmp0 (method_name, "ReleaseProfile") == 0) { |
946 | 36 | release_profile (data, parameters, invocation); | |
947 | } else { | ||
948 | ✗ | g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, | |
949 | "No such method %s in interface %s", interface_name, | ||
950 | method_name); | ||
951 | } | ||
952 | } | ||
953 | |||
954 | |||
955 | static const GDBusInterfaceVTable interface_vtable = | ||
956 | { | ||
957 | handle_method_call, | ||
958 | handle_get_property, | ||
959 | handle_set_property | ||
960 | }; | ||
961 | |||
962 | typedef struct { | ||
963 | PpdApp *app; | ||
964 | GBusNameOwnerFlags flags; | ||
965 | GDBusInterfaceInfo *interface; | ||
966 | GDBusInterfaceInfo *legacy_interface; | ||
967 | } PpdBusOwnData; | ||
968 | |||
969 | static void | ||
970 | 2 | ppd_bus_own_data_free (PpdBusOwnData *data) | |
971 | { | ||
972 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | g_clear_pointer (&data->interface, g_dbus_interface_info_unref); |
973 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | g_clear_pointer (&data->legacy_interface, g_dbus_interface_info_unref); |
974 | 2 | g_free (data); | |
975 | 2 | } | |
976 | |||
977 | static void | ||
978 | 2 | name_lost_handler (GDBusConnection *connection, | |
979 | const gchar *name, | ||
980 | gpointer user_data) | ||
981 | { | ||
982 | 2 | PpdBusOwnData *data = user_data; | |
983 | 2 | PpdApp *app = data->app; | |
984 | |||
985 | 2 | g_warning ("power-profiles-daemon is already running, or it cannot own its D-Bus name. Verify installation."); | |
986 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (!app->was_started) |
987 | 2 | app->ret = EXIT_FAILURE; | |
988 | |||
989 | 2 | g_main_loop_quit (app->main_loop); | |
990 | 2 | } | |
991 | |||
992 | static void | ||
993 | 130 | legacy_name_acquired_handler (GDBusConnection *connection, | |
994 | const gchar *name, | ||
995 | gpointer user_data) | ||
996 | { | ||
997 | 130 | g_debug ("Name '%s' acquired", name); | |
998 | 130 | } | |
999 | |||
1000 | static void | ||
1001 | 130 | bus_acquired_handler (GDBusConnection *connection, | |
1002 | const gchar *name, | ||
1003 | gpointer user_data) | ||
1004 | { | ||
1005 | 130 | PpdBusOwnData *data = user_data; | |
1006 | |||
1007 | 130 | g_dbus_connection_register_object (connection, | |
1008 | POWER_PROFILES_DBUS_PATH, | ||
1009 | data->interface, | ||
1010 | &interface_vtable, | ||
1011 | 130 | data->app, | |
1012 | NULL, | ||
1013 | NULL); | ||
1014 | |||
1015 | 130 | g_dbus_connection_register_object (connection, | |
1016 | POWER_PROFILES_LEGACY_DBUS_PATH, | ||
1017 | data->legacy_interface, | ||
1018 | &interface_vtable, | ||
1019 | 130 | data->app, | |
1020 | NULL, | ||
1021 | NULL); | ||
1022 | |||
1023 | 130 | data->app->legacy_name_id = g_bus_own_name_on_connection (connection, | |
1024 | POWER_PROFILES_LEGACY_DBUS_NAME, | ||
1025 | data->flags, | ||
1026 | legacy_name_acquired_handler, | ||
1027 | name_lost_handler, | ||
1028 | data, | ||
1029 | NULL); | ||
1030 | |||
1031 | 130 | data->app->connection = g_object_ref (connection); | |
1032 | 130 | } | |
1033 | |||
1034 | static void | ||
1035 | 66 | upower_source_update_from_value (PpdApp *data, | |
1036 | GVariant *battery_val) | ||
1037 | { | ||
1038 | 66 | PpdPowerChangedReason reason; | |
1039 | |||
1040 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 44 times.
|
66 | if (!battery_val) |
1041 | reason = PPD_POWER_CHANGED_REASON_UNKNOWN; | ||
1042 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 14 times.
|
22 | else if (g_variant_get_boolean (battery_val)) |
1043 | reason = PPD_POWER_CHANGED_REASON_BATTERY; | ||
1044 | else | ||
1045 | 8 | reason = PPD_POWER_CHANGED_REASON_AC; | |
1046 | |||
1047 | 66 | upower_battery_set_power_changed_reason (data, reason); | |
1048 | 66 | } | |
1049 | |||
1050 | static void | ||
1051 | 54 | upower_source_update (PpdApp *data) | |
1052 | { | ||
1053 | 108 | g_autoptr(GVariant) battery_val = NULL; | |
1054 | |||
1055 | 54 | battery_val = g_dbus_proxy_get_cached_property (data->upower_proxy, "OnBattery"); | |
1056 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 44 times.
|
54 | upower_source_update_from_value (data, battery_val); |
1057 | 54 | } | |
1058 | |||
1059 | static void | ||
1060 | 10 | upower_battery_changed (PpdApp *data, gdouble level) | |
1061 | { | ||
1062 | 10 | g_info ("Battery level changed to %f", level); | |
1063 | |||
1064 |
2/2✓ Branch 1 taken 30 times.
✓ Branch 2 taken 10 times.
|
40 | for (guint i = 0; i < data->actions->len; i++) { |
1065 | 30 | g_autoptr(GError) error = NULL; | |
1066 | 30 | PpdAction *action; | |
1067 | |||
1068 | 30 | action = g_ptr_array_index (data->actions, i); | |
1069 | |||
1070 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
|
30 | if (!ppd_action_battery_changed (action, level, &error)) { |
1071 | ✗ | g_warning ("failed to update action %s: %s", | |
1072 | ppd_action_get_action_name (action), | ||
1073 | error->message); | ||
1074 | ✗ | g_clear_error (&error); | |
1075 | ✗ | continue; | |
1076 | } | ||
1077 | } | ||
1078 | |||
1079 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if (PPD_IS_DRIVER_CPU (data->cpu_driver)) { |
1080 | ✗ | g_autoptr(GError) error = NULL; | |
1081 | |||
1082 | ✗ | if (!ppd_driver_battery_changed (PPD_DRIVER (data->cpu_driver), level, &error)) { | |
1083 | ✗ | g_warning ("failed to update driver %s: %s", | |
1084 | ppd_driver_get_driver_name (PPD_DRIVER (data->cpu_driver)), | ||
1085 | error->message); | ||
1086 | } | ||
1087 | } | ||
1088 | |||
1089 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | if (PPD_IS_DRIVER_PLATFORM (data->platform_driver)) { |
1090 | 10 | g_autoptr(GError) error = NULL; | |
1091 | |||
1092 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if (!ppd_driver_battery_changed (PPD_DRIVER (data->platform_driver), level, &error)) { |
1093 | ✗ | g_warning ("failed to update driver %s: %s", | |
1094 | ppd_driver_get_driver_name (PPD_DRIVER (data->platform_driver)), | ||
1095 | error->message); | ||
1096 | } | ||
1097 | } | ||
1098 | 10 | } | |
1099 | |||
1100 | static void | ||
1101 | 8 | upower_battery_update (PpdApp *data) | |
1102 | { | ||
1103 | 16 | g_autoptr(GVariant) val = NULL; | |
1104 | |||
1105 | 8 | val = g_dbus_proxy_get_cached_property (data->upower_display_proxy, "Percentage"); | |
1106 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
|
8 | if (val) |
1107 | 2 | upower_battery_changed(data, g_variant_get_double (val)); | |
1108 | 8 | } | |
1109 | |||
1110 | static void | ||
1111 | 29 | upower_properties_changed (GDBusProxy *proxy, | |
1112 | GVariant *changed_properties, | ||
1113 | GStrv invalidated_properties, | ||
1114 | PpdApp *data) | ||
1115 | { | ||
1116 | 58 | g_auto(GVariantDict) props_dict = G_VARIANT_DICT_INIT (changed_properties); | |
1117 | 29 | g_autoptr(GVariant) battery_val = NULL; | |
1118 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 17 times.
|
29 | g_autoptr(GVariant) percent_val = NULL; |
1119 | |||
1120 | 29 | battery_val = g_variant_dict_lookup_value (&props_dict, "OnBattery", | |
1121 | G_VARIANT_TYPE_BOOLEAN); | ||
1122 | |||
1123 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 17 times.
|
29 | if (battery_val) |
1124 | 12 | upower_source_update_from_value (data, battery_val); | |
1125 | |||
1126 | 29 | percent_val = g_variant_dict_lookup_value (&props_dict, "Percentage", | |
1127 | G_VARIANT_TYPE_DOUBLE); | ||
1128 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 21 times.
|
29 | if (percent_val) |
1129 | 8 | upower_battery_changed (data, g_variant_get_double (percent_val)); | |
1130 | 29 | } | |
1131 | |||
1132 | static void | ||
1133 | 209 | upower_battery_set_power_changed_reason (PpdApp *data, | |
1134 | PpdPowerChangedReason reason) | ||
1135 | { | ||
1136 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 169 times.
|
209 | if (data->power_changed_reason == reason) |
1137 | return; | ||
1138 | |||
1139 | 40 | data->power_changed_reason = reason; | |
1140 | 40 | g_info ("Power Changed because of reason %s", | |
1141 | ppd_power_changed_reason_to_str (reason)); | ||
1142 | |||
1143 |
2/2✓ Branch 1 taken 48 times.
✓ Branch 2 taken 40 times.
|
88 | for (guint i = 0; i < data->actions->len; i++) { |
1144 | 48 | g_autoptr(GError) error = NULL; | |
1145 | 48 | PpdAction *action; | |
1146 | |||
1147 | 48 | action = g_ptr_array_index (data->actions, i); | |
1148 | |||
1149 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
|
48 | if (!ppd_action_power_changed (action, reason, &error)) { |
1150 | ✗ | g_warning ("failed to update action %s: %s", | |
1151 | ppd_action_get_action_name (action), | ||
1152 | error->message); | ||
1153 | ✗ | g_clear_error (&error); | |
1154 | ✗ | continue; | |
1155 | } | ||
1156 | } | ||
1157 | |||
1158 |
2/2✓ Branch 1 taken 36 times.
✓ Branch 2 taken 4 times.
|
40 | if (PPD_IS_DRIVER_CPU (data->cpu_driver)) { |
1159 | 36 | g_autoptr(GError) error = NULL; | |
1160 | |||
1161 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
|
36 | if (!ppd_driver_power_changed (PPD_DRIVER (data->cpu_driver), reason, &error)) { |
1162 | ✗ | g_warning ("failed to update driver %s: %s", | |
1163 | ppd_driver_get_driver_name (PPD_DRIVER (data->cpu_driver)), | ||
1164 | error->message); | ||
1165 | } | ||
1166 | } | ||
1167 | |||
1168 |
1/2✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
|
40 | if (PPD_IS_DRIVER_PLATFORM (data->platform_driver)) { |
1169 | 40 | g_autoptr(GError) error = NULL; | |
1170 | |||
1171 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
|
40 | if (!ppd_driver_power_changed (PPD_DRIVER (data->platform_driver), reason, &error)) { |
1172 | ✗ | g_warning ("failed to update driver %s: %s", | |
1173 | ppd_driver_get_driver_name (PPD_DRIVER (data->platform_driver)), | ||
1174 | error->message); | ||
1175 | } | ||
1176 | } | ||
1177 | } | ||
1178 | |||
1179 | static void | ||
1180 | 15 | upower_name_owner_changed (GObject *object, | |
1181 | GParamSpec *pspec, | ||
1182 | gpointer user_data) | ||
1183 | { | ||
1184 | 15 | PpdApp *data = user_data; | |
1185 | 15 | GDBusProxy *upower_proxy = G_DBUS_PROXY (object); | |
1186 | 15 | g_autofree char *name_owner = NULL; | |
1187 | |||
1188 | 15 | name_owner = g_dbus_proxy_get_name_owner (upower_proxy); | |
1189 | |||
1190 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7 times.
|
15 | if (name_owner != NULL) { |
1191 | 8 | g_debug ("%s appeared", UPOWER_DBUS_NAME); | |
1192 | 8 | upower_source_update (data); | |
1193 | 8 | return; | |
1194 | } | ||
1195 | |||
1196 | 7 | g_debug ("%s vanished", UPOWER_DBUS_NAME); | |
1197 | 7 | upower_battery_set_power_changed_reason (data, PPD_POWER_CHANGED_REASON_UNKNOWN); | |
1198 | } | ||
1199 | |||
1200 | static void | ||
1201 | 46 | on_upower_proxy_cb (GObject *source_object, | |
1202 | GAsyncResult *res, | ||
1203 | gpointer user_data) | ||
1204 | { | ||
1205 | 46 | PpdApp *data = user_data; | |
1206 | 46 | g_autoptr(GDBusProxy) upower_proxy = NULL; | |
1207 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
46 | g_autoptr(GError) error = NULL; |
1208 | |||
1209 | 46 | upower_proxy = g_dbus_proxy_new_finish (res, &error); | |
1210 | |||
1211 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
|
46 | if (upower_proxy == NULL) { |
1212 | ✗ | if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) | |
1213 | return; | ||
1214 | |||
1215 | ✗ | g_warning ("failed to connect to upower: %s", error->message); | |
1216 | ✗ | return; | |
1217 | } | ||
1218 | |||
1219 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | g_return_if_fail (data->upower_proxy == NULL); |
1220 | 46 | data->upower_proxy = g_steal_pointer (&upower_proxy); | |
1221 | |||
1222 | 46 | data->upower_properties_id = g_signal_connect (data->upower_proxy, | |
1223 | "g-properties-changed", | ||
1224 | G_CALLBACK (upower_properties_changed), | ||
1225 | data); | ||
1226 | |||
1227 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | if (!data->upower_display_watch_id) { |
1228 | 46 | data->upower_watch_id = g_signal_connect (data->upower_proxy, | |
1229 | "notify::g-name-owner", | ||
1230 | G_CALLBACK (upower_name_owner_changed), | ||
1231 | data); | ||
1232 | } | ||
1233 | |||
1234 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
|
46 | upower_source_update (data); |
1235 | } | ||
1236 | |||
1237 | static void | ||
1238 | 8 | on_upower_display_proxy_cb (GObject *source_object, | |
1239 | GAsyncResult *res, | ||
1240 | gpointer user_data) | ||
1241 | { | ||
1242 | 8 | PpdApp *data = user_data; | |
1243 | 8 | g_autoptr(GDBusProxy) proxy = NULL; | |
1244 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
8 | g_autoptr(GError) error = NULL; |
1245 | |||
1246 | 8 | proxy = g_dbus_proxy_new_finish (res, &error); | |
1247 | |||
1248 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (proxy == NULL) { |
1249 | ✗ | if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) | |
1250 | return; | ||
1251 | |||
1252 | ✗ | g_warning ("failed to connect to upower: %s", error->message); | |
1253 | ✗ | return; | |
1254 | } | ||
1255 | |||
1256 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | g_return_if_fail (data->upower_display_proxy == NULL); |
1257 | 8 | data->upower_display_proxy = g_steal_pointer (&proxy); | |
1258 | |||
1259 | 8 | data->upower_display_properties_id = g_signal_connect (data->upower_display_proxy, | |
1260 | "g-properties-changed", | ||
1261 | G_CALLBACK (upower_properties_changed), | ||
1262 | data); | ||
1263 | |||
1264 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (!data->upower_watch_id) { |
1265 | ✗ | data->upower_display_watch_id = g_signal_connect (data->upower_display_proxy, | |
1266 | "notify::g-name-owner", | ||
1267 | G_CALLBACK (upower_name_owner_changed), | ||
1268 | data); | ||
1269 | } | ||
1270 | |||
1271 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | upower_battery_update (data); |
1272 | } | ||
1273 | |||
1274 | static void | ||
1275 | 4 | on_logind_prepare_for_sleep_cb (GDBusConnection *connection, | |
1276 | const gchar *sender_name, | ||
1277 | const gchar *object_path, | ||
1278 | const gchar *interface_name, | ||
1279 | const gchar *signal_name, | ||
1280 | GVariant *parameters, | ||
1281 | gpointer user_data) | ||
1282 | { | ||
1283 | 4 | PpdApp *data = user_data; | |
1284 | 4 | gboolean start; | |
1285 | |||
1286 | 4 | g_variant_get (parameters, "(b)", &start); | |
1287 | |||
1288 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | if (start) |
1289 | 2 | g_debug ("System preparing for suspend"); | |
1290 | else | ||
1291 | 2 | g_debug ("System woke up from suspend"); | |
1292 | |||
1293 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | if (PPD_IS_DRIVER_CPU (data->cpu_driver)) { |
1294 | 4 | g_autoptr(GError) error = NULL; | |
1295 | |||
1296 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (!ppd_driver_prepare_to_sleep (PPD_DRIVER (data->cpu_driver), start, &error)) { |
1297 | ✗ | g_warning ("failed to notify driver %s: %s", | |
1298 | ppd_driver_get_driver_name (PPD_DRIVER (data->cpu_driver)), | ||
1299 | error->message); | ||
1300 | } | ||
1301 | } | ||
1302 | |||
1303 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | if (PPD_IS_DRIVER_PLATFORM (data->platform_driver)) { |
1304 | 4 | g_autoptr(GError) error = NULL; | |
1305 | |||
1306 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (!ppd_driver_prepare_to_sleep (PPD_DRIVER (data->platform_driver), start, &error)) { |
1307 | ✗ | g_warning ("failed to notify driver %s: %s", | |
1308 | ppd_driver_get_driver_name (PPD_DRIVER (data->platform_driver)), | ||
1309 | error->message); | ||
1310 | } | ||
1311 | } | ||
1312 | 4 | } | |
1313 | |||
1314 | static gboolean | ||
1315 | 134 | has_required_drivers (PpdApp *data) | |
1316 | { | ||
1317 |
3/4✓ Branch 1 taken 94 times.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 94 times.
|
228 | if (!PPD_IS_DRIVER_CPU (data->cpu_driver) && |
1318 | 94 | !PPD_IS_DRIVER_PLATFORM (data->platform_driver)) | |
1319 | return FALSE; | ||
1320 | |||
1321 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 134 times.
|
134 | if (!get_profile_available (data, PPD_PROFILE_BALANCED | PPD_PROFILE_POWER_SAVER)) |
1322 | return FALSE; | ||
1323 | |||
1324 | return TRUE; | ||
1325 | } | ||
1326 | |||
1327 | static void | ||
1328 | 4 | restart_profile_drivers (PpdApp *data) | |
1329 | { | ||
1330 | 4 | stop_profile_drivers (data); | |
1331 | 4 | start_profile_drivers (data); | |
1332 | } | ||
1333 | |||
1334 | static void | ||
1335 | 4 | driver_probe_request_cb (PpdDriver *driver, | |
1336 | gpointer user_data) | ||
1337 | { | ||
1338 | 4 | PpdApp *data = user_data; | |
1339 | |||
1340 | 4 | restart_profile_drivers (data); | |
1341 | 4 | } | |
1342 | |||
1343 | static void | ||
1344 | 272 | disconnect_array_objects_signals_by_data (GPtrArray *array, | |
1345 | void *data) | ||
1346 | { | ||
1347 |
2/2✓ Branch 0 taken 156 times.
✓ Branch 1 taken 272 times.
|
428 | for (guint i = 0; i < array->len; ++i) { |
1348 | 156 | GObject *object = g_ptr_array_index (array, i); | |
1349 | |||
1350 | 156 | g_signal_handlers_disconnect_by_data (object, data); | |
1351 | } | ||
1352 | 272 | } | |
1353 | |||
1354 | static void | ||
1355 | 544 | maybe_disconnect_object_by_data (void *object, | |
1356 | void *data) | ||
1357 | { | ||
1358 |
2/2✓ Branch 0 taken 228 times.
✓ Branch 1 taken 316 times.
|
544 | if (!G_IS_OBJECT (object)) |
1359 | return; | ||
1360 | |||
1361 | 228 | g_signal_handlers_disconnect_by_data (object, data); | |
1362 | } | ||
1363 | |||
1364 | static void | ||
1365 | 136 | stop_profile_drivers (PpdApp *data) | |
1366 | { | ||
1367 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 114 times.
|
136 | if (data->logind_sleep_signal_id) { |
1368 | 22 | g_dbus_connection_signal_unsubscribe (data->connection, data->logind_sleep_signal_id); | |
1369 | 22 | data->logind_sleep_signal_id = 0; | |
1370 | } | ||
1371 | |||
1372 | 136 | upower_battery_set_power_changed_reason (data, PPD_POWER_CHANGED_REASON_UNKNOWN); | |
1373 | 136 | release_all_profile_holds (data); | |
1374 | 136 | g_cancellable_cancel (data->cancellable); | |
1375 | 136 | disconnect_array_objects_signals_by_data (data->probed_drivers, data); | |
1376 | 136 | g_ptr_array_set_size (data->probed_drivers, 0); | |
1377 | 136 | disconnect_array_objects_signals_by_data (data->actions, data); | |
1378 | 136 | g_ptr_array_set_size (data->actions, 0); | |
1379 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 90 times.
|
136 | g_clear_signal_handler (&data->upower_watch_id, data->upower_proxy); |
1380 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 90 times.
|
136 | g_clear_signal_handler (&data->upower_properties_id, data->upower_proxy); |
1381 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
|
136 | g_clear_signal_handler (&data->upower_display_watch_id, data->upower_display_proxy); |
1382 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 128 times.
|
136 | g_clear_signal_handler (&data->upower_display_properties_id, data->upower_display_proxy); |
1383 |
2/2✓ Branch 0 taken 134 times.
✓ Branch 1 taken 2 times.
|
136 | g_clear_object (&data->cancellable); |
1384 | 136 | maybe_disconnect_object_by_data (data->upower_proxy, data); | |
1385 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 90 times.
|
136 | g_clear_object (&data->upower_proxy); |
1386 | 136 | maybe_disconnect_object_by_data (data->upower_display_proxy, data); | |
1387 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 128 times.
|
136 | g_clear_object (&data->upower_display_proxy); |
1388 | 136 | maybe_disconnect_object_by_data (data->cpu_driver, data); | |
1389 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 96 times.
|
136 | g_clear_object (&data->cpu_driver); |
1390 | 136 | maybe_disconnect_object_by_data (data->platform_driver, data); | |
1391 |
2/2✓ Branch 0 taken 134 times.
✓ Branch 1 taken 2 times.
|
136 | g_clear_object (&data->platform_driver); |
1392 | 136 | } | |
1393 | |||
1394 | static gboolean | ||
1395 | 402 | action_blocked (PpdApp *app, PpdAction *action) | |
1396 | { | ||
1397 | 402 | const gchar *action_name = ppd_action_get_action_name (action); | |
1398 | 402 | gboolean blocked; | |
1399 | |||
1400 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 396 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
|
402 | if (app->debug_options->blocked_actions == NULL || g_strv_length (app->debug_options->blocked_actions) == 0) |
1401 | 396 | return FALSE; | |
1402 | |||
1403 | 6 | blocked = g_strv_contains ((const gchar *const *) app->debug_options->blocked_actions, action_name); | |
1404 | |||
1405 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
|
6 | if (blocked) |
1406 | 2 | g_debug ("Action '%s' is blocked", action_name); | |
1407 | return blocked; | ||
1408 | } | ||
1409 | |||
1410 | static gboolean | ||
1411 | 670 | driver_blocked (PpdApp *app, PpdDriver *driver) | |
1412 | { | ||
1413 | 670 | const gchar *driver_name = ppd_driver_get_driver_name (driver); | |
1414 | 670 | gboolean blocked; | |
1415 | |||
1416 |
3/4✓ Branch 0 taken 20 times.
✓ Branch 1 taken 650 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
|
670 | if (app->debug_options->blocked_drivers == NULL || g_strv_length (app->debug_options->blocked_drivers) == 0) |
1417 | 650 | return FALSE; | |
1418 | |||
1419 | 20 | blocked = g_strv_contains ((const gchar *const *) app->debug_options->blocked_drivers, driver_name); | |
1420 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 14 times.
|
20 | if (blocked) |
1421 | 6 | g_debug ("Driver '%s' is blocked", driver_name); | |
1422 | return blocked; | ||
1423 | } | ||
1424 | |||
1425 | static void | ||
1426 | 134 | start_profile_drivers (PpdApp *data) | |
1427 | { | ||
1428 | 134 | guint i; | |
1429 | 134 | g_autoptr(GError) initial_error = NULL; | |
1430 | 134 | gboolean needs_battery_state_monitor = FALSE; | |
1431 | 134 | gboolean needs_battery_change_monitor = FALSE; | |
1432 | 134 | gboolean needs_suspend_monitor = FALSE; | |
1433 | |||
1434 | 134 | data->cancellable = g_cancellable_new (); | |
1435 | |||
1436 |
2/2✓ Branch 0 taken 1072 times.
✓ Branch 1 taken 134 times.
|
1206 | for (i = 0; i < G_N_ELEMENTS (objects); i++) { |
1437 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
1072 | g_autoptr(GObject) object = NULL; |
1438 | |||
1439 | 1072 | object = g_object_new (objects[i] (), NULL); | |
1440 | |||
1441 |
2/2✓ Branch 1 taken 670 times.
✓ Branch 2 taken 402 times.
|
1072 | if (PPD_IS_DRIVER (object)) { |
1442 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
1742 | g_autoptr(PpdDriver) driver = PPD_DRIVER (g_steal_pointer (&object)); |
1443 | 670 | PpdProfile profiles; | |
1444 | 670 | PpdProbeResult result; | |
1445 | |||
1446 | 670 | g_debug ("Handling driver '%s'", ppd_driver_get_driver_name (driver)); | |
1447 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 664 times.
|
670 | if (driver_blocked (data, driver)) { |
1448 | 6 | g_debug ("Driver '%s' is blocked, skipping", ppd_driver_get_driver_name (driver)); | |
1449 | 6 | continue; | |
1450 | } | ||
1451 | |||
1452 |
4/4✓ Branch 1 taken 64 times.
✓ Branch 2 taken 600 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 40 times.
|
664 | if (PPD_IS_DRIVER_CPU (data->cpu_driver) && PPD_IS_DRIVER_CPU (driver)) { |
1453 | 24 | g_debug ("CPU driver '%s' already probed, skipping driver '%s'", | |
1454 | ppd_driver_get_driver_name (PPD_DRIVER (data->cpu_driver)), | ||
1455 | ppd_driver_get_driver_name (driver)); | ||
1456 | 24 | continue; | |
1457 | } | ||
1458 | |||
1459 |
4/4✓ Branch 1 taken 154 times.
✓ Branch 2 taken 486 times.
✓ Branch 4 taken 54 times.
✓ Branch 5 taken 100 times.
|
640 | if (PPD_IS_DRIVER_PLATFORM (data->platform_driver) && PPD_IS_DRIVER_PLATFORM (driver)) { |
1460 | 54 | g_debug ("Platform driver '%s' already probed, skipping driver '%s'", | |
1461 | ppd_driver_get_driver_name (PPD_DRIVER (data->platform_driver)), | ||
1462 | ppd_driver_get_driver_name (driver)); | ||
1463 | 54 | continue; | |
1464 | } | ||
1465 | |||
1466 | 586 | profiles = ppd_driver_get_profiles (driver); | |
1467 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 586 times.
|
586 | if (!(profiles & PPD_PROFILE_ALL)) { |
1468 | ✗ | g_warning ("Profile Driver '%s' implements invalid profiles '0x%X'", | |
1469 | ppd_driver_get_driver_name (driver), | ||
1470 | profiles); | ||
1471 | ✗ | continue; | |
1472 | } | ||
1473 | |||
1474 | 586 | result = ppd_driver_probe (driver); | |
1475 |
2/2✓ Branch 0 taken 408 times.
✓ Branch 1 taken 178 times.
|
586 | if (result == PPD_PROBE_RESULT_FAIL) { |
1476 | 408 | g_debug ("probe () failed for driver %s, skipping", | |
1477 | ppd_driver_get_driver_name (driver)); | ||
1478 | 408 | continue; | |
1479 | } | ||
1480 | |||
1481 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 174 times.
|
178 | if (result == PPD_PROBE_RESULT_DEFER) { |
1482 | 4 | g_signal_connect (G_OBJECT (driver), "probe-request", | |
1483 | G_CALLBACK (driver_probe_request_cb), data); | ||
1484 | 4 | g_ptr_array_add (data->probed_drivers, g_steal_pointer (&driver)); | |
1485 | 4 | continue; | |
1486 | } | ||
1487 | |||
1488 |
2/2✓ Branch 1 taken 40 times.
✓ Branch 2 taken 134 times.
|
174 | if (PPD_IS_DRIVER_CPU (driver)) |
1489 | 40 | g_set_object (&data->cpu_driver, PPD_DRIVER_CPU (driver)); | |
1490 |
1/2✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
|
134 | else if (PPD_IS_DRIVER_PLATFORM (driver)) |
1491 | 134 | g_set_object (&data->platform_driver, PPD_DRIVER_PLATFORM (driver)); | |
1492 | else | ||
1493 | ✗ | g_return_if_reached (); | |
1494 | |||
1495 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 134 times.
|
174 | if (PPD_DRIVER_GET_CLASS (driver)->power_changed != NULL) |
1496 | 40 | needs_battery_state_monitor = TRUE; | |
1497 | |||
1498 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
|
174 | if (PPD_DRIVER_GET_CLASS (driver)->battery_changed != NULL) |
1499 | ✗ | needs_battery_change_monitor = TRUE; | |
1500 | |||
1501 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 150 times.
|
174 | if (PPD_DRIVER_GET_CLASS (driver)->prepare_to_sleep != NULL) |
1502 | 24 | needs_suspend_monitor = TRUE; | |
1503 | |||
1504 | 174 | g_info ("Driver '%s' loaded", ppd_driver_get_driver_name (driver)); | |
1505 | |||
1506 | 174 | g_signal_connect (G_OBJECT (driver), "notify::performance-degraded", | |
1507 | G_CALLBACK (driver_performance_degraded_changed_cb), data); | ||
1508 | 174 | g_signal_connect (G_OBJECT (driver), "profile-changed", | |
1509 | G_CALLBACK (driver_profile_changed_cb), data); | ||
1510 | 174 | continue; | |
1511 | } | ||
1512 | |||
1513 |
1/2✓ Branch 1 taken 402 times.
✗ Branch 2 not taken.
|
402 | if (PPD_IS_ACTION (object)) { |
1514 | 402 | g_autoptr(PpdAction) action = PPD_ACTION (g_steal_pointer (&object)); | |
1515 | |||
1516 | 402 | g_debug ("Handling action '%s'", ppd_action_get_action_name (action)); | |
1517 | |||
1518 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 400 times.
|
402 | if (action_blocked (data, action)) { |
1519 | 2 | g_debug ("Action '%s' is blocked, skipping", ppd_action_get_action_name (action)); | |
1520 | 2 | continue; | |
1521 | } | ||
1522 | |||
1523 |
2/2✓ Branch 1 taken 248 times.
✓ Branch 2 taken 152 times.
|
400 | if (ppd_action_probe (action) == PPD_PROBE_RESULT_FAIL) { |
1524 | 248 | g_debug ("probe () failed for action '%s', skipping", | |
1525 | ppd_action_get_action_name (action)); | ||
1526 | 248 | continue; | |
1527 | } | ||
1528 | |||
1529 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 144 times.
|
152 | if (PPD_ACTION_GET_CLASS (action)->power_changed != NULL) |
1530 | 8 | needs_battery_state_monitor = TRUE; | |
1531 | |||
1532 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 144 times.
|
152 | if (PPD_ACTION_GET_CLASS (action)->battery_changed != NULL) |
1533 | 8 | needs_battery_change_monitor = TRUE; | |
1534 | |||
1535 | 152 | g_info ("Action '%s' loaded", ppd_action_get_action_name (action)); | |
1536 | 152 | g_ptr_array_add (data->actions, g_steal_pointer (&action)); | |
1537 | 152 | continue; | |
1538 | } | ||
1539 | |||
1540 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
1072 | g_return_if_reached (); |
1541 | } | ||
1542 | |||
1543 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 134 times.
|
134 | if (!has_required_drivers (data)) { |
1544 | ✗ | data->ret = EXIT_FAILURE; | |
1545 | ✗ | g_warning ("Some non-optional profile drivers are missing, programmer error"); | |
1546 | ✗ | g_main_loop_quit (data->main_loop); | |
1547 | } | ||
1548 | |||
1549 | /* Set initial state either from configuration, or using the currently selected profile */ | ||
1550 | 134 | apply_configuration (data); | |
1551 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 132 times.
|
134 | if (!activate_target_profile (data, data->active_profile, PPD_PROFILE_ACTIVATION_REASON_RESET, &initial_error)) |
1552 | 2 | g_warning ("Failed to activate initial profile: %s", initial_error->message); | |
1553 | |||
1554 | 134 | send_dbus_event (data, PROP_ALL); | |
1555 | 134 | data->was_started = TRUE; | |
1556 | |||
1557 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 132 times.
|
134 | if (data->debug_options->disable_upower) { |
1558 | 2 | g_debug ("upower is disabled, let's skip it"); | |
1559 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 86 times.
|
132 | } else if (needs_battery_state_monitor || needs_battery_change_monitor) { |
1560 | /* start watching for power changes */ | ||
1561 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | if (needs_battery_state_monitor) { |
1562 | 46 | g_debug ("Battery state monitor required, connecting to upower..."); | |
1563 | 46 | g_dbus_proxy_new (data->connection, | |
1564 | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | | ||
1565 | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, | ||
1566 | NULL, | ||
1567 | UPOWER_DBUS_NAME, | ||
1568 | UPOWER_DBUS_PATH, | ||
1569 | UPOWER_DBUS_INTERFACE, | ||
1570 | data->cancellable, | ||
1571 | on_upower_proxy_cb, | ||
1572 | data); | ||
1573 | } | ||
1574 | |||
1575 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 38 times.
|
46 | if (needs_battery_change_monitor) { |
1576 | 8 | g_debug ("Battery change monitor required, connecting to upower..."); | |
1577 | 8 | g_dbus_proxy_new (data->connection, | |
1578 | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | | ||
1579 | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, | ||
1580 | NULL, | ||
1581 | UPOWER_DBUS_NAME, | ||
1582 | UPOWER_DBUS_DISPLAY_DEVICE_PATH, | ||
1583 | UPOWER_DBUS_DEVICE_INTERFACE, | ||
1584 | data->cancellable, | ||
1585 | on_upower_display_proxy_cb, | ||
1586 | data); | ||
1587 | } | ||
1588 | } else { | ||
1589 | 86 | g_debug ("No battery state monitor required by any driver, let's skip it"); | |
1590 | } | ||
1591 | |||
1592 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 132 times.
|
134 | if (data->debug_options->disable_logind) { |
1593 | 2 | g_debug ("logind is disabled, let's skip it"); | |
1594 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 110 times.
|
132 | } else if (needs_suspend_monitor) { |
1595 | 22 | g_debug ("Suspension state monitor required, monitoring logind..."); | |
1596 | 22 | data->logind_sleep_signal_id = | |
1597 | 22 | g_dbus_connection_signal_subscribe (data->connection, | |
1598 | LOGIND_DBUS_NAME, | ||
1599 | LOGIND_DBUS_INTERFACE, | ||
1600 | "PrepareForSleep", | ||
1601 | LOGIND_DBUS_PATH, | ||
1602 | NULL, | ||
1603 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
1604 | on_logind_prepare_for_sleep_cb, | ||
1605 | data, | ||
1606 | NULL); | ||
1607 | } else { | ||
1608 | 110 | g_debug ("No suspension monitor required by any driver, let's skip it"); | |
1609 | } | ||
1610 | } | ||
1611 | |||
1612 | void | ||
1613 | ✗ | restart_profile_drivers_for_default_app (void) | |
1614 | { | ||
1615 | ✗ | restart_profile_drivers (ppd_app); | |
1616 | ✗ | } | |
1617 | |||
1618 | |||
1619 | static void | ||
1620 | 130 | name_acquired_handler (GDBusConnection *connection, | |
1621 | const gchar *name, | ||
1622 | gpointer user_data) | ||
1623 | { | ||
1624 | 130 | PpdBusOwnData *data = user_data; | |
1625 | |||
1626 | 130 | g_debug ("Name '%s' acquired", name); | |
1627 | |||
1628 | 130 | start_profile_drivers (data->app); | |
1629 | 130 | } | |
1630 | |||
1631 | static gboolean | ||
1632 | 132 | setup_dbus (PpdApp *data, | |
1633 | GError **error) | ||
1634 | { | ||
1635 | 264 | g_autoptr(GBytes) iface_data = NULL; | |
1636 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_autoptr(GBytes) legacy_iface_data = NULL; |
1637 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_autoptr(GDBusNodeInfo) introspection_data = NULL; |
1638 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_autoptr(GDBusNodeInfo) legacy_introspection_data = NULL; |
1639 | 132 | PpdBusOwnData *own_data; | |
1640 | |||
1641 | 132 | iface_data = g_resources_lookup_data (POWER_PROFILES_RESOURCES_PATH "/" | |
1642 | POWER_PROFILES_DBUS_NAME ".xml", | ||
1643 | G_RESOURCE_LOOKUP_FLAGS_NONE, | ||
1644 | error); | ||
1645 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | if (!iface_data) |
1646 | return FALSE; | ||
1647 | |||
1648 | 132 | legacy_iface_data = g_resources_lookup_data (POWER_PROFILES_RESOURCES_PATH "/" | |
1649 | POWER_PROFILES_LEGACY_DBUS_NAME ".xml", | ||
1650 | G_RESOURCE_LOOKUP_FLAGS_NONE, | ||
1651 | error); | ||
1652 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if (!legacy_iface_data) |
1653 | return FALSE; | ||
1654 | |||
1655 | 132 | introspection_data = g_dbus_node_info_new_for_xml (g_bytes_get_data (iface_data, NULL), | |
1656 | error); | ||
1657 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | if (!introspection_data) |
1658 | return FALSE; | ||
1659 | |||
1660 | 132 | legacy_introspection_data = g_dbus_node_info_new_for_xml (g_bytes_get_data (legacy_iface_data, NULL), | |
1661 | error); | ||
1662 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | if (!legacy_introspection_data) |
1663 | return FALSE; | ||
1664 | |||
1665 | 132 | own_data = g_new0 (PpdBusOwnData, 1); | |
1666 | 132 | own_data->app = data; | |
1667 | 132 | own_data->interface = g_dbus_interface_info_ref (introspection_data->interfaces[0]); | |
1668 | 132 | own_data->legacy_interface = g_dbus_interface_info_ref (legacy_introspection_data->interfaces[0]); | |
1669 | |||
1670 | 132 | own_data->flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT; | |
1671 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if (data->debug_options->replace) |
1672 | ✗ | own_data->flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE; | |
1673 | |||
1674 | 132 | data->name_id = g_bus_own_name (G_BUS_TYPE_SYSTEM, | |
1675 | POWER_PROFILES_DBUS_NAME, | ||
1676 | own_data->flags, | ||
1677 | bus_acquired_handler, | ||
1678 | name_acquired_handler, | ||
1679 | name_lost_handler, | ||
1680 | own_data, | ||
1681 | (GDestroyNotify) ppd_bus_own_data_free); | ||
1682 | |||
1683 | 132 | return TRUE; | |
1684 | } | ||
1685 | |||
1686 | static void | ||
1687 | 132 | free_app_data (PpdApp *data) | |
1688 | { | ||
1689 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | if (data == NULL) |
1690 | return; | ||
1691 | |||
1692 | 132 | stop_profile_drivers (data); | |
1693 | |||
1694 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_clear_handle_id (&data->name_id, g_bus_unown_name); |
1695 |
2/2✓ Branch 0 taken 130 times.
✓ Branch 1 taken 2 times.
|
132 | g_clear_handle_id (&data->legacy_name_id, g_bus_unown_name); |
1696 | |||
1697 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_clear_pointer (&data->debug_options, debug_options_free); |
1698 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_clear_pointer (&data->config_path, g_free); |
1699 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_clear_pointer (&data->config, g_key_file_unref); |
1700 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_clear_pointer (&data->probed_drivers, g_ptr_array_unref); |
1701 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_clear_pointer (&data->actions, g_ptr_array_unref); |
1702 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | g_clear_object (&data->cpu_driver); |
1703 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | g_clear_object (&data->platform_driver); |
1704 | 132 | g_hash_table_destroy (data->profile_holds); | |
1705 | |||
1706 |
2/2✓ Branch 0 taken 130 times.
✓ Branch 1 taken 2 times.
|
132 | g_clear_object (&data->auth); |
1707 | |||
1708 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_clear_pointer (&data->main_loop, g_main_loop_unref); |
1709 |
2/2✓ Branch 0 taken 130 times.
✓ Branch 1 taken 2 times.
|
132 | g_clear_object (&data->connection); |
1710 | 132 | g_free (data); | |
1711 | 132 | ppd_app = NULL; | |
1712 | } | ||
1713 | |||
1714 | 132 | G_DEFINE_AUTOPTR_CLEANUP_FUNC (PpdApp, free_app_data) | |
1715 | |||
1716 | void | ||
1717 | ✗ | main_loop_quit (void) | |
1718 | { | ||
1719 | ✗ | g_main_loop_quit (ppd_app->main_loop); | |
1720 | ✗ | } | |
1721 | |||
1722 | static inline gboolean | ||
1723 | 5610 | use_colored_ouput (void) | |
1724 | { | ||
1725 |
1/2✓ Branch 1 taken 5610 times.
✗ Branch 2 not taken.
|
5610 | if (g_getenv ("NO_COLOR")) |
1726 | return FALSE; | ||
1727 | 5610 | return isatty (fileno (stdout)); | |
1728 | } | ||
1729 | |||
1730 | static void | ||
1731 | 5614 | debug_handler_cb (const gchar *log_domain, | |
1732 | GLogLevelFlags log_level, | ||
1733 | const gchar *message, | ||
1734 | gpointer user_data) | ||
1735 | { | ||
1736 | 5614 | DebugOptions *data = user_data; | |
1737 | 5610 | g_autoptr(GString) domain = NULL; | |
1738 | 5614 | gboolean use_color; | |
1739 | 5614 | gint color; | |
1740 | |||
1741 | /* not in verbose mode */ | ||
1742 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5610 times.
|
5614 | if (log_level > data->log_level) |
1743 | 4 | return; | |
1744 | |||
1745 | 5610 | domain = g_string_new (log_domain); | |
1746 | 5610 | use_color = use_colored_ouput (); | |
1747 | |||
1748 |
2/2✓ Branch 0 taken 48436 times.
✓ Branch 1 taken 5610 times.
|
54046 | for (gsize i = domain->len; i < 15; i++) |
1749 |
1/2✓ Branch 0 taken 48436 times.
✗ Branch 1 not taken.
|
96872 | g_string_append_c (domain, ' '); |
1750 | 5610 | g_print ("%s", domain->str); | |
1751 | |||
1752 |
2/2✓ Branch 0 taken 5604 times.
✓ Branch 1 taken 6 times.
|
5610 | switch (log_level) { |
1753 | case G_LOG_LEVEL_ERROR: | ||
1754 | case G_LOG_LEVEL_CRITICAL: | ||
1755 | case G_LOG_LEVEL_WARNING: | ||
1756 | color = 31; /* red */ | ||
1757 | break; | ||
1758 | 5604 | default: | |
1759 | 5604 | color = 34; /* blue */ | |
1760 | 5604 | break; | |
1761 | } | ||
1762 | |||
1763 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5610 times.
|
5610 | if (use_color) |
1764 | ✗ | g_print ("%c[%dm%s\n%c[%dm", 0x1B, color, message, 0x1B, 0); | |
1765 | else | ||
1766 | 5610 | g_print ("%s\n", message); | |
1767 | } | ||
1768 | |||
1769 | static gboolean | ||
1770 | 130 | quit_signal_callback (gpointer user_data) | |
1771 | { | ||
1772 | 130 | PpdApp *data = user_data; | |
1773 | |||
1774 | 130 | g_main_loop_quit (data->main_loop); | |
1775 | 130 | return FALSE; | |
1776 | } | ||
1777 | |||
1778 | static gboolean | ||
1779 | 260 | verbose_arg_cb (const gchar *option_name, | |
1780 | const gchar *value, | ||
1781 | gpointer user_data, | ||
1782 | GError **error) | ||
1783 | { | ||
1784 | 260 | DebugOptions *data = user_data; | |
1785 | |||
1786 |
2/2✓ Branch 0 taken 130 times.
✓ Branch 1 taken 130 times.
|
260 | if (data->log_level == G_LOG_LEVEL_MESSAGE) { |
1787 | 130 | data->log_level = G_LOG_LEVEL_INFO; | |
1788 | 130 | return TRUE; | |
1789 | } | ||
1790 |
1/2✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
|
130 | if (data->log_level == G_LOG_LEVEL_INFO) { |
1791 | 130 | data->log_level = G_LOG_LEVEL_DEBUG; | |
1792 | 130 | return TRUE; | |
1793 | } | ||
1794 | ✗ | g_set_error_literal (error, | |
1795 | G_OPTION_ERROR, | ||
1796 | G_OPTION_ERROR_FAILED, | ||
1797 | "No further debug level supported"); | ||
1798 | ✗ | return FALSE; | |
1799 | } | ||
1800 | |||
1801 | static gboolean | ||
1802 | 132 | debug_pre_parse_hook (GOptionContext *context, | |
1803 | GOptionGroup *group, | ||
1804 | gpointer user_data, | ||
1805 | GError **error) | ||
1806 | { | ||
1807 | 132 | DebugOptions *data = user_data; | |
1808 | |||
1809 | 132 | const GOptionEntry options[] = { | |
1810 | { | ||
1811 | "verbose", | ||
1812 | 'v', | ||
1813 | G_OPTION_FLAG_NO_ARG, | ||
1814 | G_OPTION_ARG_CALLBACK, | ||
1815 | (GOptionArgFunc)verbose_arg_cb, | ||
1816 | "Show extra debugging information", | ||
1817 | NULL, | ||
1818 | }, | ||
1819 | { | ||
1820 | "replace", | ||
1821 | 'r', | ||
1822 | G_OPTION_FLAG_NONE, | ||
1823 | G_OPTION_ARG_NONE, | ||
1824 | 132 | &data->replace, | |
1825 | "Replace the running instance of power-profiles-daemon", | ||
1826 | NULL, | ||
1827 | }, | ||
1828 | { | ||
1829 | "block-driver", | ||
1830 | 0, | ||
1831 | G_OPTION_FLAG_NONE, | ||
1832 | G_OPTION_ARG_STRING_ARRAY, | ||
1833 | 132 | &data->blocked_drivers, | |
1834 | "Block driver(s) from loading", | ||
1835 | NULL, | ||
1836 | }, | ||
1837 | { | ||
1838 | "block-action", | ||
1839 | 0, | ||
1840 | G_OPTION_FLAG_NONE, | ||
1841 | G_OPTION_ARG_STRING_ARRAY, | ||
1842 | 132 | &data->blocked_actions, | |
1843 | "Block action(s) from loading", | ||
1844 | NULL, | ||
1845 | }, | ||
1846 | { | ||
1847 | "disable-upower", | ||
1848 | 0, | ||
1849 | G_OPTION_FLAG_NONE, | ||
1850 | G_OPTION_ARG_NONE, | ||
1851 | 132 | &data->disable_upower, | |
1852 | "Disable upower integration", | ||
1853 | NULL, | ||
1854 | }, | ||
1855 | { | ||
1856 | "disable-logind", | ||
1857 | 0, | ||
1858 | G_OPTION_FLAG_NONE, | ||
1859 | G_OPTION_ARG_NONE, | ||
1860 | 132 | &data->disable_logind, | |
1861 | "Disable logind integration", | ||
1862 | NULL, | ||
1863 | }, | ||
1864 | { NULL } | ||
1865 | }; | ||
1866 | 132 | g_option_group_add_entries (group, options); | |
1867 | |||
1868 | 132 | return TRUE; | |
1869 | } | ||
1870 | |||
1871 | static gboolean | ||
1872 | 132 | debug_post_parse_hook (GOptionContext *context, | |
1873 | GOptionGroup *group, | ||
1874 | gpointer user_data, | ||
1875 | GError **error) | ||
1876 | { | ||
1877 | 132 | DebugOptions *debug = (DebugOptions *)user_data; | |
1878 | |||
1879 | 132 | g_log_set_default_handler (debug_handler_cb, debug); | |
1880 | |||
1881 | 132 | return TRUE; | |
1882 | } | ||
1883 | |||
1884 | 132 | int main (int argc, char **argv) | |
1885 | { | ||
1886 | 132 | g_autoptr(DebugOptions) debug_options = g_new0 (DebugOptions, 1); | |
1887 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | g_autoptr(PpdApp) data = NULL; |
1888 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_autoptr(GOptionContext) option_context = NULL; |
1889 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | g_autoptr(GError) error = NULL; |
1890 | |||
1891 | 132 | debug_options->log_level = G_LOG_LEVEL_MESSAGE; | |
1892 | 132 | debug_options->group = g_option_group_new ("debug", | |
1893 | "Debugging Options", | ||
1894 | "Show debugging options", | ||
1895 | debug_options, | ||
1896 | NULL); | ||
1897 | 132 | g_option_group_set_parse_hooks (debug_options->group, | |
1898 | debug_pre_parse_hook, | ||
1899 | debug_post_parse_hook); | ||
1900 | |||
1901 | 132 | setlocale (LC_ALL, ""); | |
1902 | 132 | option_context = g_option_context_new (""); | |
1903 | 132 | g_option_context_add_group (option_context, debug_options->group); | |
1904 | |||
1905 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 132 times.
|
132 | if (!g_option_context_parse (option_context, &argc, &argv, &error)) { |
1906 | ✗ | g_print ("Failed to parse arguments: %s\n", error->message); | |
1907 | ✗ | return EXIT_FAILURE; | |
1908 | } | ||
1909 | |||
1910 | 132 | data = g_new0 (PpdApp, 1); | |
1911 | 132 | data->main_loop = g_main_loop_new (NULL, TRUE); | |
1912 | 132 | data->auth = polkit_authority_get_sync (NULL, NULL); | |
1913 | 132 | data->probed_drivers = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); | |
1914 | 132 | data->actions = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); | |
1915 | 132 | data->profile_holds = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) profile_hold_free); | |
1916 | 132 | data->active_profile = PPD_PROFILE_BALANCED; | |
1917 | 132 | data->selected_profile = PPD_PROFILE_BALANCED; | |
1918 | 132 | data->debug_options = g_steal_pointer(&debug_options); | |
1919 | |||
1920 | 132 | g_unix_signal_add (SIGTERM, quit_signal_callback, data); | |
1921 | 132 | g_unix_signal_add (SIGINT, quit_signal_callback, data); | |
1922 | |||
1923 | 132 | g_info ("Starting power-profiles-daemon version "VERSION); | |
1924 | |||
1925 | 132 | load_configuration (data); | |
1926 | 132 | ppd_app = data; | |
1927 | |||
1928 | /* Set up D-Bus */ | ||
1929 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 132 times.
|
132 | if (!setup_dbus (data, &error)) { |
1930 | ✗ | g_error ("Failed to start dbus: %s", error->message); | |
1931 | return EXIT_FAILURE; | ||
1932 | } | ||
1933 | |||
1934 | 132 | g_main_loop_run (data->main_loop); | |
1935 | |||
1936 | 132 | return data->ret; | |
1937 | } | ||
1938 |