[gnome-settings-daemon] rfkill: Handle Airplane mode for Wireless WAN



commit 45cc86c410dac7c051c123934dfc2a6a49414e0b
Author: Mohammed Sadiq <sadiq sadiqpk org>
Date:   Tue Jun 11 18:16:01 2019 +0530

    rfkill: Handle Airplane mode for Wireless WAN
    
    This commit allows handling airplane mode for WWAN interfaces
    which will be handled via rfkill and Modem Manager.
    
    The following boolean DBUS properties are added:
    
    * WwanAirplaneMode: read/write
    * WwanHardwareAirplaneMode: read
    * WwanHasAirplaneMode: read
    
    https://gitlab.gnome.org/GNOME/gnome-settings-daemon/issues/414

 plugins/rfkill/gsd-rfkill-manager.c | 144 ++++++++++++++++++++++++++++++++++--
 1 file changed, 138 insertions(+), 6 deletions(-)
---
diff --git a/plugins/rfkill/gsd-rfkill-manager.c b/plugins/rfkill/gsd-rfkill-manager.c
index 5ad560eb..4c24c733 100644
--- a/plugins/rfkill/gsd-rfkill-manager.c
+++ b/plugins/rfkill/gsd-rfkill-manager.c
@@ -38,6 +38,16 @@
  *        "org.gnome.SettingsDaemon.Rfkill" \
  *        "BluetoothAirplaneMode" \
  *        "<true|false>"
+ *
+ * and
+ *    gdbus call \
+ *        --session \
+ *        --dest org.gnome.SettingsDaemon.Rfkill \
+ *        --object-path /org/gnome/SettingsDaemon/Rfkill \
+ *        --method org.freedesktop.DBus.Properties.Set \
+ *        "org.gnome.SettingsDaemon.Rfkill" \
+ *        "WwanAirplaneMode" \
+ *        "<true|false>"
  */
 
 #include "config.h"
@@ -62,6 +72,7 @@ struct _GsdRfkillManager
         CcRfkillGlib            *rfkill;
         GHashTable              *killswitches;
         GHashTable              *bt_killswitches;
+        GHashTable              *wwan_killswitches;
 
         /* In addition to using the rfkill kernel subsystem
            (which is exposed by wlan, wimax, bluetooth, nfc,
@@ -100,6 +111,9 @@ static const gchar introspection_xml[] =
 "    <property name='BluetoothAirplaneMode' type='b' access='readwrite'/>"
 "    <property name='BluetoothHardwareAirplaneMode' type='b' access='read'/>"
 "    <property name='BluetoothHasAirplaneMode' type='b' access='read'/>"
+"    <property name='WwanAirplaneMode' type='b' access='readwrite'/>"
+"    <property name='WwanHardwareAirplaneMode' type='b' access='read'/>"
+"    <property name='WwanHasAirplaneMode' type='b' access='read'/>"
 "  </interface>"
 "</node>";
 
@@ -184,6 +198,58 @@ engine_get_has_bluetooth_airplane_mode (GsdRfkillManager *manager)
        return (g_hash_table_size (manager->bt_killswitches) > 0);
 }
 
+static gboolean
+engine_get_wwan_airplane_mode (GsdRfkillManager *manager)
+{
+        gboolean is_airplane;
+
+        is_airplane = engine_get_airplane_mode_helper (manager->wwan_killswitches);
+
+        /* Try our luck with Modem Manager too.  Check only if no rfkill
+         * devices found, or if rfkill reports all devices to be down.
+         * (Airplane mode will be disabled if at least one device is up,
+         * so if rfkill says no device is up, check any device is up via
+         * Network Manager (which in turn, is handled via Modem Manager))
+         */
+        if (g_hash_table_size (manager->wwan_killswitches) == 0 || is_airplane)
+                if (manager->wwan_interesting)
+                        is_airplane = !manager->wwan_enabled;
+
+        return is_airplane;
+}
+
+static gboolean
+engine_get_wwan_hardware_airplane_mode (GsdRfkillManager *manager)
+{
+        GHashTableIter iter;
+        gpointer key, value;
+
+        /* If we have no killswitches, hw airplane mode is off. */
+        if (g_hash_table_size (manager->wwan_killswitches) == 0)
+                return FALSE;
+
+        g_hash_table_iter_init (&iter, manager->wwan_killswitches);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                int state;
+
+                state = GPOINTER_TO_INT (value);
+
+                /* A single rfkill switch that's not hw blocked? Hw airplane mode is off */
+                if (state != RFKILL_STATE_HARD_BLOCKED) {
+                        return FALSE;
+                }
+        }
+
+        return TRUE;
+}
+
+static gboolean
+engine_get_has_wwan_airplane_mode (GsdRfkillManager *manager)
+{
+        return (g_hash_table_size (manager->wwan_killswitches) > 0 ||
+                manager->wwan_interesting);
+}
+
 static gboolean
 engine_get_airplane_mode (GsdRfkillManager *manager)
 {
@@ -261,6 +327,12 @@ engine_properties_changed (GsdRfkillManager *manager)
                                g_variant_new_boolean (engine_get_bluetooth_hardware_airplane_mode 
(manager)));
         g_variant_builder_add (&props_builder, "{sv}", "BluetoothHasAirplaneMode",
                                g_variant_new_boolean (engine_get_has_bluetooth_airplane_mode (manager)));
