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

Commit 12f290d9 authored by Susheel Nyamala's avatar Susheel Nyamala Committed by Jack Yu
Browse files

Add support to retry for DDS switch failures

DDS requests are rejected when there is active call. Add support
to retry failed DDS switch imediately on call end

Also, DDS request fails when SIM is not ready. Retry failed DDS
switch once SIM moves to ready state

Added UT for these changes

Change-Id: I34021984b0245d53ccce80dd986434ff1539f645
Bug: 169649103
Test: Unit tests
parent 9b7d07ad
Loading
Loading
Loading
Loading
+153 −12
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import android.os.RemoteException;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyRegistryManager;
@@ -78,7 +79,9 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

/**
@@ -271,6 +274,7 @@ public class PhoneSwitcher extends Handler {
    @VisibleForTesting
    public static final int EVENT_MULTI_SIM_CONFIG_CHANGED        = 117;
    private static final int EVENT_NETWORK_AVAILABLE              = 118;
    private static final int EVENT_PROCESS_SIM_STATE_CHANGE       = 119;

    // Depending on version of IRadioConfig, we need to send either RIL_REQUEST_ALLOW_DATA if it's
    // 1.0, or RIL_REQUEST_SET_PREFERRED_DATA if it's 1.1 or later. So internally mHalCommandToUse
@@ -291,6 +295,8 @@ public class PhoneSwitcher extends Handler {

    private ConnectivityManager mConnectivityManager;

    private List<Set<CommandException.Error>> mCurrentDdsSwitchFailure;

    private class DefaultNetworkCallback extends ConnectivityManager.NetworkCallback {
        public int mExpectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
        public int mSwitchReason = TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN;
@@ -402,6 +408,11 @@ public class PhoneSwitcher extends Handler {
        mRadioConfig = RadioConfig.getInstance();
        mValidator = CellularNetworkValidator.getInstance();

        mCurrentDdsSwitchFailure = new ArrayList<Set<CommandException.Error>>();
        IntentFilter filter = new IntentFilter();
        filter.addAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED);
        mContext.registerReceiver(mSimStateIntentReceiver, filter);

        mActivePhoneRegistrants = new RegistrantList();
        for (int i = 0; i < mActiveModemCount; i++) {
            mPhoneStates[i] = new PhoneState();
@@ -418,6 +429,8 @@ public class PhoneSwitcher extends Handler {
                PhoneFactory.getPhone(i).getDataEnabledSettings().registerForDataEnabledChanged(
                        this, EVENT_DATA_ENABLED_CHANGED, null);
            }
            Set<CommandException.Error> ddsFailure = new HashSet<CommandException.Error>();
            mCurrentDdsSwitchFailure.add(ddsFailure);
        }

        if (mActiveModemCount > 0) {
@@ -461,6 +474,8 @@ public class PhoneSwitcher extends Handler {
        // we want to see all requests
        networkFactory.registerIgnoringScore();

        updateHalCommandToUse();

        log("PhoneSwitcher started");
    }

@@ -472,6 +487,40 @@ public class PhoneSwitcher extends Handler {
        }
    };

    private BroadcastReceiver mSimStateIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED)) {
                int state = intent.getIntExtra(TelephonyManager.EXTRA_SIM_STATE,
                        TelephonyManager.SIM_STATE_UNKNOWN);
                int slotIndex = intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX,
                        SubscriptionManager.INVALID_SIM_SLOT_INDEX);
                log("mSimStateIntentReceiver: slotIndex = " + slotIndex + " state = " + state);
                obtainMessage(EVENT_PROCESS_SIM_STATE_CHANGE, slotIndex, state).sendToTarget();
            }
        }
    };

    private boolean isSimApplicationReady(int slotIndex) {
        if (!SubscriptionManager.isValidSlotIndex(slotIndex)) {
            return false;
        }

        SubscriptionInfo info = SubscriptionController.getInstance()
                .getActiveSubscriptionInfoForSimSlotIndex(slotIndex,
                mContext.getOpPackageName(), null);
        boolean uiccAppsEnabled = info != null && info.areUiccApplicationsEnabled();

        IccCard iccCard = PhoneFactory.getPhone(slotIndex).getIccCard();
        if (!iccCard.isEmptyProfile() && uiccAppsEnabled) {
            log("isSimApplicationReady: SIM is ready for slotIndex: " + slotIndex);
            return true;
        } else {
            return false;
        }
    }

    private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener =
            new SubscriptionManager.OnSubscriptionsChangedListener() {
        @Override
@@ -542,9 +591,21 @@ public class PhoneSwitcher extends Handler {
                break;
            }
            case EVENT_PRECISE_CALL_STATE_CHANGED: {
                log("EVENT_PRECISE_CALL_STATE_CHANGED");

                // If the phoneId in voice call didn't change, do nothing.
                if (!isPhoneInVoiceCallChanged()) break;

                if (!isAnyVoiceCallActiveOnDevice()) {
                    for (int i = 0; i < mActiveModemCount; i++) {
                        if (mCurrentDdsSwitchFailure.get(i).contains(
                                CommandException.Error.OP_NOT_ALLOWED_DURING_VOICE_CALL)
                                 && isPhoneIdValidForRetry(i)) {
                            sendRilCommands(i);
                        }
                    }
                }

                // Only handle this event if we are currently waiting for the emergency call
                // associated with the override request to start or end.
                if (mEmergencyOverride != null && mEmergencyOverride.mPendingOriginatingCall) {
@@ -595,18 +656,21 @@ public class PhoneSwitcher extends Handler {
                    mEmergencyOverride.sendOverrideCompleteCallbackResultAndClear(commandSuccess);
                    // Do not retry , as we do not allow changes in onEvaluate during an emergency
                    // call. When the call ends, we will start the countdown to remove the override.
                } else if (!commandSuccess) {
                } else {
                    int phoneId = (int) ar.userObj;
                    log("Modem command failed. with exception " + ar.exception);
                    sendMessageDelayed(Message.obtain(this, EVENT_MODEM_COMMAND_RETRY,
                            phoneId), MODEM_COMMAND_RETRY_PERIOD_MS);
                    onDdsSwitchResponse(ar, phoneId);
                }
                break;
            }
            case EVENT_MODEM_COMMAND_RETRY: {
                int phoneId = (int) msg.obj;
                log("Resend modem command on phone " + phoneId);
                if (isPhoneIdValidForRetry(phoneId)) {
                    log("EVENT_MODEM_COMMAND_RETRY: resend modem command on phone " + phoneId);
                    sendRilCommands(phoneId);
                } else {
                    log("EVENT_MODEM_COMMAND_RETRY: skip retry as DDS sub changed");
                    mCurrentDdsSwitchFailure.get(phoneId).clear();
                }
                break;
            }
            case EVENT_OVERRIDE_DDS_FOR_EMERGENCY: {
@@ -664,6 +728,21 @@ public class PhoneSwitcher extends Handler {
                onMultiSimConfigChanged(activeModemCount);
                break;
            }
            case EVENT_PROCESS_SIM_STATE_CHANGE: {
                int slotIndex = (int) msg.arg1;
                int simState = (int) msg.arg2;

                if (!SubscriptionManager.isValidSlotIndex(slotIndex)) {
                    log("EVENT_PROCESS_SIM_STATE_CHANGE: skip processing due to invalid slotId: "
                            + slotIndex);
                } else if (mCurrentDdsSwitchFailure.get(slotIndex).contains(
                        CommandException.Error.INVALID_SIM_STATE)
                        && (TelephonyManager.SIM_STATE_LOADED == simState)
                        && isSimApplicationReady(slotIndex)) {
                    sendRilCommands(slotIndex);
                }
                break;
            }
        }
    }

@@ -675,6 +754,8 @@ public class PhoneSwitcher extends Handler {

        mPhoneSubscriptions = copyOf(mPhoneSubscriptions, mActiveModemCount);
        mPhoneStates = copyOf(mPhoneStates, mActiveModemCount);
        //clear the list in case of multisim config change
        mCurrentDdsSwitchFailure.clear();

        // Single SIM -> dual SIM switch.
        for (int phoneId = oldActiveModemCount; phoneId < mActiveModemCount; phoneId++) {
@@ -691,6 +772,9 @@ public class PhoneSwitcher extends Handler {
            }
            phone.getDataEnabledSettings().registerForDataEnabledChanged(
                    this, EVENT_DATA_ENABLED_CHANGED, null);

            Set<CommandException.Error> ddsFailure = new HashSet<CommandException.Error>();
            mCurrentDdsSwitchFailure.add(ddsFailure);
        }
    }

@@ -947,11 +1031,6 @@ public class PhoneSwitcher extends Handler {
                    activate(phoneId);
                }
            }

            notifyPreferredDataSubIdChanged();

            // Notify all registrants.
            mActivePhoneRegistrants.notifyRegistrants();
        }
        return diffDetected;
    }
@@ -1021,7 +1100,10 @@ public class PhoneSwitcher extends Handler {
    }

    protected void sendRilCommands(int phoneId) {
        if (!SubscriptionManager.isValidPhoneId(phoneId)) return;
        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
            log("sendRilCommands: skip dds switch due to invalid phoneid=" + phoneId);
            return;
        }

        Message message = Message.obtain(this, EVENT_MODEM_COMMAND_DONE, phoneId);
        if (mHalCommandToUse == HAL_COMMAND_ALLOW_DATA || mHalCommandToUse == HAL_COMMAND_UNKNOWN) {
@@ -1455,4 +1537,63 @@ public class PhoneSwitcher extends Handler {
        mLocalLog.dump(fd, pw, args);
        pw.decreaseIndent();
    }

    private boolean isAnyVoiceCallActiveOnDevice() {
        boolean ret = mPhoneIdInVoiceCall != SubscriptionManager.INVALID_PHONE_INDEX;
        log("isAnyVoiceCallActiveOnDevice: " + ret);
        return ret;
    }

    private void onDdsSwitchResponse(AsyncResult ar, int phoneId) {
        if (ar.exception != null) {
            log("onDdsSwitchResponse: DDS switch failed. with exception " + ar.exception);
            if (ar.exception instanceof CommandException) {
                CommandException.Error error = ((CommandException)
                        (ar.exception)).getCommandError();
                mCurrentDdsSwitchFailure.get(phoneId).add(error);
                if (error == CommandException.Error.OP_NOT_ALLOWED_DURING_VOICE_CALL) {
                    log("onDdsSwitchResponse: Wait for call end indication");
                    return;
                } else if (error == CommandException.Error.INVALID_SIM_STATE) {
                    /* If there is a attach failure due to sim not ready then
                    hold the retry until sim gets ready */
                    log("onDdsSwitchResponse: Wait for SIM to get READY");
                    return;
                }
            }

            log("onDdsSwitchResponse: Scheduling DDS switch retry");
            sendMessageDelayed(Message.obtain(this, EVENT_MODEM_COMMAND_RETRY,
                        phoneId), MODEM_COMMAND_RETRY_PERIOD_MS);
        } else {
            log("onDdsSwitchResponse: DDS switch success on phoneId = " + phoneId);
            mCurrentDdsSwitchFailure.get(phoneId).clear();
            // Notify all registrants
            mActivePhoneRegistrants.notifyRegistrants();
            notifyPreferredDataSubIdChanged();
        }
    }

    private boolean isPhoneIdValidForRetry(int phoneId) {
        int phoneIdForRequest = INVALID_PHONE_INDEX;
        int ddsPhoneId = mSubscriptionController.getPhoneId(
                mSubscriptionController.getDefaultDataSubId());
        if (ddsPhoneId != INVALID_PHONE_INDEX && ddsPhoneId == phoneId) {
            return true;
        } else {
            if (mPrioritizedDcRequests.size() == 0) {
                return false;
            }
            for (int i = 0; i < mMaxDataAttachModemCount; i++) {
                DcRequest dcRequest = mPrioritizedDcRequests.get(i);
                if (dcRequest != null) {
                    phoneIdForRequest = phoneIdForRequest(dcRequest.networkRequest);
                    if (phoneIdForRequest == phoneId) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
}
+115 −5

File changed.

Preview size limit exceeded, changes collapsed.