Ensure DISCONNECTING state is passed to the InCallService on local disc.
When a local disconnect request is requested from an InCallService, the
call is effectively in a DISCONNECTING state. This was not being
explicitly communicated to the InCallService, however, and instead it
was relying on the fact that other call updates would occur causing
the InCallService to be updated.
This CL explicitly invokes the onCallStateChanged callback in CallsManager
to ensure that the DISCONNECTING state is reported to the ICS immediately
should there be no intermediate call changes which would cause such an
update to occur.
Also, moved the logic for determining the "parceled call state" into the
com.android.server.telecom.Call so that it can be used in logging to
ensure Telecom logs more accurately report the call state the ICS will
see.
Also, updated a CallAudioManager log message reported when an invalid
audio route is specified; moved it to warning level and made it more
explicitly report that the log is due to an error in an InCallService
(I see this reported a lot as a root cause for bugs when it is completely
unrelated).
Test: Manual testing to verify disconnecting state passed immediately to
IncallService
Test: Add unit test to ensure disconnecting state will be passed to the
InCallController immediately.
Fixes: 155109531
Change-Id: I94d24182ee82679fb918244c9e3042dfce2f383a
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index c170599..491aed3 100755
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -821,7 +821,7 @@
return String.format(Locale.US, "[Call id=%s, state=%s, tpac=%s, cmgr=%s, handle=%s, "
+ "vidst=%s, childs(%d), has_parent(%b), cap=%s, prop=%s]",
mId,
- CallState.toString(mState),
+ CallState.toString(getParcelableCallState()),
getTargetPhoneAccount(),
getConnectionManagerPhoneAccount(),
Log.piiHandle(mHandle),
@@ -964,6 +964,20 @@
}
/**
+ * Similar to {@link #getState()}, except will return {@link CallState#DISCONNECTING} if the
+ * call is locally disconnecting. This is the call state which is reported to the
+ * {@link android.telecom.InCallService}s when a call is parcelled.
+ * @return The parcelable call state.
+ */
+ public int getParcelableCallState() {
+ if (isLocallyDisconnecting() &&
+ (mState != android.telecom.Call.STATE_DISCONNECTED)) {
+ return CallState.DISCONNECTING;
+ }
+ return mState;
+ }
+
+ /**
* Determines if this {@link Call} can receive call focus via the
* {@link ConnectionServiceFocusManager}.
* Only top-level calls and non-external calls are eligible.
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index b370815..dac5b4e 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -423,7 +423,7 @@
CallAudioRouteStateMachine.NO_INCLUDE_BLUETOOTH_IN_BASELINE);
return;
default:
- Log.wtf(this, "Invalid route specified: %d", route);
+ Log.w(this, "InCallService requested an invalid audio route: %d", route);
}
}
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index f2e8bc3..8fac4db 100755
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -2549,7 +2549,11 @@
Log.w(this, "Unknown call (%s) asked to disconnect", call);
} else {
mLocallyDisconnectingCalls.add(call);
+ int previousState = call.getState();
call.disconnect();
+ for (CallsManagerListener listener : mListeners) {
+ listener.onCallStateChanged(call, previousState, call.getState());
+ }
// Cancel any of the outgoing call futures if they're still around.
if (mPendingCallConfirm != null && !mPendingCallConfirm.isDone()) {
mPendingCallConfirm.complete(null);
@@ -3524,7 +3528,8 @@
return;
}
int oldState = call.getState();
- Log.i(this, "setCallState %s -> %s, call: %s", CallState.toString(oldState),
+ Log.i(this, "setCallState %s -> %s, call: %s",
+ CallState.toString(call.getParcelableCallState()),
CallState.toString(newState), call);
if (newState != oldState) {
// If the call switches to held state while a DTMF tone is playing, stop the tone to
diff --git a/src/com/android/server/telecom/ParcelableCallUtils.java b/src/com/android/server/telecom/ParcelableCallUtils.java
index 9638fee..5c821a4 100644
--- a/src/com/android/server/telecom/ParcelableCallUtils.java
+++ b/src/com/android/server/telecom/ParcelableCallUtils.java
@@ -381,7 +381,7 @@
private static int getParcelableState(Call call, boolean supportsExternalCalls) {
int state = CallState.NEW;
- switch (call.getState()) {
+ switch (call.getParcelableCallState()) {
case CallState.ABORTED:
case CallState.DISCONNECTED:
state = android.telecom.Call.STATE_DISCONNECTED;
@@ -433,12 +433,6 @@
break;
}
- // If we are marked as 'locally disconnecting' then mark ourselves as disconnecting instead.
- // Unless we're disconnect*ED*, in which case leave it at that.
- if (call.isLocallyDisconnecting() &&
- (state != android.telecom.Call.STATE_DISCONNECTED)) {
- state = android.telecom.Call.STATE_DISCONNECTING;
- }
return state;
}
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 8364869..6fd53eb 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -103,8 +103,10 @@
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
- assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
- assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_DISCONNECTING,
+ mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_DISCONNECTING,
+ mInCallServiceFixtureY.getCall(ids.mCallId).getState());
when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
@@ -259,12 +261,15 @@
IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
- assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
- assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_DISCONNECTING,
+ mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+ assertEquals(Call.STATE_DISCONNECTING,
+ mInCallServiceFixtureY.getCall(ids.mCallId).getState());
when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
+
assertEquals(Call.STATE_DISCONNECTED,
mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_DISCONNECTED,
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index e9794e3..9e7680a 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -66,6 +66,7 @@
import com.android.server.telecom.CallState;
import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.CallsManagerListenerBase;
import com.android.server.telecom.ClockProxy;
import com.android.server.telecom.ConnectionServiceFocusManager;
import com.android.server.telecom.ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory;
@@ -1390,6 +1391,26 @@
verify(heldCall).unhold(any());
}
+ /**
+ * Verifies we inform the InCallService on local disconnect.
+ * @throws Exception
+ */
+ @SmallTest
+ @Test
+ public void testRequestDisconnect() throws Exception {
+ CallsManager.CallsManagerListener listener = mock(CallsManager.CallsManagerListener.class);
+ mCallsManager.addListener(listener);
+
+ Call ongoingCall = addSpyCall(CallState.ACTIVE);
+ mCallsManager.addCall(ongoingCall);
+
+ mCallsManager.disconnectCall(ongoingCall);
+ // Seems odd, but ultimately the call state is still active even though it is locally
+ // disconnecting.
+ verify(listener).onCallStateChanged(eq(ongoingCall), eq(CallState.ACTIVE),
+ eq(CallState.ACTIVE));
+ }
+
private Call addSpyCall() {
return addSpyCall(SIM_2_HANDLE, CallState.ACTIVE);
}