00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <dbus/dbus.h>
00023 #include <glib/gthread.h>
00024 #include <glib/gslist.h>
00025 #include <glib/gstrfuncs.h>
00026 #include <systemui/dbus-names.h>
00027 #include <systemui/alarm_dialog-dbus-names.h>
00028 #include <systemui/actingdead-dbus-names.h>
00029 #include <string.h>
00030
00031 #include "debug.h"
00032 #include "include/alarm_dbus.h"
00033 #include "rpc-dbus.h"
00034 #include "rpc-systemui.h"
00035 #include "rpc-mce.h"
00036
00037 #define ALARMD_ACTION_DBUS_METHOD "action_dbus_return"
00038
00039
00040 enum response {
00041 RESPONSE_ACCEPT = -3
00042 };
00043
00044 enum flag {
00045 FLAG_CAN_SNOOZE = 1 << 0,
00046 FLAG_POWERUP = 1 << 1,
00047 };
00048
00049 typedef struct _SystemuiAlarmdDialog SystemuiAlarmdDialog;
00050 struct _SystemuiAlarmdDialog {
00051 time_t alarm_time;
00052 gchar *title;
00053 gchar *message;
00054 gchar *sound;
00055 gchar *icon;
00056 gpointer user_data;
00057 SystemuiAlarmdDialogCallback cb;
00058 enum flag flags;
00059 gboolean status;
00060 guint count;
00061 guint timer_id;
00062 };
00063
00064 static GStaticMutex queue_mutex = G_STATIC_MUTEX_INIT;
00065 static GSList *dialog_queue = NULL;
00066 static DBusConnection *system_bus = NULL;
00067 static gboolean mce_dialog_visible = FALSE;
00068 static void _dialog_free(SystemuiAlarmdDialog *dialog);
00069
00070 static gboolean _resend_message(gpointer user_data);
00071 static DBusConnection *_dbus_connect(void);
00072 static void _dbus_disconnect(DBusConnection *conn);
00073 static void _queue_changed(void);
00074 static void _close_dialog(void);
00075 static gint _queue_compare(gconstpointer v1, gconstpointer v2);
00076 static gboolean _dialog_do_cb(gpointer data);
00077 static DBusHandlerResult _dialog_ackd(DBusConnection *connection,
00078 DBusMessage *message,
00079 void *user_data);
00080 static void _systemui_dialog_queue_append(time_t alarm_time, const gchar *title, const gchar *message, const gchar *sound, const gchar *icon, enum flag flags, SystemuiAlarmdDialogCallback cb, gpointer user_data);
00081
00082 void systemui_powerup_dialog_queue_append(SystemuiAlarmdDialogCallback cb, gpointer user_data)
00083 {
00084 _systemui_dialog_queue_append(0, NULL, NULL, NULL, NULL, FLAG_POWERUP, cb, user_data);
00085 }
00086
00087 void systemui_alarm_dialog_queue_append(time_t alarm_time, const gchar *title, const gchar *message, const gchar *sound, const gchar *icon, gboolean can_snooze, SystemuiAlarmdDialogCallback cb, gpointer user_data)
00088 {
00089 _systemui_dialog_queue_append(alarm_time, title, message, sound, icon, can_snooze ? FLAG_CAN_SNOOZE : 0, cb, user_data);
00090 }
00091
00092 void systemui_powerup_dialog_queue_remove(SystemuiAlarmdDialogCallback cb, gpointer user_data)
00093 {
00094 systemui_alarm_dialog_queue_remove(0, NULL, NULL, NULL, NULL, cb, user_data);
00095 }
00096
00097 void systemui_alarm_dialog_queue_remove(time_t alarm_time, const gchar *title, const gchar *message, const gchar *sound, const gchar *icon, SystemuiAlarmdDialogCallback cb, gpointer user_data)
00098 {
00099 SystemuiAlarmdDialog dlg = {
00100 .alarm_time = alarm_time,
00101 .title = (gchar *)title,
00102 .message = (gchar *)message,
00103 .sound = (gchar *)sound,
00104 .icon = (gchar *)icon,
00105 .user_data = user_data,
00106 .cb = cb,
00107 .flags = 0
00108 };
00109 GSList *iter = NULL;
00110 SystemuiAlarmdDialog *remove = NULL;
00111 ENTER_FUNC;
00112
00113 g_static_mutex_lock(&queue_mutex);
00114 iter = g_slist_find_custom(dialog_queue, &dlg, _queue_compare);
00115 if (iter) {
00116 remove = (SystemuiAlarmdDialog *)iter->data;
00117 if (iter == dialog_queue && system_bus) {
00118 _close_dialog();
00119 }
00120 } else {
00121 g_static_mutex_unlock(&queue_mutex);
00122 LEAVE_FUNC;
00123 return;
00124 }
00125 dialog_queue = g_slist_delete_link(dialog_queue, iter);
00126 g_static_mutex_unlock(&queue_mutex);
00127
00128 if (remove->timer_id) {
00129 g_source_remove(remove->timer_id);
00130 remove->timer_id = 0;
00131 }
00132 _dialog_free(remove);
00133 _queue_changed();
00134 LEAVE_FUNC;
00135 }
00136
00137 static gint _queue_compare(gconstpointer v1, gconstpointer v2)
00138 {
00139 SystemuiAlarmdDialog *lval = (SystemuiAlarmdDialog *)v1;
00140 SystemuiAlarmdDialog *rval = (SystemuiAlarmdDialog *)v2;
00141
00142 ENTER_FUNC;
00143 gint retval;
00144
00145 if ((retval = lval->alarm_time - rval->alarm_time)) {
00146 LEAVE_FUNC;
00147 return retval;
00148 }
00149 if (lval->title && rval->title && (retval = strcmp(lval->title, rval->title))) {
00150 LEAVE_FUNC;
00151 return retval;
00152 }
00153 if (lval->message && rval->message && (retval = strcmp(lval->message, rval->message))) {
00154 LEAVE_FUNC;
00155 return retval;
00156 }
00157 if (lval->sound && rval->sound && (retval = strcmp(lval->sound, rval->sound))) {
00158 LEAVE_FUNC;
00159 return retval;
00160 }
00161 if (lval->icon && rval->icon && (retval = strcmp(lval->icon, rval->icon))) {
00162 LEAVE_FUNC;
00163 return retval;
00164 }
00165 if ((retval = (gint)lval->user_data - (gint)rval->user_data)) {
00166 LEAVE_FUNC;
00167 return retval;
00168 }
00169 LEAVE_FUNC;
00170 return lval->cb != rval->cb;
00171 }
00172
00173 static void _dialog_free(SystemuiAlarmdDialog *dialog)
00174 {
00175 ENTER_FUNC;
00176 if (!dialog) {
00177 LEAVE_FUNC;
00178 return;
00179 }
00180
00181 if (dialog->title) {
00182 g_free(dialog->title);
00183 }
00184 if (dialog->message) {
00185 g_free(dialog->message);
00186 }
00187 if (dialog->sound) {
00188 g_free(dialog->sound);
00189 }
00190 if (dialog->icon) {
00191 g_free(dialog->icon);
00192 }
00193 g_free(dialog);
00194 LEAVE_FUNC;
00195 }
00196
00197 static void _queue_changed(void)
00198 {
00199 ENTER_FUNC;
00200 g_static_mutex_lock(&queue_mutex);
00201 if (dialog_queue && !system_bus) {
00202 SystemuiAlarmdDialog *dlg = (SystemuiAlarmdDialog *)dialog_queue->data;
00203 const gchar *my_service = ALARMD_SERVICE;
00204 const gchar *my_path = ALARMD_PATH;
00205 const gchar *my_interface = ALARMD_INTERFACE;
00206 const gchar *my_method = ALARMD_ACTION_DBUS_METHOD;
00207 DBusMessage *reply = NULL;
00208 system_bus = _dbus_connect();
00209 dbus_int32_t retval = 0;
00210 if (dlg->flags & FLAG_POWERUP) {
00211 const int dialog_type = ALARM_MODE_SWITCHON;
00212
00213 dbus_do_call(system_bus,
00214 &reply,
00215 FALSE,
00216 SYSTEMUI_SERVICE,
00217 SYSTEMUI_REQUEST_PATH,
00218 SYSTEMUI_REQUEST_IF,
00219 SYSTEMUI_ALARM_OPEN_REQ,
00220 DBUS_TYPE_STRING, &my_service,
00221 DBUS_TYPE_STRING, &my_path,
00222 DBUS_TYPE_STRING, &my_interface,
00223 DBUS_TYPE_STRING, &my_method,
00224 DBUS_TYPE_UINT32, &dialog_type,
00225 DBUS_TYPE_INVALID);
00226 } else {
00227 const gchar *my_sound = dlg->sound == NULL ? "" : dlg->sound;
00228 const gchar *my_icon = dlg->icon == NULL ? "" : dlg->icon;
00229 const gchar *my_message = dlg->message == NULL ? "" : dlg->message;
00230 const gchar *my_title = dlg->title == NULL ? "" : dlg->title;
00231 const int dialog_type = (dlg->flags & FLAG_CAN_SNOOZE) ? ALARM_MODE_NORMAL : ALARM_MODE_NOSNOOZE;
00232
00233 DEBUG("sound = %s, icon = %s, message = %s", my_sound, my_icon, my_message);
00234 dbus_do_call(system_bus,
00235 &reply,
00236 FALSE,
00237 SYSTEMUI_SERVICE,
00238 SYSTEMUI_REQUEST_PATH,
00239 SYSTEMUI_REQUEST_IF,
00240 SYSTEMUI_ALARM_OPEN_REQ,
00241 DBUS_TYPE_STRING, &my_service,
00242 DBUS_TYPE_STRING, &my_path,
00243 DBUS_TYPE_STRING, &my_interface,
00244 DBUS_TYPE_STRING, &my_method,
00245 DBUS_TYPE_UINT32, &dialog_type,
00246 DBUS_TYPE_STRING, &my_message,
00247 DBUS_TYPE_STRING, &my_sound,
00248 DBUS_TYPE_STRING, &my_icon,
00249 DBUS_TYPE_STRING, &my_title,
00250 DBUS_TYPE_UINT32, &dlg->alarm_time,
00251 DBUS_TYPE_INVALID);
00252 dlg->timer_id = g_timeout_add(300000, _resend_message,
00253 dlg);
00254 }
00255
00256 if (reply) {
00257 dbus_message_get_args(reply, NULL, DBUS_TYPE_INT32, &retval, DBUS_TYPE_INVALID);
00258 dbus_message_unref(reply);
00259 reply = NULL;
00260 }
00261 if (retval != RESPONSE_ACCEPT) {
00262 if (dlg->timer_id) {
00263 g_source_remove(dlg->timer_id);
00264 dlg->timer_id = 0;
00265 }
00266 _dbus_disconnect(system_bus);
00267 system_bus = NULL;
00268 }
00269 }
00270 g_static_mutex_unlock(&queue_mutex);
00271 LEAVE_FUNC;
00272 }
00273
00274 static void _close_dialog(void)
00275 {
00276 ENTER_FUNC;
00277 g_static_mutex_lock(&queue_mutex);
00278 if (system_bus) {
00279 dbus_do_call(system_bus,
00280 NULL,
00281 FALSE,
00282 SYSTEMUI_SERVICE,
00283 SYSTEMUI_REQUEST_PATH,
00284 SYSTEMUI_REQUEST_IF,
00285 SYSTEMUI_ALARM_CLOSE_REQ,
00286 DBUS_TYPE_INVALID);
00287 _dbus_disconnect(system_bus);
00288 system_bus = NULL;
00289 }
00290 g_static_mutex_unlock(&queue_mutex);
00291 LEAVE_FUNC;
00292 }
00293
00294 static DBusConnection *_dbus_connect(void)
00295 {
00296 ENTER_FUNC;
00297 DBusConnection *retval = get_dbus_connection(DBUS_BUS_SYSTEM);
00298
00299 if (retval) {
00300 int status = dbus_bus_request_name(retval, ALARMD_SERVICE, 0, NULL);
00301 if (!(status == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER || DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER))
00302 {
00303 dbus_connection_unref(retval);
00304 LEAVE_FUNC;
00305 return NULL;
00306 }
00307 dbus_connection_add_filter(retval, _dialog_ackd, NULL, NULL);
00308 }
00309
00310 LEAVE_FUNC;
00311 return retval;
00312 }
00313
00314 static void _dbus_disconnect(DBusConnection *conn)
00315 {
00316 ENTER_FUNC;
00317 if (conn) {
00318 dbus_connection_remove_filter(conn, _dialog_ackd, NULL);
00319 dbus_connection_unref(conn);
00320 }
00321 LEAVE_FUNC;
00322 }
00323
00324 static gboolean _dialog_do_cb(gpointer data)
00325 {
00326 SystemuiAlarmdDialog *dlg = data;
00327 if (dlg->cb) {
00328 dlg->cb(dlg->user_data, dlg->status);
00329 }
00330
00331 return FALSE;
00332 }
00333
00334 static DBusHandlerResult _dialog_ackd(DBusConnection *connection,
00335 DBusMessage *message,
00336 void *user_data)
00337 {
00338 ENTER_FUNC;
00339 (void)connection;
00340 (void)user_data;
00341
00342 if (dbus_message_is_method_call(message,
00343 ALARMD_INTERFACE,
00344 ALARMD_ACTION_DBUS_METHOD)) {
00345 dbus_int32_t retval = 0;
00346 SystemuiAlarmdDialog *dlg = NULL;
00347
00348 dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &retval, DBUS_TYPE_INVALID);
00349
00350 g_static_mutex_lock(&queue_mutex);
00351 if (dialog_queue) {
00352 dlg = (SystemuiAlarmdDialog *)dialog_queue->data;
00353
00354 DEBUG("Deleting link from queue.");
00355 dialog_queue = g_slist_delete_link(dialog_queue, dialog_queue);
00356 DEBUG("Queue now %p", dialog_queue);
00357 }
00358 _dbus_disconnect(system_bus);
00359 system_bus = NULL;
00360 g_static_mutex_unlock(&queue_mutex);
00361
00362 dlg->status = (retval == ALARM_DIALOG_RESPONSE_SNOOZE
00363 || retval == ALARM_DIALOG_RESPONSE_POWERUP);
00364 if (dlg->timer_id) {
00365 g_source_remove(dlg->timer_id);
00366 dlg->timer_id = 0;
00367 }
00368
00369 _queue_changed();
00370
00371 g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
00372 _dialog_do_cb,
00373 dlg, (GDestroyNotify)_dialog_free);
00374
00375 LEAVE_FUNC;
00376 return DBUS_HANDLER_RESULT_HANDLED;
00377 }
00378
00379 LEAVE_FUNC;
00380 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00381 }
00382
00383 static void _systemui_dialog_queue_append(time_t alarm_time, const gchar *title, const gchar *message, const gchar *sound, const gchar *icon, enum flag flags, SystemuiAlarmdDialogCallback cb, gpointer user_data)
00384 {
00385 SystemuiAlarmdDialog *new_dialog = g_new0(SystemuiAlarmdDialog, 1);
00386 ENTER_FUNC;
00387 new_dialog->alarm_time = alarm_time;
00388 new_dialog->title = g_strdup(title);
00389 new_dialog->message = g_strdup(message);
00390 new_dialog->sound = g_strdup(sound);
00391 new_dialog->icon = g_strdup(icon);
00392 new_dialog->flags = flags;
00393 new_dialog->cb = cb;
00394 new_dialog->user_data = user_data;
00395 g_static_mutex_lock(&queue_mutex);
00396 dialog_queue = g_slist_append(dialog_queue, new_dialog);
00397 g_static_mutex_unlock(&queue_mutex);
00398 _queue_changed();
00399 LEAVE_FUNC;
00400 }
00401
00402 void update_mce_alarm_visibility(void)
00403 {
00404 DBusConnection *conn;
00405
00406 conn = get_dbus_connection(DBUS_BUS_SYSTEM);
00407 g_static_mutex_lock(&queue_mutex);
00408 if ((dialog_queue && mce_dialog_visible)) {
00409 g_static_mutex_unlock(&queue_mutex);
00410 dbus_connection_unref(conn);
00411 return;
00412 }
00413 mce_dialog_visible = dialog_queue ? TRUE : FALSE;
00414 mce_set_alarm_visibility(conn, mce_dialog_visible);
00415 g_static_mutex_unlock(&queue_mutex);
00416 dbus_connection_unref(conn);
00417 }
00418
00419 void systemui_ack_all_dialogs(void)
00420 {
00421 GSList *my_list;
00422
00423 ENTER_FUNC;
00424 g_static_mutex_lock(&queue_mutex);
00425 my_list = dialog_queue;
00426 dialog_queue = NULL;
00427 g_static_mutex_unlock(&queue_mutex);
00428
00429 _close_dialog();
00430
00431 while (my_list) {
00432 SystemuiAlarmdDialog *dlg = my_list->data;
00433 if (dlg->timer_id) {
00434 g_source_remove(dlg->timer_id);
00435 dlg->timer_id = 0;
00436 }
00437 dlg->cb(dlg->user_data, FALSE);
00438 g_free(dlg);
00439
00440 my_list = g_slist_delete_link(my_list, my_list);
00441 }
00442
00443 LEAVE_FUNC;
00444 }
00445
00446 static gboolean _resend_message(gpointer user_data)
00447 {
00448 SystemuiAlarmdDialog *dlg = user_data;
00449
00450 const gchar *my_service = ALARMD_SERVICE;
00451 const gchar *my_path = ALARMD_PATH;
00452 const gchar *my_interface = ALARMD_INTERFACE;
00453 const gchar *my_method = ALARMD_ACTION_DBUS_METHOD;
00454 const gchar *my_sound = dlg->sound == NULL ? "" : dlg->sound;
00455 const gchar *my_icon = dlg->icon == NULL ? "" : dlg->icon;
00456 const gchar *my_message = dlg->message == NULL ? "" : dlg->message;
00457 const gchar *my_title = dlg->title == NULL ? "" : dlg->title;
00458 const int dialog_type = (dlg->flags & FLAG_CAN_SNOOZE) ? ALARM_MODE_NORMAL : ALARM_MODE_NOSNOOZE;
00459 ENTER_FUNC;
00460
00461 DEBUG("sound = %s, icon = %s, message = %s", my_sound, my_icon, my_message);
00462 g_static_mutex_unlock(&queue_mutex);
00463 if (system_bus) {
00464 dbus_do_call(system_bus,
00465 NULL,
00466 FALSE,
00467 SYSTEMUI_SERVICE,
00468 SYSTEMUI_REQUEST_PATH,
00469 SYSTEMUI_REQUEST_IF,
00470 SYSTEMUI_ALARM_OPEN_REQ,
00471 DBUS_TYPE_STRING, &my_service,
00472 DBUS_TYPE_STRING, &my_path,
00473 DBUS_TYPE_STRING, &my_interface,
00474 DBUS_TYPE_STRING, &my_method,
00475 DBUS_TYPE_UINT32, &dialog_type,
00476 DBUS_TYPE_STRING, &my_message,
00477 DBUS_TYPE_STRING, &my_sound,
00478 DBUS_TYPE_STRING, &my_icon,
00479 DBUS_TYPE_STRING, &my_title,
00480 DBUS_TYPE_UINT32, &dlg->alarm_time,
00481 DBUS_TYPE_INVALID);
00482 }
00483 g_static_mutex_unlock(&queue_mutex);
00484 dlg->count++;
00485
00486 if (dlg->count < 3) {
00487 LEAVE_FUNC;
00488 return TRUE;
00489 }
00490 dlg->timer_id = 0;
00491 LEAVE_FUNC;
00492 return FALSE;
00493 }
00494
00495 gboolean systemui_is_acting_dead(void)
00496 {
00497 DBusMessage *reply = NULL;
00498 gboolean retval = FALSE;
00499 DBusConnection *system_bus;
00500
00501 ENTER_FUNC;
00502 system_bus = get_dbus_connection(DBUS_BUS_SYSTEM);
00503 dbus_do_call(system_bus,
00504 &reply,
00505 FALSE,
00506 SYSTEMUI_SERVICE,
00507 SYSTEMUI_REQUEST_PATH,
00508 SYSTEMUI_REQUEST_IF,
00509 SYSTEMUI_ACTINGDEAD_GETSTATE_REQ,
00510 DBUS_TYPE_INVALID);
00511 dbus_connection_unref(system_bus);
00512
00513 if (reply) {
00514 dbus_message_get_args(reply, NULL,
00515 DBUS_TYPE_BOOLEAN, &retval,
00516 DBUS_TYPE_INVALID);
00517 dbus_message_unref(reply);
00518 }
00519
00520 LEAVE_FUNC;
00521 return retval;
00522 }