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

Commit c164fda2 authored by Malcolm Chen's avatar Malcolm Chen
Browse files

Switch data to non default SIM if mobile data enabled and in call.

If the non default data SIM has an active call and its mobile data
is turned on in Settings, we switch internet on it until call ends.

Bug: 117980553
Test: unittest
Change-Id: I877b38e1572f0ab42de379ffa7dc61d00c585b59
Merged-In: I877b38e1572f0ab42de379ffa7dc61d00c585b59
parent cfd90aec
Loading
Loading
Loading
Loading
+66 −13
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.telephony;

import static android.telephony.PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE;
import static android.telephony.PhoneStateListener.LISTEN_PRECISE_CALL_STATE;
import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
import static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -39,6 +40,7 @@ import android.os.RegistrantList;
import android.os.RemoteException;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
import android.telephony.PreciseCallState;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -76,7 +78,8 @@ public class PhoneSwitcher extends Handler {
    private final int mNumPhones;
    private final Phone[] mPhones;
    private final LocalLog mLocalLog;
    private final PhoneStateListener mPhoneStateListener;
    @VisibleForTesting
    public final PhoneStateListener mPhoneStateListener;

    private int mMaxActivePhones;
    private static PhoneSwitcher sPhoneSwitcher = null;
@@ -95,6 +98,8 @@ public class PhoneSwitcher extends Handler {
    // Corresponding phoneId after considerting mPreferredDataSubId and mDefaultDataSubId above.
    protected int mPreferredDataPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;

    private int mPhoneIdInCall = SubscriptionManager.INVALID_PHONE_INDEX;

    private static final int EVENT_DEFAULT_SUBSCRIPTION_CHANGED   = 101;
    private static final int EVENT_SUBSCRIPTION_CHANGED           = 102;
    private static final int EVENT_REQUEST_NETWORK                = 103;
@@ -103,6 +108,7 @@ public class PhoneSwitcher extends Handler {
    private static final int EVENT_RADIO_CAPABILITY_CHANGED       = 106;
    private static final int EVENT_PREFERRED_SUBSCRIPTION_CHANGED = 107;
    private static final int EVENT_RADIO_AVAILABLE                = 108;
    private static final int EVENT_PHONE_IN_CALL_CHANGED          = 109;

    // 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
@@ -174,14 +180,38 @@ public class PhoneSwitcher extends Handler {
        mRadioConfig = RadioConfig.getInstance(mContext);

        mPhoneStateListener = new PhoneStateListener(looper) {
            @Override
            public void onPhoneCapabilityChanged(PhoneCapability capability) {
                onPhoneCapabilityChangedInternal(capability);
            }

            @Override
            public void onPreciseCallStateChanged(PreciseCallState callState) {
                int oldPhoneIdInCall = mPhoneIdInCall;
                // If there's no active call, the value will become INVALID_PHONE_INDEX
                // and internet data will be switched back to system selected or user selected
                // subscription.
                mPhoneIdInCall = SubscriptionManager.INVALID_PHONE_INDEX;
                for (Phone phone : mPhones) {
                    if (isCallActive(phone) || isCallActive(phone.getImsPhone())) {
                        mPhoneIdInCall = phone.getPhoneId();
                        break;
                    }
                }

                if (mPhoneIdInCall != oldPhoneIdInCall) {
                    log("mPhoneIdInCall changed from" + oldPhoneIdInCall
                            + " to " + mPhoneIdInCall);
                    Message msg = PhoneSwitcher.this.obtainMessage(EVENT_PHONE_IN_CALL_CHANGED);
                    msg.sendToTarget();
                }
            }
        };

        TelephonyManager telephonyManager =
                (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        telephonyManager.listen(mPhoneStateListener, LISTEN_PHONE_CAPABILITY_CHANGE);
        telephonyManager.listen(mPhoneStateListener, LISTEN_PHONE_CAPABILITY_CHANGE
                | LISTEN_PRECISE_CALL_STATE);

        mActivePhoneRegistrants = new RegistrantList();
        mPhoneStates = new PhoneState[numPhones];
@@ -282,6 +312,10 @@ public class PhoneSwitcher extends Handler {
                onEvaluate(REQUESTS_UNCHANGED, "EVENT_RADIO_AVAILABLE");
                break;
            }
            case EVENT_PHONE_IN_CALL_CHANGED: {
                onEvaluate(REQUESTS_UNCHANGED, "EVENT_PHONE_IN_CALL_CHANGED");
                break;
            }
        }
    }

@@ -404,7 +438,7 @@ public class PhoneSwitcher extends Handler {
                 */
                if (mMaxActivePhones == mPhones.length) {
                    for (int i = 0; i < mMaxActivePhones; i++) {
                        newActivePhones.add(mPhones[i].mPhoneId);
                        newActivePhones.add(mPhones[i].getPhoneId());
                    }
                } else {
                    for (DcRequest dcRequest : mPrioritizedDcRequests) {
@@ -571,6 +605,14 @@ public class PhoneSwitcher extends Handler {
    // This updates mPreferredDataPhoneId which decides which phone should
    // handle default network requests.
    private void updatePhoneIdForDefaultNetworkRequests() {
        if (SubscriptionManager.isValidPhoneId(mPhoneIdInCall)) {
            // If a phone is in call and user enabled its mobile data, we
            // should switch internet connection to it. Because the other modem
            // will lose data connection anyway.
            // TODO: validate network first.

            mPreferredDataPhoneId = mPhoneIdInCall;
        } else {
            int subId = getSubIdForDefaultNetworkRequests();
            int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;

@@ -585,6 +627,7 @@ public class PhoneSwitcher extends Handler {

            mPreferredDataPhoneId = phoneId;
        }
    }

    public boolean shouldApplyNetworkRequest(NetworkRequest networkRequest, int phoneId) {
        validatePhoneId(phoneId);
@@ -636,6 +679,16 @@ public class PhoneSwitcher extends Handler {
        }
    }

    private boolean isCallActive(Phone phone) {
        if (phone == null) {
            return false;
        }

        return (phone.getForegroundCall().getState() == Call.State.ACTIVE
                || phone.getBackgroundCall().getState() == Call.State.ACTIVE
                || phone.getRingingCall().getState() == Call.State.ACTIVE);
    }

    private void updateHalCommandToUse() {
        mHalCommandToUse = mRadioConfig.isSetPreferredDataCommandSupported()
                ? HAL_COMMAND_PREFERRED_DATA : HAL_COMMAND_ALLOW_DATA;
+58 −0
Original line number Diff line number Diff line
@@ -68,6 +68,10 @@ public class PhoneSwitcherTest extends TelephonyTest {
    private Phone mPhone2; // mPhone as phone 1 is already defined in TelephonyTest.
    @Mock
    private Handler mActivePhoneSwitchHandler;
    @Mock
    private GsmCdmaCall mActiveCall;
    @Mock
    private GsmCdmaCall mInactiveCall;

    // The thread that mPhoneSwitcher will handle events in.
    private HandlerThread mHandlerThread;
@@ -463,6 +467,57 @@ public class PhoneSwitcherTest extends TelephonyTest {

    }

    @Test
    @SmallTest
    public void testNonDefaultDataPhoneInCall() throws Exception {
        final int numPhones = 2;
        final int maxActivePhones = 1;
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize(numPhones, maxActivePhones);
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setSlotIndexToSubId(0, 1);
        setSlotIndexToSubId(1, 2);
        setDefaultDataSubId(1);
        waitABit();
        NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
        waitABit();
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        clearInvocations(mMockRadioConfig);

        doReturn(Call.State.ACTIVE).when(mActiveCall).getState();
        doReturn(Call.State.IDLE).when(mInactiveCall).getState();
        doReturn(mInactiveCall).when(mPhone).getForegroundCall();
        doReturn(mInactiveCall).when(mPhone).getBackgroundCall();
        doReturn(mInactiveCall).when(mPhone).getRingingCall();
        doReturn(mInactiveCall).when(mPhone2).getForegroundCall();
        doReturn(mInactiveCall).when(mPhone2).getBackgroundCall();
        doReturn(mInactiveCall).when(mPhone2).getRingingCall();

        // Initialization done.

        // Phone2 has active call. So data switch to it.
        doReturn(mActiveCall).when(mPhone2).getForegroundCall();
        mPhoneSwitcher.mPhoneStateListener.onPreciseCallStateChanged(null);
        waitABit();
        verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        clearInvocations(mMockRadioConfig);

        // Phone2 call ended. So data switch back to default data sub.
        doReturn(mInactiveCall).when(mPhone2).getForegroundCall();
        mPhoneSwitcher.mPhoneStateListener.onPreciseCallStateChanged(null);
        waitABit();
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));

        mHandlerThread.quit();
    }

    /* Private utility methods start here */

    private void sendDefaultDataSubChanged() {
@@ -503,11 +558,14 @@ public class PhoneSwitcherTest extends TelephonyTest {
    private void setNumPhones(int numPhones) {
        mDataAllowed = new boolean[numPhones];
        mSlotIndexToSubId = new int[numPhones][];
        doReturn(0).when(mPhone).getPhoneId();
        doReturn(1).when(mPhone2).getPhoneId();
        for (int i = 0; i < numPhones; i++) {
            mSlotIndexToSubId[i] = new int[1];
            mSlotIndexToSubId[i][0] = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
        }

        doReturn(numPhones).when(mTelephonyManager).getPhoneCount();
        if (numPhones == 1) {
            mCommandsInterfaces = new CommandsInterface[] {mCommandsInterface0};
            mPhones = new Phone[] {mPhone};