ringer: Never cancel async DBus calls and refactor

Previously our code assumed that g_cancellable_cancel() the async DBus
calls to libfeedback would guarantee that the underlying operation would
not be performed (i.e. triggering or ending a feedback).

However the endless ringing exhibited in #470 shows this assumption not
to hold. Therefore we avoid using g_cancellable_cancel () completely and
default to waiting for the async operation to finish.

update_ring () now sets the target state by inspecting managed calls and
the main logic will now step towards the target state:
Changing from regular/loud to soft/quiet ringing (or vice versa)
requires we first end feedback before (re)triggering it.

Additionally the "is-quiet" and "is-ringing" properties are replaced by
a new "state" property to allow changing the combination atomically.

Closes: #470
This commit is contained in:
Evangelos Ribeiro Tzaras
2022-09-13 12:25:15 +02:00
parent 43353d48a3
commit 1056cba62a
4 changed files with 231 additions and 257 deletions

View File

@@ -96,11 +96,11 @@ t1_on_ringer_call_accepted (CallsRinger *ringer,
switch (test_phase++) {
case 0: /* incoming call */
g_assert_true (calls_ringer_get_is_ringing (ringer));
g_assert_cmpint (calls_ringer_get_state (ringer), ==, CALLS_RING_STATE_RINGING);
calls_call_answer (CALLS_CALL (fixture->call_one));
break;
case 1: /* incoming call accepted */
g_assert_false (calls_ringer_get_is_ringing (ringer));
g_assert_cmpint (calls_ringer_get_state (ringer), ==, CALLS_RING_STATE_INACTIVE);
g_main_loop_quit ((GMainLoop *) fixture->loop);
break;
default:
@@ -113,21 +113,21 @@ static void
test_ringing_accept_call (RingerFixture *fixture,
gconstpointer user_data)
{
g_assert_false (calls_ringer_get_is_ringing (fixture->ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
g_signal_connect (fixture->ringer,
"notify::ringing",
"notify::state",
G_CALLBACK (t1_on_ringer_call_accepted),
fixture);
calls_call_set_state (CALLS_CALL (fixture->call_one), CALLS_CALL_STATE_INCOMING);
add_call (fixture->manager, fixture->ui_call_one);
/* main loop will quit in callback of notify::ring */
/* main loop will quit in callback of notify::state */
g_main_loop_run (fixture->loop);
remove_call (fixture->manager, fixture->ui_call_one);
g_assert_false (calls_ringer_get_is_ringing (fixture->ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
}
/* t2: test_ringing_hang_up_call */
@@ -141,11 +141,11 @@ t2_on_ringer_call_hang_up (CallsRinger *ringer,
switch (test_phase++) {
case 0: /* incoming call */
g_assert_true (calls_ringer_get_is_ringing (ringer));
g_assert_cmpint (calls_ringer_get_state (ringer), ==, CALLS_RING_STATE_RINGING);
calls_call_hang_up (CALLS_CALL (fixture->call_one));
break;
case 1: /* incoming call hung up */
g_assert_false (calls_ringer_get_is_ringing (ringer));
g_assert_cmpint (calls_ringer_get_state (ringer), ==, CALLS_RING_STATE_INACTIVE);
g_main_loop_quit ((GMainLoop *) fixture->loop);
break;
default:
@@ -158,21 +158,21 @@ static void
test_ringing_hang_up_call (RingerFixture *fixture,
gconstpointer user_data)
{
g_assert_false (calls_ringer_get_is_ringing (fixture->ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
g_signal_connect (fixture->ringer,
"notify::ringing",
"notify::state",
G_CALLBACK (t2_on_ringer_call_hang_up),
fixture);
calls_call_set_state (CALLS_CALL (fixture->call_one), CALLS_CALL_STATE_INCOMING);
add_call (fixture->manager, fixture->ui_call_one);
/* main loop will quit in callback of notify::ring */
/* main loop will quit in callback of notify::state */
g_main_loop_run (fixture->loop);
remove_call (fixture->manager, fixture->ui_call_one);
g_assert_false (calls_ringer_get_is_ringing (fixture->ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
}
@@ -187,12 +187,12 @@ t3_on_ringer_call_silence (CallsRinger *ringer,
switch (test_phase++) {
case 0: /* incoming call */
g_assert_true (calls_ringer_get_is_ringing (ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_RINGING);
calls_ui_call_data_silence_ring (fixture->ui_call_one);
g_assert_true (calls_ui_call_data_get_silenced (fixture->ui_call_one));
break;
case 1: /* incoming call hung up */
g_assert_false (calls_ringer_get_is_ringing (ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
g_main_loop_quit ((GMainLoop *) fixture->loop);
break;
default:
@@ -205,21 +205,21 @@ static void
test_ringing_silence_call (RingerFixture *fixture,
gconstpointer user_data)
{
g_assert_false (calls_ringer_get_is_ringing (fixture->ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
g_signal_connect (fixture->ringer,
"notify::ringing",
"notify::state",
G_CALLBACK (t3_on_ringer_call_silence),
fixture);
calls_call_set_state (CALLS_CALL (fixture->call_one), CALLS_CALL_STATE_INCOMING);
add_call (fixture->manager, fixture->ui_call_one);
/* main loop will quit in callback of notify::ring */
/* main loop will quit in callback of notify::state */
g_main_loop_run (fixture->loop);
remove_call (fixture->manager, fixture->ui_call_one);
g_assert_false (calls_ringer_get_is_ringing (fixture->ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
}
@@ -236,7 +236,7 @@ t4_remove_calls (gpointer user_data)
return G_SOURCE_CONTINUE;
}
g_assert_true (calls_ringer_get_is_ringing (fixture->ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_RINGING);
remove_call (fixture->manager, fixture->ui_call_two);
return G_SOURCE_REMOVE;
@@ -253,12 +253,12 @@ t4_on_ringer_multiple_calls (CallsRinger *ringer,
switch (test_phase++) {
case 0: /* add second call, and schedule call removal */
g_assert_true (calls_ringer_get_is_ringing (ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_RINGING);
add_call (fixture->manager, fixture->ui_call_two);
g_timeout_add (25, t4_remove_calls, fixture);
break;
case 1: /* both calls should be removed now */
g_assert_false (calls_ringer_get_is_ringing (ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
g_main_loop_quit ((GMainLoop *) fixture->loop);
break;
default:
@@ -271,20 +271,20 @@ static void
test_ringing_multiple_calls (RingerFixture *fixture,
gconstpointer user_data)
{
g_assert_false (calls_ringer_get_is_ringing (fixture->ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
g_signal_connect (fixture->ringer,
"notify::ringing",
"notify::state",
G_CALLBACK (t4_on_ringer_multiple_calls),
fixture);
calls_call_set_state (CALLS_CALL (fixture->call_one), CALLS_CALL_STATE_INCOMING);
add_call (fixture->manager, fixture->ui_call_one);
/* main loop will quit in callback of notify::ring */
/* main loop will quit in callback of notify::state */
g_main_loop_run (fixture->loop);
g_assert_false (calls_ringer_get_is_ringing (fixture->ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
}
@@ -298,31 +298,27 @@ t5_on_ringer_multiple_calls_with_restart (CallsRinger *ringer,
switch (test_phase++) {
case 0:
g_assert_true (calls_ringer_get_is_ringing (ringer));
g_assert_false (calls_ringer_get_ring_is_quiet (ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_RINGING);
calls_call_answer (CALLS_CALL (fixture->call_one));
break;
case 1:
g_assert_true (calls_ringer_get_is_ringing (ringer));
g_assert_true (calls_ringer_get_ring_is_quiet (ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_RINGING_SOFT);
calls_call_hang_up (CALLS_CALL (fixture->call_one));
break;
case 2:
g_assert_true (calls_ringer_get_is_ringing (ringer));
g_assert_false (calls_ringer_get_ring_is_quiet (ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_RINGING);
calls_call_hang_up (CALLS_CALL (fixture->call_two));
break;
case 3:
g_assert_false (calls_ringer_get_is_ringing (ringer));
g_assert_false (calls_ringer_get_ring_is_quiet (ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
g_main_loop_quit (fixture->loop);
break;
default:
g_assert_not_reached (); /* did not find equivalent cmocka assertion */
g_assert_not_reached ();
}
}
@@ -330,10 +326,10 @@ static void
test_ringing_multiple_calls_with_restart (RingerFixture *fixture,
gconstpointer user_data)
{
g_assert_false (calls_ringer_get_is_ringing (fixture->ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
g_signal_connect (fixture->ringer,
"notify::ringing",
"notify::state",
G_CALLBACK (t5_on_ringer_multiple_calls_with_restart),
fixture);
@@ -342,10 +338,10 @@ test_ringing_multiple_calls_with_restart (RingerFixture *fixture,
calls_call_set_state (CALLS_CALL (fixture->call_two), CALLS_CALL_STATE_INCOMING);
add_call (fixture->manager, fixture->ui_call_two);
/* main loop will quit in callback of notify::ring */
/* main loop will quit in callback of notify::state */
g_main_loop_run (fixture->loop);
g_assert_false (calls_ringer_get_is_ringing (fixture->ringer));
g_assert_cmpint (calls_ringer_get_state (fixture->ringer), ==, CALLS_RING_STATE_INACTIVE);
}
int