Skip to content

Commit

Permalink
Do not broadcast intermediate tklock changes over D-Bus
Browse files Browse the repository at this point in the history
If mce side state machines oscillate between tklock on and off, it
can cause problems due to ui side trying to react to intermediate
states.

Use idle callback to delay sending of tklock state information so that
only the final tklock state is communicated outside mce process. Hold
a wakelock until the dbus ipc is actually made plus couple of seconds
to make it more likely for ui side to have time to process the state
change before device is allowed to suspend.

Also clear last send state when tklock change requests are made over
D-Bus. This way the state mce arrived at is always broadcast even if
the request ends up getting ignored.

[mce] Do not broadcast intermediate tklock changes over D-Bus
  • Loading branch information
spiiroin committed Oct 28, 2014
1 parent 9efa7db commit f7411f9
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 17 deletions.
1 change: 1 addition & 0 deletions mce.c
Expand Up @@ -156,6 +156,7 @@ static void mce_cleanup_wakelocks(void)
wakelock_unlock("mce_bluez_wait");
wakelock_unlock("mce_led_breathing");
wakelock_unlock("mce_lpm_off");
wakelock_unlock("mce_tklock_notify");
}
#endif // ENABLE_WAKELOCKS

Expand Down
139 changes: 122 additions & 17 deletions tklock.c
Expand Up @@ -498,7 +498,7 @@ static ps_history_t tklock_lpmui_hist[8];
static bool tklock_ui_enabled = false;

/** Current tklock ui state that has been sent to lipstick */
static int tklock_ui_sent = -1; // does not match bool values
static int tklock_ui_notified = -1; // does not match bool values

/** System state; is undefined at bootup, can't assume anything */
static system_state_t system_state = MCE_STATE_UNDEF;
Expand Down Expand Up @@ -589,7 +589,7 @@ static void tklock_datapipe_lipstick_available_cb(gconstpointer data)
lipstick_available);

// force tklock ipc
tklock_ui_sent = -1;
tklock_ui_notified = -1;
tklock_ui_set(false);

if( lipstick_available ) {
Expand Down Expand Up @@ -3647,10 +3647,118 @@ static void tklock_ui_close(void)
DBUS_TYPE_INVALID);
}

static void tklock_ui_set(bool enable)
static guint tklock_ui_notify_end_id = 0;
static guint tklock_ui_notify_beg_id = 0;

static void tklock_ui_notify_rethink_wakelock(void)
{
bool requested = enable;
static bool have_lock = false;

bool need_lock = (tklock_ui_notify_beg_id || tklock_ui_notify_end_id);

if( have_lock == need_lock )
goto EXIT;

mce_log(LL_DEBUG, "ui notify wakelock: %s",
need_lock ? "OBTAIN" : "RELEASE");

if( (have_lock = need_lock) ) {
wakelock_lock("mce_tklock_notify", -1);
}
else
wakelock_unlock("mce_tklock_notify");

EXIT:
return;
}

static gboolean tklock_ui_notify_end_cb(gpointer data)
{
(void) data;

if( !tklock_ui_notify_end_id )
goto EXIT;

tklock_ui_notify_end_id = 0;

EXIT:

tklock_ui_notify_rethink_wakelock();

return FALSE;
}

static gboolean tklock_ui_notify_beg_cb(gpointer data)
{
(void) data;

if( !tklock_ui_notify_beg_id )
goto EXIT;

tklock_ui_notify_beg_id = 0;

bool current = tklock_datapipe_have_tklock_submode();

if( tklock_ui_notified == current )
goto EXIT;

tklock_ui_notified = current;

/* do lipstick specific ipc */
if( lipstick_available ) {
if( current )
tklock_ui_open();
else
tklock_ui_close();
}

/* broadcast signal */
tklock_dbus_send_tklock_mode(0);

/* give ui a chance to see the signal */
if( tklock_ui_notify_end_id )
g_source_remove(tklock_ui_notify_end_id);

tklock_ui_notify_end_id = g_timeout_add(2000,
tklock_ui_notify_end_cb,
0);

EXIT:

tklock_ui_notify_rethink_wakelock();

return FALSE;
}

static void tklock_ui_notify_cancel(void)
{
if( tklock_ui_notify_end_id ) {
g_source_remove(tklock_ui_notify_end_id),
tklock_ui_notify_end_id = 0;
}
if( tklock_ui_notify_beg_id ) {
g_source_remove(tklock_ui_notify_beg_id),
tklock_ui_notify_beg_id = 0;
}

tklock_ui_notify_rethink_wakelock();
}

static void tklock_ui_notify_schdule(void)
{
if( tklock_ui_notify_end_id ) {
g_source_remove(tklock_ui_notify_end_id),
tklock_ui_notify_end_id = 0;
}
if( !tklock_ui_notify_beg_id ) {
tklock_ui_notify_beg_id = g_idle_add(tklock_ui_notify_beg_cb, 0);
}

tklock_ui_notify_rethink_wakelock();
}

static void tklock_ui_set(bool enable)
{
if( enable ) {
if( system_state != MCE_STATE_USER ) {
mce_log(LL_INFO, "deny tklock; not in user mode");
Expand All @@ -3666,21 +3774,14 @@ static void tklock_ui_set(bool enable)
}
}

if( tklock_ui_sent != enable || requested != enable ) {
mce_log(LL_DEVEL, "tklock state = %s", enable ? "locked" : "unlocked");

if( (tklock_ui_sent = tklock_ui_enabled = enable) ) {
if( lipstick_available )
tklock_ui_open();
if( tklock_ui_enabled != enable ) {
if( (tklock_ui_enabled = enable) )
mce_add_submode_int32(MCE_TKLOCK_SUBMODE);
}
else {
if( lipstick_available )
tklock_ui_close();
else
mce_rem_submode_int32(MCE_TKLOCK_SUBMODE);
}
tklock_dbus_send_tklock_mode(0);
}

tklock_ui_notify_schdule();
}

/** Handle reply to device lock state query
Expand Down Expand Up @@ -3889,8 +3990,10 @@ static gboolean tklock_dbus_mode_change_req_cb(DBusMessage *const msg)

mce_log(LL_DEBUG, "mode: %s/%d", mode, state);

if( state != LOCK_UNDEF )
if( state != LOCK_UNDEF ) {
tklock_ui_notified = -1;
tklock_datapipe_tk_lock_cb(GINT_TO_POINTER(state));
}

if( no_reply )
status = TRUE;
Expand Down Expand Up @@ -3931,6 +4034,7 @@ static gboolean tklock_dbus_systemui_callback_cb(DBusMessage *const msg)

switch( result ) {
case TKLOCK_UNLOCK:
tklock_ui_notified = -1;
tklock_ui_set(false);
break;

Expand Down Expand Up @@ -4636,6 +4740,7 @@ void mce_tklock_exit(void)
tklock_dtcalib_stop();
tklock_datapipe_proximity_uncover_cancel();
tklock_notif_quit();
tklock_ui_notify_cancel();

// FIXME: check that final state is sane

Expand Down

0 comments on commit f7411f9

Please sign in to comment.