Emergency call redial implementation
Handle EMERGENCY_PERM_FAILURE and
EMERGENCY_TEMP_FAILURE DisconnectCause
for redial Emergency call.
Bug: 27059146
Change-Id: Ie72ab2901ec05d972204ed11f115a05b79173c1d
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index 26690b9..a420100 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -128,7 +128,6 @@
case android.telephony.DisconnectCause.MAXIMUM_NUMBER_OF_CALLS_REACHED:
case android.telephony.DisconnectCause.DATA_DISABLED:
case android.telephony.DisconnectCause.DATA_LIMIT_REACHED:
- case android.telephony.DisconnectCause.DIALED_ON_WRONG_SLOT:
case android.telephony.DisconnectCause.DIALED_CALL_FORWARDING_WHILE_ROAMING:
case android.telephony.DisconnectCause.IMEI_NOT_ACCEPTED:
case android.telephony.DisconnectCause.WIFI_LOST:
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 064d1f1..6a14e88 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -94,6 +94,7 @@
private static final int MSG_ON_HOLD_TONE = 14;
private static final int MSG_CDMA_VOICE_PRIVACY_ON = 15;
private static final int MSG_CDMA_VOICE_PRIVACY_OFF = 16;
+ private static final int MSG_HANGUP = 17;
private final Handler mHandler = new Handler() {
@Override
@@ -240,6 +241,10 @@
Log.d(this, "MSG_CDMA_VOICE_PRIVACY_OFF received");
setCdmaVoicePrivacy(false);
break;
+ case MSG_HANGUP:
+ int cause = (int) msg.obj;
+ hangup(cause);
+ break;
}
}
};
@@ -258,7 +263,7 @@
*/
public abstract static class TelephonyConnectionListener {
public void onOriginalConnectionConfigured(TelephonyConnection c) {}
- public void onOriginalConnectionRetry(TelephonyConnection c) {}
+ public void onOriginalConnectionRetry(TelephonyConnection c, boolean isPermanentFailure) {}
}
private final PostDialListener mPostDialListener = new PostDialListener() {
@@ -544,7 +549,7 @@
@Override
public void onDisconnect() {
Log.v(this, "onDisconnect");
- hangup(android.telephony.DisconnectCause.LOCAL);
+ mHandler.obtainMessage(MSG_HANGUP, android.telephony.DisconnectCause.LOCAL).sendToTarget();
}
/**
@@ -579,7 +584,7 @@
@Override
public void onAbort() {
Log.v(this, "onAbort");
- hangup(android.telephony.DisconnectCause.LOCAL);
+ mHandler.obtainMessage(MSG_HANGUP, android.telephony.DisconnectCause.LOCAL).sendToTarget();
}
@Override
@@ -608,7 +613,8 @@
public void onReject() {
Log.v(this, "onReject");
if (isValidRingingCall()) {
- hangup(android.telephony.DisconnectCause.INCOMING_REJECTED);
+ mHandler.obtainMessage(MSG_HANGUP, android.telephony.DisconnectCause.INCOMING_REJECTED)
+ .sendToTarget();
}
super.onReject();
}
@@ -1093,8 +1099,8 @@
if (mOriginalConnection != null) {
try {
// Hanging up a ringing call requires that we invoke call.hangup() as opposed to
- // connection.hangup(). Without this change, the party originating the call will not
- // get sent to voicemail if the user opts to reject the call.
+ // connection.hangup(). Without this change, the party originating the call
+ // will not get sent to voicemail if the user opts to reject the call.
if (isValidRingingCall()) {
Call call = getCall();
if (call != null) {
@@ -1103,10 +1109,10 @@
Log.w(this, "Attempting to hangup a connection without backing call.");
}
} else {
- // We still prefer to call connection.hangup() for non-ringing calls in order
- // to support hanging-up specific calls within a conference call. If we invoked
- // call.hangup() while in a conference, we would end up hanging up the entire
- // conference call instead of the specific connection.
+ // We still prefer to call connection.hangup() for non-ringing calls
+ // in order to support hanging-up specific calls within a conference call.
+ // If we invoked call.hangup() while in a conference, we would end up
+ // hanging up the entire conference call instead of the specific connection.
mOriginalConnection.hangup();
}
} catch (CallStateException e) {
@@ -1297,6 +1303,7 @@
} else {
newState = mOriginalConnection.getState();
}
+ int cause = mOriginalConnection.getDisconnectCause();
Log.v(this, "Update state from %s to %s for %s", mConnectionState, newState, this);
if (mConnectionState != newState) {
@@ -1323,13 +1330,18 @@
setRinging();
break;
case DISCONNECTED:
- // We can get into a situation where the radio wants us to redial the same
- // emergency call on the other available slot. This will not set the state to
- // disconnected and will instead tell the TelephonyConnectionService to create
- // a new originalConnection using the new Slot.
- if (mOriginalConnection.getDisconnectCause() ==
- DisconnectCause.DIALED_ON_WRONG_SLOT) {
- fireOnOriginalConnectionRetryDial();
+ if (shouldTreatAsEmergencyCall()
+ && (cause
+ == android.telephony.DisconnectCause.EMERGENCY_TEMP_FAILURE
+ || cause
+ == android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE)) {
+ // We can get into a situation where the radio wants us to redial the
+ // same emergency call on the other available slot. This will not set
+ // the state to disconnected and will instead tell the
+ // TelephonyConnectionService to
+ // create a new originalConnection using the new Slot.
+ fireOnOriginalConnectionRetryDial(cause
+ == android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE);
} else {
setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
mOriginalConnection.getDisconnectCause(),
@@ -1728,9 +1740,9 @@
}
}
- private final void fireOnOriginalConnectionRetryDial() {
+ private final void fireOnOriginalConnectionRetryDial(boolean isPermanentFailure) {
for (TelephonyConnectionListener l : mTelephonyListeners) {
- l.onOriginalConnectionRetry(this);
+ l.onOriginalConnectionRetry(this, isPermanentFailure);
}
}
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 53bfd68..50bb096 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -61,6 +61,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Objects;
import java.util.List;
import java.util.regex.Pattern;
@@ -238,8 +239,8 @@
}
@Override
- public void onOriginalConnectionRetry(TelephonyConnection c) {
- retryOutgoingOriginalConnection(c);
+ public void onOriginalConnectionRetry(TelephonyConnection c, boolean isPermanentFailure) {
+ retryOutgoingOriginalConnection(c, isPermanentFailure);
}
};
@@ -895,7 +896,8 @@
// Check the mEmergencyRetryCache to see if it contains the TelephonyConnection. If it doesn't,
// then it is stale. Create a new one!
- private void updateCachedConnectionPhonePair(TelephonyConnection c) {
+ private void updateCachedConnectionPhonePair(TelephonyConnection c,
+ boolean isPermanentFailure) {
if (mEmergencyRetryCache == null) {
Log.i(this, "updateCachedConnectionPhonePair, cache is null. Generating new cache");
mEmergencyRetryCache = makeCachedConnectionPhonePair(c);
@@ -905,36 +907,44 @@
if (cachedConnection.get() != c) {
Log.i(this, "updateCachedConnectionPhonePair, cache is stale. Regenerating.");
mEmergencyRetryCache = makeCachedConnectionPhonePair(c);
+ } else {
+ List<Phone> cachedPhones = mEmergencyRetryCache.second;
+ Phone phoneUsed = c.getPhone();
+ if (phoneUsed == null) {
+ return;
+ }
+ // c.getPhone() can return ImsPhone object also, But here we are interested in
+ // GsmCdmaPhone object, hence get corresponding GsmCdmaPhone object from
+ // PhoneFactory.
+ Phone PhoneToBeUpdated = PhoneFactory.getPhone(phoneUsed.getPhoneId());
+ // Remove phone used from the list, but for temporary fail cause, it will be added
+ // back to list further in this method. However in case of permanent failure, the
+ // phone shouldn't be reused, hence it will not be added back again.
+ cachedPhones.remove(PhoneToBeUpdated);
+ Log.i(this, "updateCachedConnectionPhonePair, isPermanentFailure:"
+ + isPermanentFailure);
+ if (!isPermanentFailure) {
+ // In case of temporary failure, add the phone back, this will result adding it
+ // to tail of list mEmergencyRetryCache.second, giving other phone more
+ // priority and that is what we want.
+ cachedPhones.add(PhoneToBeUpdated);
+ }
}
}
}
- /**
- * Returns the first Phone that has not been used yet to place the call. Any Phones that have
- * been used to place a call will have already been removed from mEmergencyRetryCache.second.
- * The phone that it excluded will be removed from mEmergencyRetryCache.second in this method.
- * @param phoneToExclude The Phone object that will be removed from our cache of available
- * phones.
- * @return the first Phone that is available to be used to retry the call.
- */
- private Phone getPhoneForRedial(Phone phoneToExclude) {
- List<Phone> cachedPhones = mEmergencyRetryCache.second;
- if (cachedPhones.contains(phoneToExclude)) {
- Log.i(this, "getPhoneForRedial, removing Phone[" + phoneToExclude.getPhoneId() +
- "] from the available Phone cache.");
- cachedPhones.remove(phoneToExclude);
- }
- return cachedPhones.isEmpty() ? null : cachedPhones.get(0);
- }
-
- private void retryOutgoingOriginalConnection(TelephonyConnection c) {
- updateCachedConnectionPhonePair(c);
- Phone newPhoneToUse = getPhoneForRedial(c.getPhone());
+ private void retryOutgoingOriginalConnection(
+ TelephonyConnection c, boolean isPermanentFailure) {
+ int phoneId = c.getPhone() == null ? -1 : c.getPhone().getPhoneId();
+ updateCachedConnectionPhonePair(c, isPermanentFailure);
+ Phone newPhoneToUse = (mEmergencyRetryCache.second != null) ?
+ mEmergencyRetryCache.second.get(0) : null;
if (newPhoneToUse != null) {
int videoState = c.getVideoState();
Bundle connExtras = c.getExtras();
Log.i(this, "retryOutgoingOriginalConnection, redialing on Phone Id: " + newPhoneToUse);
c.clearOriginalConnection();
+ if (phoneId != newPhoneToUse.getPhoneId()) updatePhoneAccount(c, newPhoneToUse);
placeOutgoingConnection(c, newPhoneToUse, videoState, connExtras);
} else {
// We have run out of Phones to use. Disconnect the call and destroy the connection.
@@ -945,6 +955,16 @@
}
}
+ private void updatePhoneAccount(TelephonyConnection connection, Phone phone) {
+ PhoneAccountHandle pHandle = PhoneUtils.makePstnPhoneAccountHandle(phone);
+ // For ECall handling on MSIM, till the request reaches here(i.e PhoneApp)
+ // we dont know on which phone account ECall can be placed, once after deciding
+ // the phone account for ECall we should inform Telecomm so that
+ // the proper sub information will be displayed on InCallUI.
+ Log.i(this, "updatePhoneAccount setPhoneAccountHandle, account = " + pHandle);
+ connection.notifyPhoneAccountChanged(pHandle);
+ }
+
private void placeOutgoingConnection(
TelephonyConnection connection, Phone phone, ConnectionRequest request) {
placeOutgoingConnection(connection, phone, request.getVideoState(), request.getExtras());