+        g_variant_builder_add (&props_builder, "{sv}", "WwanAirplaneMode",
+                               g_variant_new_boolean (engine_get_wwan_airplane_mode (manager)));
+        g_variant_builder_add (&props_builder, "{sv}", "WwanHardwareAirplaneMode",
+                               g_variant_new_boolean (engine_get_wwan_hardware_airplane_mode (manager)));
+        g_variant_builder_add (&props_builder, "{sv}", "WwanHasAirplaneMode",
+                               g_variant_new_boolean (engine_get_has_wwan_airplane_mode (manager)));
 
         props_changed = g_variant_new ("(s@a{sv}@as)", GSD_RFKILL_DBUS_NAME,
                                        g_variant_builder_end (&props_builder),
@@ -284,6 +356,12 @@ rfkill_changed (CcRfkillGlib     *rfkill,
 
        for (l = events; l != NULL; l = l->next) {
                struct rfkill_event *event = l->data;
+                const gchar *type = "";
+
+                if (event->type == RFKILL_TYPE_BLUETOOTH)
+                        type = "Bluetooth";
+                else if (event->type == RFKILL_TYPE_WWAN)
+                        type = "WWAN";
 
                 switch (event->op) {
                 case RFKILL_OP_ADD:
@@ -302,10 +380,13 @@ rfkill_changed (CcRfkillGlib     *rfkill,
                                g_hash_table_insert (manager->bt_killswitches,
                                                     GINT_TO_POINTER (event->idx),
                                                     GINT_TO_POINTER (value));
-                       g_debug ("%s %srfkill with ID %d",
-                                event->op == RFKILL_OP_ADD ? "Added" : "Changed",
-                                event->type == RFKILL_TYPE_BLUETOOTH ? "Bluetooth " : "",
-                                event->idx);
+                        else if (event->type == RFKILL_TYPE_WWAN)
+                                g_hash_table_insert (manager->wwan_killswitches,
+                                                     GINT_TO_POINTER (event->idx),
+                                                     GINT_TO_POINTER (value));
+                        g_debug ("%s %srfkill with ID %d",
+                                 event->op == RFKILL_OP_ADD ? "Added" : "Changed",
+                                 type, event->idx);
                         break;
                 case RFKILL_OP_DEL:
                        g_hash_table_remove (manager->killswitches,
@@ -313,8 +394,10 @@ rfkill_changed (CcRfkillGlib     *rfkill,
                        if (event->type == RFKILL_TYPE_BLUETOOTH)
                                g_hash_table_remove (manager->bt_killswitches,
                                                     GINT_TO_POINTER (event->idx));
-                       g_debug ("Removed %srfkill with ID %d", event->type == RFKILL_TYPE_BLUETOOTH ? 
"Bluetooth " : "",
-                                event->idx);
+                        else if (event->type == RFKILL_TYPE_WWAN)
+                                g_hash_table_remove (manager->wwan_killswitches,
+                                                     GINT_TO_POINTER (event->idx));
+                        g_debug ("Removed %srfkill with ID %d", type, event->idx);
                         break;
                 }
        }
@@ -371,6 +454,29 @@ engine_set_bluetooth_airplane_mode (GsdRfkillManager *manager,
         return TRUE;
 }
 
+static gboolean
+engine_set_wwan_airplane_mode (GsdRfkillManager *manager,
+                               gboolean          enable)
+{
+        cc_rfkill_glib_send_change_all_event (manager->rfkill, RFKILL_TYPE_WWAN,
+                                              enable, manager->cancellable, rfkill_set_cb, manager);
+
+        if (manager->nm_client) {
+                g_dbus_proxy_call (manager->nm_client,
+                                   "org.freedesktop.DBus.Properties.Set",
+                                   g_variant_new ("(ssv)",
+                                                  "org.freedesktop.NetworkManager",
+                                                  "WwanEnabled",
+                                                  g_variant_new_boolean (!enable)),
+                                   G_DBUS_CALL_FLAGS_NONE,
+                                   -1, /* timeout */
+                                   manager->cancellable,
+                                   set_wwan_complete, NULL);
+        }
+
+        return TRUE;
+}
+
 static gboolean
 engine_set_airplane_mode (GsdRfkillManager *manager,
                           gboolean          enable)
@@ -418,6 +524,12 @@ handle_set_property (GDBusConnection *connection,
                 return engine_set_bluetooth_airplane_mode (manager, airplane_mode);
         }
 
+        if (g_strcmp0 (property_name, "WwanAirplaneMode") == 0) {
+                gboolean airplane_mode;
+                g_variant_get (value, "b", &airplane_mode);
+                return engine_set_wwan_airplane_mode (manager, airplane_mode);
+        }
+
         return FALSE;
 }
 
@@ -480,6 +592,24 @@ handle_get_property (GDBusConnection *connection,
                 return g_variant_new_boolean (has_airplane_mode);
         }
 
+        if (g_strcmp0 (property_name, "WwanAirplaneMode") == 0) {
+                gboolean airplane_mode;
+                airplane_mode = engine_get_wwan_airplane_mode (manager);
+                return g_variant_new_boolean (airplane_mode);
+        }
+
+        if (g_strcmp0 (property_name, "WwanHardwareAirplaneMode") == 0) {
+                gboolean hw_airplane_mode;
+                hw_airplane_mode = engine_get_wwan_hardware_airplane_mode (manager);
+                return g_variant_new_boolean (hw_airplane_mode);
+        }
+
+        if (g_strcmp0 (property_name, "WwanHasAirplaneMode") == 0) {
+                gboolean has_airplane_mode;
+                has_airplane_mode = engine_get_has_wwan_airplane_mode (manager);
+                return g_variant_new_boolean (has_airplane_mode);
+        }
+
         return NULL;
 }
 
@@ -666,6 +796,7 @@ gsd_rfkill_manager_start (GsdRfkillManager *manager,
 
         manager->killswitches = g_hash_table_new (g_direct_hash, g_direct_equal);
         manager->bt_killswitches = g_hash_table_new (g_direct_hash, g_direct_equal);
+        manager->wwan_killswitches = g_hash_table_new (g_direct_hash, g_direct_equal);
         manager->rfkill = cc_rfkill_glib_new ();
         g_signal_connect (G_OBJECT (manager->rfkill), "changed",
                           G_CALLBACK (rfkill_changed), manager);
@@ -724,6 +855,7 @@ gsd_rfkill_manager_stop (GsdRfkillManager *manager)
         g_clear_object (&manager->rfkill);
         g_clear_pointer (&manager->killswitches, g_hash_table_destroy);
         g_clear_pointer (&manager->bt_killswitches, g_hash_table_destroy);
+        g_clear_pointer (&manager->wwan_killswitches, g_hash_table_destroy);
 
         if (manager->cancellable) {
                 g_cancellable_cancel (manager->cancellable);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]