Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 542ae93d authored by Sungjae's avatar Sungjae Committed by Hall Liu
Browse files

Emergency: Enable silent redial CS to IMS



If emergency call needs to be triggered on IMS,
Redial call fail cause will be sent.
Define call fail cause to silent redial to IMS from CS.
(EMC_REDIAL_ON_IMS, EMC_REDIAL_ON_VOWIFI)
If call fail cause is EMC_REDIAL_ON_VOWIFI,
set extras to trigger VoWifi call.

Bug: 146531977

Change-Id: I9664e92a03fad7fb6307b4ec3464e0d7977fb4e5
Signed-off-by: default avatarSungjae <sung_jae.kim@samsung.com>
parent 8e289860
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -440,6 +440,15 @@ public interface CallFailCause {
     */
    int WIFI_LOST                                        = 2507;

    /**
     * Indicates a call was disconnected because retry over volte is needed.
     */
    int EMC_REDIAL_ON_IMS                                = 3001;

    /**
     * Indicates a call was disconnected because retry over vowifi is needed.
     */
    int EMC_REDIAL_ON_VOWIFI                             = 3002;

    /* OEM specific error codes. To be used by OEMs when they don't want to
       reveal error code which would be replaced by ERROR_UNSPECIFIED */
+24 −0
Original line number Diff line number Diff line
@@ -1552,6 +1552,22 @@ public class GsmCdmaCallTracker extends CallTracker {
                            TelephonyManager.getDefault().getNetworkType());
                }

                if (isEmcRetryCause(causeCode)) {
                    String dialString = "";
                    for(Connection conn : mForegroundCall.mConnections) {
                        GsmCdmaConnection gsmCdmaConnection = (GsmCdmaConnection)conn;
                        dialString = gsmCdmaConnection.getOrigDialString();
                        gsmCdmaConnection.getCall().detach(gsmCdmaConnection);
                        mDroppedDuringPoll.remove(gsmCdmaConnection);
                    }
                    mPhone.notifyVolteSilentRedial(dialString, causeCode);
                    updatePhoneState();
                    if (mDroppedDuringPoll.isEmpty()) {
                        log("LAST_CALL_FAIL_CAUSE - no Dropped normal Call");
                        return;
                    }
                }

                for (int i = 0, s = mDroppedDuringPoll.size(); i < s ; i++) {
                    GsmCdmaConnection conn = mDroppedDuringPoll.get(i);

@@ -1758,6 +1774,14 @@ public class GsmCdmaCallTracker extends CallTracker {
        return mPhone;
    }

    private boolean isEmcRetryCause(int causeCode) {
        if (causeCode == CallFailCause.EMC_REDIAL_ON_IMS ||
            causeCode == CallFailCause.EMC_REDIAL_ON_VOWIFI) {
            return true;
        }
        return false;
    }

    @UnsupportedAppUsage
    @Override
    protected void log(String msg) {
+22 −0
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ import com.android.internal.telephony.dataconnection.TransportManager;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.gsm.GsmMmiCode;
import com.android.internal.telephony.gsm.SuppServiceNotification;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.test.SimulatedRadioControl;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
import com.android.internal.telephony.uicc.IccCardStatus;
@@ -195,6 +196,9 @@ public class GsmCdmaPhone extends Phone {
    // mEcmTimerResetRegistrants are informed after Ecm timer is canceled or re-started
    private final RegistrantList mEcmTimerResetRegistrants = new RegistrantList();

    private final RegistrantList mVolteSilentRedialRegistrants = new RegistrantList();
    private DialArgs mDialArgs = null;

    private String mImei;
    private String mImeiSv;
    private String mVmNumber;
@@ -1264,6 +1268,7 @@ public class GsmCdmaPhone extends Phone {

        boolean isEmergency = PhoneNumberUtils.isEmergencyNumber(getSubId(), dialString);
        Phone imsPhone = mImsPhone;
        mDialArgs = dialArgs;

        CarrierConfigManager configManager =
                (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
@@ -4088,6 +4093,23 @@ public class GsmCdmaPhone extends Phone {
        mEcmTimerResetRegistrants.remove(h);
    }

    @Override
    public void registerForVolteSilentRedial(Handler h, int what, Object obj) {
        mVolteSilentRedialRegistrants.addUnique(h, what, obj);
    }

    @Override
    public void unregisterForVolteSilentRedial(Handler h) {
        mVolteSilentRedialRegistrants.remove(h);
    }

    public void notifyVolteSilentRedial(String dialString, int causeCode) {
        logd("notifyVolteSilentRedial: dialString=" + dialString + " causeCode=" + causeCode);
        AsyncResult ar = new AsyncResult(null,
                new SilentRedialParam(dialString, causeCode, mDialArgs), null);
        mVolteSilentRedialRegistrants.notifyRegistrants(ar);
    }

    /**
     * Sets the SIM voice message waiting indicator records.
     * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
+18 −0
Original line number Diff line number Diff line
@@ -254,6 +254,18 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        public String operatorAlphaShort;
    }

    public static class SilentRedialParam {
        public String dialString;
        public int causeCode;
        public DialArgs dialArgs;

        public SilentRedialParam(String dialString, int causeCode, DialArgs dialArgs) {
            this.dialString = dialString;
            this.causeCode = causeCode;
            this.dialArgs = dialArgs;
        }
    }

    /* Instance Variables */
    @UnsupportedAppUsage
    public CommandsInterface mCi;
@@ -744,6 +756,12 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    public void unregisterForSilentRedial(Handler h) {
    }

    public void registerForVolteSilentRedial(Handler h, int what, Object obj) {
    }

    public void unregisterForVolteSilentRedial(Handler h) {
    }

    private void handleSrvccStateChanged(int[] ret) {
        Rlog.d(LOG_TAG, "handleSrvccStateChanged");

+67 −0
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ import com.android.ims.ImsManager;
import com.android.ims.ImsUtInterface;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallFailCause;
import com.android.internal.telephony.CallForwardInfo;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.CallTracker;
@@ -136,6 +137,7 @@ public class ImsPhone extends ImsPhoneBase {
    @VisibleForTesting
    public static final int EVENT_SERVICE_STATE_CHANGED             = EVENT_LAST + 8;
    private static final int EVENT_VOICE_CALL_ENDED                  = EVENT_LAST + 9;
    private static final int EVENT_INITIATE_VOLTE_SILENT_REDIAL      = EVENT_LAST + 10;

    static final int RESTART_ECM_TIMER = 0; // restart Ecm timer
    static final int CANCEL_ECM_TIMER  = 1; // cancel Ecm timer
@@ -334,6 +336,8 @@ public class ImsPhone extends ImsPhoneBase {
        mDefaultPhone.registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null);
        // Force initial roaming state update later, on EVENT_CARRIER_CONFIG_CHANGED.
        // Settings provider or CarrierConfig may not be loaded now.

        mDefaultPhone.registerForVolteSilentRedial(this, EVENT_INITIATE_VOLTE_SILENT_REDIAL, null);
    }

    //todo: get rid of this function. It is not needed since parentPhone obj never changes
@@ -356,6 +360,10 @@ public class ImsPhone extends ImsPhoneBase {
            }
            mDefaultPhone.unregisterForServiceStateChanged(this);
        }

        if (mDefaultPhone != null) {
            mDefaultPhone.unregisterForVolteSilentRedial(this);
        }
    }

    @UnsupportedAppUsage
@@ -1597,6 +1605,36 @@ public class ImsPhone extends ImsPhoneBase {
                    updateRoamingState(sst.mSS);
                }
                break;
            case EVENT_INITIATE_VOLTE_SILENT_REDIAL: {
                if (VDBG) logd("EVENT_INITIATE_VOLTE_SILENT_REDIAL");
                ar = (AsyncResult) msg.obj;
                if (ar.exception == null && ar.result != null) {
                    SilentRedialParam result = (SilentRedialParam) ar.result;
                    String dialString = result.dialString;
                    int causeCode = result.causeCode;
                    DialArgs dialArgs = result.dialArgs;
                    if (VDBG) logd("dialString=" + dialString + " causeCode=" + causeCode);

                    try {
                        Connection cn = dial(dialString,
                                updateDialArgsForVolteSilentRedial(dialArgs, causeCode));
                        Rlog.d(LOG_TAG, "Notify volte redial connection changed cn: " + cn);
                        if (mDefaultPhone != null) {
                            // don't care it is null or not.
                            mDefaultPhone.notifyRedialConnectionChanged(cn);
                        }
                    } catch (CallStateException e) {
                        Rlog.e(LOG_TAG, "volte silent redial failed: " + e);
                        if (mDefaultPhone != null) {
                            mDefaultPhone.notifyRedialConnectionChanged(null);
                        }
                    }
                } else {
                    if (VDBG) logd("EVENT_INITIATE_VOLTE_SILENT_REDIAL" +
                                   " has exception or empty result");
                }
                break;
            }

            default:
                super.handleMessage(msg);
@@ -2113,6 +2151,35 @@ public class ImsPhone extends ImsPhoneBase {
        return mDefaultPhone.getIccRecords();
    }

    public DialArgs updateDialArgsForVolteSilentRedial(DialArgs dialArgs, int causeCode) {
        if (dialArgs != null) {
            ImsPhone.ImsDialArgs.Builder imsDialArgsBuilder;
            if (dialArgs instanceof ImsPhone.ImsDialArgs) {
                imsDialArgsBuilder = ImsPhone.ImsDialArgs.Builder
                                      .from((ImsPhone.ImsDialArgs) dialArgs);
            } else {
                imsDialArgsBuilder = ImsPhone.ImsDialArgs.Builder
                                      .from(dialArgs);
            }
            Bundle extras = new Bundle(dialArgs.intentExtras);
            if (causeCode == CallFailCause.EMC_REDIAL_ON_VOWIFI && isWifiCallingEnabled()) {
                extras.putString(ImsCallProfile.EXTRA_CALL_RAT_TYPE,
                        String.valueOf(ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN));
                logd("trigger VoWifi emergency call");
                imsDialArgsBuilder.setIntentExtras(extras);
            } else if (causeCode == CallFailCause.EMC_REDIAL_ON_IMS) {
                logd("trigger VoLte emergency call");
            }
            return imsDialArgsBuilder.build();
        }
        return new DialArgs.Builder<>().build();
    }

    public boolean hasAliveCall() {
        return (getForegroundCall().getState() != Call.State.IDLE ||
                getBackgroundCall().getState() != Call.State.IDLE);
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
        IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");