~mir-team/ubuntu-app-launch/mir-release-0.14.0

« back to all changes in this revision

Viewing changes to libubuntu-app-launch/ubuntu-app-launch.c

  • Committer: CI Train Bot
  • Author(s): Ted Gould
  • Date: 2015-03-05 14:36:29 UTC
  • mfrom: (184.2.14 suspend-signal)
  • Revision ID: ci-train-bot@canonical.com-20150305143629-tr17d64m1vwtihyy
Emit a signal when applications are paused or resumed Fixes: #1425285
Approved by: PS Jenkins bot, Rodney Dawes

Show diffs side-by-side

added added

removed removed

Lines of Context:
499
499
        return FALSE;
500
500
}
501
501
 
 
502
/* Throw out a DBus signal that we've signalled all of these processes. This
 
503
   is the fun GVariant building part. */
 
504
static void
 
505
notify_signalling (GList * pids, const gchar * appid, const gchar * signal_name)
 
506
{
 
507
        GDBusConnection * conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
 
508
        if (conn == NULL) {
 
509
                return;
 
510
        }
 
511
 
 
512
        /* Pull together a PID array */
 
513
        GVariant *pidarray = NULL;
 
514
        if (pids == NULL) {
 
515
                pidarray = g_variant_new_array(G_VARIANT_TYPE_UINT64, NULL, 0);
 
516
        } else {
 
517
                GList * i;
 
518
                GVariantBuilder builder;
 
519
                g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
 
520
 
 
521
                for (i = pids; i != NULL; i = g_list_next(i))
 
522
                        g_variant_builder_add_value(&builder, g_variant_new_uint64(GPOINTER_TO_INT(i->data)));
 
523
 
 
524
                pidarray = g_variant_builder_end(&builder);
 
525
        }
 
526
 
 
527
        /* Combine into the wrapping tuple */
 
528
        GVariantBuilder btuple;
 
529
        g_variant_builder_init(&btuple, G_VARIANT_TYPE_TUPLE);
 
530
        g_variant_builder_add_value(&btuple, g_variant_new_string(appid));
 
531
        g_variant_builder_add_value(&btuple, pidarray);
 
532
 
 
533
        /* Emit !!! */
 
534
        GError * error = NULL;
 
535
        g_dbus_connection_emit_signal(conn,
 
536
                NULL, /* destination */
 
537
                "/", /* path */
 
538
                "com.canonical.UbuntuAppLaunch", /* interface */
 
539
                signal_name, /* signal */
 
540
                g_variant_builder_end(&btuple), /* params, the same */
 
541
                &error);
 
542
 
 
543
        if (error != NULL) {
 
544
                g_warning("Unable to emit signal '%s' for appid '%s': %s", signal_name, appid, error->message);
 
545
                g_error_free(error);
 
546
        } else {
 
547
                g_debug("Emmitted '%s' to DBus", signal_name);
 
548
        }
 
549
 
 
550
        g_object_unref(conn);
 
551
}
 
552
 
502
553
/* Gets all the pids for an appid and sends a signal to all of them. This also
503
554
   loops to ensure no new pids are added while we're signaling */
504
555
static gboolean
505
 
signal_to_cgroup (const gchar * appid, int signal, const gchar * oomscore)
 
556
signal_to_cgroup (const gchar * appid, int signal, const gchar * oomscore, const gchar * signal_name)
506
557
{
507
558
        GHashTable * pidssignaled = g_hash_table_new(g_direct_hash, g_direct_equal);
508
559
        guint hash_table_size = 0;
543
594
        /* If it grew, then try again */
544
595
        } while (hash_table_size != g_hash_table_size(pidssignaled));
545
596
 
 
597
        notify_signalling(g_hash_table_get_keys(pidssignaled), appid, signal_name);
546
598
        g_hash_table_destroy(pidssignaled);
547
599
 
548
600
        return retval;
612
664
ubuntu_app_launch_pause_application (const gchar * appid)
613
665
{
614
666
        report_zg_event(appid, ZEITGEIST_ZG_LEAVE_EVENT);
615
 
        return signal_to_cgroup(appid, SIGSTOP, "900");
 
667
        return signal_to_cgroup(appid, SIGSTOP, "900", "ApplicationPaused");
616
668
}
617
669
 
618
670
gboolean
619
671
ubuntu_app_launch_resume_application (const gchar * appid)
620
672
{
621
673
        report_zg_event(appid, ZEITGEIST_ZG_ACCESS_EVENT);
622
 
        return signal_to_cgroup(appid, SIGCONT, "100");
 
674
        return signal_to_cgroup(appid, SIGCONT, "100", "ApplicationResumed");
623
675
}
624
676
 
625
677
gchar *
709
761
        gpointer user_data;
710
762
};
711
763
 
 
764
/* The data we keep for each failed observer */
 
765
typedef struct _paused_resumed_observer_t paused_resumed_observer_t;
 
766
struct _paused_resumed_observer_t {
 
767
        GDBusConnection * conn;
 
768
        guint sighandle;
 
769
        UbuntuAppLaunchAppPausedResumedObserver func;
 
770
        gpointer user_data;
 
771
        const gchar * lttng_signal;
 
772
};
 
773
 
712
774
/* The lists of Observers */
713
775
static GList * starting_array = NULL;
714
776
static GList * started_array = NULL;
716
778
static GList * focus_array = NULL;
717
779
static GList * resume_array = NULL;
718
780
static GList * failed_array = NULL;
 
781
static GList * paused_array = NULL;
 
782
static GList * resumed_array = NULL;
719
783
 
720
784
static void
721
785
observer_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data)
994
1058
        return TRUE;
995
1059
}
996
1060
 
 
1061
/* Handle the paused signal when it occurs, call the observer */
 
1062
static void
 
1063
paused_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data)
 
1064
{
 
1065
        paused_resumed_observer_t * observer = (paused_resumed_observer_t *)user_data;
 
1066
 
 
1067
        ual_tracepoint(observer_start, observer->lttng_signal);
 
1068
 
 
1069
        if (observer->func != NULL) {
 
1070
                GArray * pidarray = g_array_new(TRUE, TRUE, sizeof(GPid));
 
1071
                GVariant * appid = g_variant_get_child_value(params, 0);
 
1072
                GVariant * pids = g_variant_get_child_value(params, 1);
 
1073
                guint64 pid;
 
1074
                GVariantIter thispid;
 
1075
                g_variant_iter_init(&thispid, pids);
 
1076
 
 
1077
                while (g_variant_iter_loop(&thispid, "t", &pid)) {
 
1078
                        GPid gpid = (GPid)pid; /* Should be a no-op for most architectures, but just in case */
 
1079
                        g_array_append_val(pidarray, gpid);
 
1080
                }
 
1081
 
 
1082
                observer->func(g_variant_get_string(appid, NULL), (GPid *)pidarray->data, observer->user_data);
 
1083
 
 
1084
                g_array_free(pidarray, TRUE);
 
1085
                g_variant_unref(appid);
 
1086
                g_variant_unref(pids);
 
1087
        }
 
1088
 
 
1089
        ual_tracepoint(observer_finish, observer->lttng_signal);
 
1090
}
 
1091
 
 
1092
static gboolean
 
1093
paused_resumed_generic (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data, GList ** queue, const gchar * signal_name, const gchar * lttng_signal)
 
1094
{
 
1095
        GDBusConnection * conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
 
1096
 
 
1097
        if (conn == NULL) {
 
1098
                return FALSE;
 
1099
        }
 
1100
 
 
1101
        paused_resumed_observer_t * observert = g_new0(paused_resumed_observer_t, 1);
 
1102
 
 
1103
        observert->conn = conn;
 
1104
        observert->func = observer;
 
1105
        observert->user_data = user_data;
 
1106
        observert->lttng_signal = lttng_signal;
 
1107
 
 
1108
        *queue = g_list_prepend(*queue, observert);
 
1109
 
 
1110
        observert->sighandle = g_dbus_connection_signal_subscribe(conn,
 
1111
                NULL, /* sender */
 
1112
                "com.canonical.UbuntuAppLaunch", /* interface */
 
1113
                signal_name, /* signal */
 
1114
                "/", /* path */
 
1115
                NULL, /* arg0 */
 
1116
                G_DBUS_SIGNAL_FLAGS_NONE,
 
1117
                paused_signal_cb,
 
1118
                observert,
 
1119
                NULL); /* user data destroy */
 
1120
 
 
1121
        return TRUE;
 
1122
}
 
1123
 
 
1124
gboolean
 
1125
ubuntu_app_launch_observer_add_app_paused (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data)
 
1126
{
 
1127
        return paused_resumed_generic(observer, user_data, &paused_array, "ApplicationPaused", "paused");
 
1128
}
 
1129
 
 
1130
gboolean
 
1131
ubuntu_app_launch_observer_add_app_resumed (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data)
 
1132
{
 
1133
        return paused_resumed_generic(observer, user_data, &resumed_array, "ApplicationResumed", "resumed");
 
1134
}
 
1135
 
997
1136
static gboolean
998
1137
delete_app_generic (UbuntuAppLaunchAppObserver observer, gpointer user_data, GList ** list)
999
1138
{
1078
1217
        return TRUE;
1079
1218
}
1080
1219
 
 
1220
static gboolean
 
1221
paused_resumed_delete (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data, GList ** list)
 
1222
{
 
1223
        paused_resumed_observer_t * observert = NULL;
 
1224
        GList * look;
 
1225
 
 
1226
        for (look = *list; look != NULL; look = g_list_next(look)) {
 
1227
                observert = (paused_resumed_observer_t *)look->data;
 
1228
 
 
1229
                if (observert->func == observer && observert->user_data == user_data) {
 
1230
                        break;
 
1231
                }
 
1232
        }
 
1233
 
 
1234
        if (look == NULL) {
 
1235
                return FALSE;
 
1236
        }
 
1237
 
 
1238
        g_dbus_connection_signal_unsubscribe(observert->conn, observert->sighandle);
 
1239
        g_object_unref(observert->conn);
 
1240
 
 
1241
        g_free(observert);
 
1242
        *list = g_list_delete_link(*list, look);
 
1243
 
 
1244
        return TRUE;
 
1245
}
 
1246
 
 
1247
gboolean
 
1248
ubuntu_app_launch_observer_delete_app_paused (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data)
 
1249
{
 
1250
        return paused_resumed_delete(observer, user_data, &paused_array);
 
1251
}
 
1252
 
 
1253
gboolean
 
1254
ubuntu_app_launch_observer_delete_app_resumed (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data)
 
1255
{
 
1256
        return paused_resumed_delete(observer, user_data, &resumed_array);
 
1257
}
 
1258
 
1081
1259
typedef void (*per_instance_func_t) (GDBusConnection * con, GVariant * prop_dict, gpointer user_data);
1082
1260
 
1083
1261
static void