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

Commit 57684f68 authored by Malcolm Chen's avatar Malcolm Chen
Browse files

Don't apply Internet network request specified on non-default sub.

Cellular network requests may specify a subscription ID. However
if the requests is asking for Internet capability, network factory
should ignore it if it's not targeted on preferred data phone.

In implementation, TelephonyNetworkFactory is refactored so that
it queries a PhoneSwitcher API on every network request to decide
whether it should be applied or not. This way PhoneSwitcher has
better control of distrubuting network requests more flexibly.

Bug: 121094781
Test: unittest
Change-Id: I49f8702b19c0bd0f559cf9a97b3d0fa41f6f7222
Merged-In: I49f8702b19c0bd0f559cf9a97b3d0fa41f6f7222
parent cb37406a
Loading
Loading
Loading
Loading
+57 −38
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.telephony;
package com.android.internal.telephony;


import static android.telephony.PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE;
import static android.telephony.PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE;
import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
import static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX;
import static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;


@@ -137,18 +138,18 @@ public class PhoneSwitcher extends Handler {
    }
    }


    @VisibleForTesting
    @VisibleForTesting
    public PhoneSwitcher(Looper looper) {
    public PhoneSwitcher(int numPhones, Looper looper) {
        super(looper);
        super(looper);
        mMaxActivePhones = 0;
        mMaxActivePhones = 0;
        mSubscriptionController = null;
        mSubscriptionController = null;
        mPhoneSubscriptions = null;
        mCommandsInterfaces = null;
        mCommandsInterfaces = null;
        mContext = null;
        mContext = null;
        mPhoneStates = null;
        mPhoneStates = null;
        mPhones = null;
        mPhones = null;
        mLocalLog = null;
        mLocalLog = null;
        mActivePhoneRegistrants = null;
        mActivePhoneRegistrants = null;
        mNumPhones = 0;
        mNumPhones = numPhones;
        mPhoneSubscriptions = new int[numPhones];
        mRadioConfig = RadioConfig.getInstance(mContext);
        mRadioConfig = RadioConfig.getInstance(mContext);
        mPhoneStateListener = new PhoneStateListener(looper) {
        mPhoneStateListener = new PhoneStateListener(looper) {
            public void onPhoneCapabilityChanged(PhoneCapability capability) {
            public void onPhoneCapabilityChanged(PhoneCapability capability) {
@@ -385,6 +386,11 @@ public class PhoneSwitcher extends Handler {
        if (diffDetected) {
        if (diffDetected) {
            log("evaluating due to " + sb.toString());
            log("evaluating due to " + sb.toString());
            if (mHalCommandToUse == HAL_COMMAND_PREFERRED_DATA) {
            if (mHalCommandToUse == HAL_COMMAND_PREFERRED_DATA) {
                // With HAL_COMMAND_PREFERRED_DATA, all phones are assumed to allow PS attach.
                // So marking all phone as active.
                for (int phoneId = 0; phoneId < mNumPhones; phoneId++) {
                    activate(phoneId);
                }
                if (SubscriptionManager.isUsableSubIdValue(mPreferredDataPhoneId)) {
                if (SubscriptionManager.isUsableSubIdValue(mPreferredDataPhoneId)) {
                    mRadioConfig.setPreferredDataModem(mPreferredDataPhoneId, null);
                    mRadioConfig.setPreferredDataModem(mPreferredDataPhoneId, null);
                }
                }
@@ -485,7 +491,7 @@ public class PhoneSwitcher extends Handler {
        if (mHalCommandToUse == HAL_COMMAND_ALLOW_DATA || mHalCommandToUse == HAL_COMMAND_UNKNOWN) {
        if (mHalCommandToUse == HAL_COMMAND_ALLOW_DATA || mHalCommandToUse == HAL_COMMAND_UNKNOWN) {
            // Skip ALLOW_DATA for single SIM device
            // Skip ALLOW_DATA for single SIM device
            if (mNumPhones > 1) {
            if (mNumPhones > 1) {
                mCommandsInterfaces[phoneId].setDataAllowed(mPhoneStates[phoneId].active, null);
                mCommandsInterfaces[phoneId].setDataAllowed(isPhoneActive(phoneId), null);
            }
            }
        } else {
        } else {
            mRadioConfig.setPreferredDataModem(mPreferredDataPhoneId, null);
            mRadioConfig.setPreferredDataModem(mPreferredDataPhoneId, null);
@@ -503,9 +509,38 @@ public class PhoneSwitcher extends Handler {
    }
    }


    private int phoneIdForRequest(NetworkRequest netRequest) {
    private int phoneIdForRequest(NetworkRequest netRequest) {
        NetworkSpecifier specifier = netRequest.networkCapabilities.getNetworkSpecifier();
        int subId = getSubIdFromNetworkRequest(netRequest);

        if (subId == DEFAULT_SUBSCRIPTION_ID) return mPreferredDataPhoneId;
        if (subId == INVALID_SUBSCRIPTION_ID) return INVALID_PHONE_INDEX;

        int preferredDataSubId = SubscriptionManager.isValidPhoneId(mPreferredDataPhoneId)
                ? mPhoneSubscriptions[mPreferredDataPhoneId] : INVALID_SUBSCRIPTION_ID;
        // Currently we assume multi-SIM devices will only support one Internet PDN connection. So
        // if Internet PDN is established on the non-preferred phone, it will interrupt
        // Internet connection on the preferred phone. So we only accept Internet request with
        // preferred data subscription or no specified subscription.
        if (netRequest.networkCapabilities.hasCapability(
                NetworkCapabilities.NET_CAPABILITY_INTERNET) && subId != preferredDataSubId) {
            // Returning INVALID_PHONE_INDEX will result in netRequest not being handled.
            return INVALID_PHONE_INDEX;
        }

        // Try to find matching phone ID. If it doesn't exist, we'll end up returning INVALID.
        int phoneId = INVALID_PHONE_INDEX;
        for (int i = 0; i < mNumPhones; i++) {
            if (mPhoneSubscriptions[i] == subId) {
                phoneId = i;
                break;
            }
        }
        return phoneId;
    }

    private int getSubIdFromNetworkRequest(NetworkRequest networkRequest) {
        NetworkSpecifier specifier = networkRequest.networkCapabilities.getNetworkSpecifier();
        if (specifier == null) {
        if (specifier == null) {
            return mPreferredDataPhoneId;
            return DEFAULT_SUBSCRIPTION_ID;
        }
        }


        int subId;
        int subId;
@@ -516,22 +551,13 @@ public class PhoneSwitcher extends Handler {
            } catch (NumberFormatException e) {
            } catch (NumberFormatException e) {
                Rlog.e(LOG_TAG, "NumberFormatException on "
                Rlog.e(LOG_TAG, "NumberFormatException on "
                        + ((StringNetworkSpecifier) specifier).specifier);
                        + ((StringNetworkSpecifier) specifier).specifier);
                subId = INVALID_SUBSCRIPTION_ID;
                return INVALID_SUBSCRIPTION_ID;
            }
            }
        } else {
        } else {
            subId = INVALID_SUBSCRIPTION_ID;
            return INVALID_SUBSCRIPTION_ID;
        }
        }


        int phoneId = INVALID_PHONE_INDEX;
        return subId;
        if (subId == INVALID_SUBSCRIPTION_ID) return phoneId;

        for (int i = 0 ; i < mNumPhones; i++) {
            if (mPhoneSubscriptions[i] == subId) {
                phoneId = i;
                break;
            }
        }
        return phoneId;
    }
    }


    private int getSubIdForDefaultNetworkRequests() {
    private int getSubIdForDefaultNetworkRequests() {
@@ -560,28 +586,20 @@ public class PhoneSwitcher extends Handler {
        mPreferredDataPhoneId = phoneId;
        mPreferredDataPhoneId = phoneId;
    }
    }


    /**
    public boolean shouldApplyNetworkRequest(NetworkRequest networkRequest, int phoneId) {
     * Returns whether phone should handle network requests
     * that don't specify a subId.
     */
    public boolean shouldApplyUnspecifiedRequests(int phoneId) {
        validatePhoneId(phoneId);
        validatePhoneId(phoneId);
        if (mHalCommandToUse == HAL_COMMAND_PREFERRED_DATA) {

            return phoneId == mPreferredDataPhoneId;
        // In any case, if phone state is inactive, don't apply the network request.
        } else {
        if (!isPhoneActive(phoneId)) return false;
            return mPhoneStates[phoneId].active && phoneId == mPreferredDataPhoneId;

        }
        int phoneIdToHandle = phoneIdForRequest(networkRequest);

        return phoneId == phoneIdToHandle;
    }
    }


    /**
    @VisibleForTesting
     * Returns whether phone should handle network requests
    protected boolean isPhoneActive(int phoneId) {
     * that specify a subId.
        return mPhoneStates[phoneId].active;
     */
    public boolean shouldApplySpecifiedRequests(int phoneId) {
        validatePhoneId(phoneId);
        // If we use SET_PREFERRED_DATA, always apply specified network requests. Otherwise,
        // only apply network requests if the phone is active (dataAllowed).
        return mHalCommandToUse == HAL_COMMAND_PREFERRED_DATA || mPhoneStates[phoneId].active;
    }
    }


    /**
    /**
@@ -598,7 +616,8 @@ public class PhoneSwitcher extends Handler {
        mActivePhoneRegistrants.remove(h);
        mActivePhoneRegistrants.remove(h);
    }
    }


    private void validatePhoneId(int phoneId) {
    @VisibleForTesting
    protected void validatePhoneId(int phoneId) {
        if (phoneId < 0 || phoneId >= mNumPhones) {
        if (phoneId < 0 || phoneId >= mNumPhones) {
            throw new IllegalArgumentException("Invalid PhoneId");
            throw new IllegalArgumentException("Invalid PhoneId");
        }
        }
+55 −97
Original line number Original line Diff line number Diff line
@@ -43,22 +43,22 @@ public class TelephonyNetworkFactory extends NetworkFactory {
    public final String LOG_TAG;
    public final String LOG_TAG;
    protected static final boolean DBG = true;
    protected static final boolean DBG = true;


    private static final int REQUEST_LOG_SIZE = 40;

    private static final int ACTION_NO_OP   = 0;
    private static final int ACTION_REQUEST = 1;
    private static final int ACTION_RELEASE = 2;

    private final PhoneSwitcher mPhoneSwitcher;
    private final PhoneSwitcher mPhoneSwitcher;
    private final SubscriptionController mSubscriptionController;
    private final SubscriptionController mSubscriptionController;
    private final SubscriptionMonitor mSubscriptionMonitor;
    private final SubscriptionMonitor mSubscriptionMonitor;
    private final DcTracker mDcTracker;
    private final DcTracker mDcTracker;
    private final LocalLog mLocalLog = new LocalLog(REQUEST_LOG_SIZE);


    private final HashMap<NetworkRequest, LocalLog> mDefaultRequests =
    // Key: network request. Value: whether it's applied to DcTracker.
            new HashMap<NetworkRequest, LocalLog>();
    private final HashMap<NetworkRequest, Boolean> mNetworkRequests = new HashMap();
    private final HashMap<NetworkRequest, LocalLog> mSpecificRequests =
            new HashMap<NetworkRequest, LocalLog>();


    private final Phone mPhone;
    private final Phone mPhone;
    // Only when this network factory is active, it will apply any network requests.
    private boolean mIsActive;
    // Whether this network factory is active and should handle default network requests.
    // Default network requests are those that don't specify subscription ID.
    private boolean mIsActiveForDefault;
    private int mSubscriptionId;
    private int mSubscriptionId;


    private final static int TELEPHONY_NETWORK_SCORE = 50;
    private final static int TELEPHONY_NETWORK_SCORE = 50;
@@ -88,7 +88,6 @@ public class TelephonyNetworkFactory extends NetworkFactory {
        // the future. For now we route everything to WWAN.
        // the future. For now we route everything to WWAN.
        mDcTracker = mPhone.getDcTracker(TransportType.WWAN);
        mDcTracker = mPhone.getDcTracker(TransportType.WWAN);


        mIsActive = false;
        mPhoneSwitcher.registerForActivePhoneSwitch(mInternalHandler, EVENT_ACTIVE_PHONE_SWITCH,
        mPhoneSwitcher.registerForActivePhoneSwitch(mInternalHandler, EVENT_ACTIVE_PHONE_SWITCH,
                null);
                null);


@@ -96,8 +95,6 @@ public class TelephonyNetworkFactory extends NetworkFactory {
        mSubscriptionMonitor.registerForSubscriptionChanged(mPhone.getPhoneId(), mInternalHandler,
        mSubscriptionMonitor.registerForSubscriptionChanged(mPhone.getPhoneId(), mInternalHandler,
                EVENT_SUBSCRIPTION_CHANGED, null);
                EVENT_SUBSCRIPTION_CHANGED, null);


        mIsActiveForDefault = false;

        register();
        register();
    }
    }


@@ -154,24 +151,17 @@ public class TelephonyNetworkFactory extends NetworkFactory {
        }
        }
    }
    }


    private static final int REQUEST_LOG_SIZE = 40;
    private void applyRequestsOnActivePhoneSwitch(NetworkRequest networkRequest,

            boolean cleanUpOnRelease, int action) {
    private static final int ACTION_NO_OP   = 0;
    private static final int ACTION_REQUEST = 1;
    private static final int ACTION_RELEASE = 2;

    private void applyRequestsOnActivePhoneSwitch(HashMap<NetworkRequest, LocalLog> requestMap,
            boolean cleanUpOnRelease, int action, String logStr) {
        if (action == ACTION_NO_OP) return;
        if (action == ACTION_NO_OP) return;


        for (NetworkRequest networkRequest : requestMap.keySet()) {
        String logStr = "onActivePhoneSwitch: " + ((action == ACTION_REQUEST)
            LocalLog localLog = requestMap.get(networkRequest);
                ? "Requesting" : "Releasing") + " network request " + networkRequest;
            localLog.log(logStr);
        mLocalLog.log(logStr);
        if (action == ACTION_REQUEST) {
        if (action == ACTION_REQUEST) {
                mDcTracker.requestNetwork(networkRequest, localLog);
            mDcTracker.requestNetwork(networkRequest, mLocalLog);
        } else if (action == ACTION_RELEASE) {
        } else if (action == ACTION_RELEASE) {
                mDcTracker.releaseNetwork(networkRequest, localLog, cleanUpOnRelease);
            mDcTracker.releaseNetwork(networkRequest, mLocalLog, cleanUpOnRelease);
            }
        }
        }
    }
    }


@@ -187,22 +177,17 @@ public class TelephonyNetworkFactory extends NetworkFactory {


    // apply or revoke requests if our active-ness changes
    // apply or revoke requests if our active-ness changes
    private void onActivePhoneSwitch() {
    private void onActivePhoneSwitch() {
        final boolean newIsActive = mPhoneSwitcher.shouldApplySpecifiedRequests(
        for (HashMap.Entry<NetworkRequest, Boolean> entry : mNetworkRequests.entrySet()) {
                mPhone.getPhoneId());
            NetworkRequest networkRequest = entry.getKey();
        final boolean newIsActiveForDefault =
            boolean applied = entry.getValue();
                mPhoneSwitcher.shouldApplyUnspecifiedRequests(mPhone.getPhoneId());


        String logString = "onActivePhoneSwitch(newIsActive " + newIsActive + ", "
            boolean shouldApply = mPhoneSwitcher.shouldApplyNetworkRequest(
                + "newIsActiveForDefault " + newIsActiveForDefault + ")";
                    networkRequest, mPhone.getPhoneId());
        if (DBG) log(logString);


        applyRequestsOnActivePhoneSwitch(mSpecificRequests, false,
            applyRequestsOnActivePhoneSwitch(networkRequest, true,
                getAction(mIsActive, newIsActive), logString);
                    getAction(applied, shouldApply));
        applyRequestsOnActivePhoneSwitch(mDefaultRequests, true,
            mNetworkRequests.put(networkRequest, shouldApply);
                getAction(mIsActiveForDefault, newIsActiveForDefault), logString);
        }

        mIsActive = newIsActive;
        mIsActiveForDefault = newIsActiveForDefault;
    }
    }


    // watch for phone->subId changes, reapply new filter and let
    // watch for phone->subId changes, reapply new filter and let
@@ -226,34 +211,17 @@ public class TelephonyNetworkFactory extends NetworkFactory {


    private void onNeedNetworkFor(Message msg) {
    private void onNeedNetworkFor(Message msg) {
        NetworkRequest networkRequest = (NetworkRequest)msg.obj;
        NetworkRequest networkRequest = (NetworkRequest)msg.obj;
        boolean isApplicable = false;
        boolean shouldApply = mPhoneSwitcher.shouldApplyNetworkRequest(
        LocalLog localLog = null;
                networkRequest, mPhone.getPhoneId());
        if (networkRequest.networkCapabilities.getNetworkSpecifier() == null) {

            // request only for the default network
        mNetworkRequests.put(networkRequest, shouldApply);
            localLog = mDefaultRequests.get(networkRequest);

            if (localLog == null) {
        String s = "onNeedNetworkFor " + networkRequest + " shouldApply " + shouldApply;
                localLog = new LocalLog(REQUEST_LOG_SIZE);
        log(s);
                localLog.log("created for " + networkRequest);
        mLocalLog.log(s);
                mDefaultRequests.put(networkRequest, localLog);

                isApplicable = mIsActiveForDefault;
        if (shouldApply) {
            }
            mDcTracker.requestNetwork(networkRequest, mLocalLog);
        } else {
            localLog = mSpecificRequests.get(networkRequest);
            if (localLog == null) {
                localLog = new LocalLog(REQUEST_LOG_SIZE);
                mSpecificRequests.put(networkRequest, localLog);
                isApplicable = mIsActive;
            }
        }
        if (isApplicable) {
            String s = "onNeedNetworkFor";
            localLog.log(s);
            log(s + " " + networkRequest);
            mDcTracker.requestNetwork(networkRequest, localLog);
        } else {
            String s = "not acting - isApplicable=" + isApplicable + ", mIsActive=" + mIsActive;
            localLog.log(s);
            log(s + " " + networkRequest);
        }
        }
    }
    }


@@ -266,25 +234,17 @@ public class TelephonyNetworkFactory extends NetworkFactory {


    private void onReleaseNetworkFor(Message msg) {
    private void onReleaseNetworkFor(Message msg) {
        NetworkRequest networkRequest = (NetworkRequest)msg.obj;
        NetworkRequest networkRequest = (NetworkRequest)msg.obj;
        LocalLog localLog = null;
        boolean applied = mNetworkRequests.get(networkRequest);
        boolean isApplicable = false;

        if (networkRequest.networkCapabilities.getNetworkSpecifier() == null) {
        mNetworkRequests.remove(networkRequest);
            // request only for the default network

            isApplicable = mDefaultRequests.containsKey(networkRequest) && mIsActiveForDefault;
        String s = "onReleaseNetworkFor " + networkRequest + " applied " + applied;
            localLog = mDefaultRequests.remove(networkRequest);
        log(s);
        } else {
        mLocalLog.log(s);
            isApplicable = mSpecificRequests.containsKey(networkRequest) && mIsActive;

            localLog = mSpecificRequests.remove(networkRequest);

        }
        if (applied) {
        if (isApplicable) {
            mDcTracker.releaseNetwork(networkRequest, mLocalLog, false);
            String s = "onReleaseNetworkFor";
            localLog.log(s);
            log(s + " " + networkRequest);
            mDcTracker.releaseNetwork(networkRequest, localLog, false);
        } else {
            String s = "not releasing - isApplicable=" + isApplicable + ", mIsActive=" + mIsActive;
            localLog.log(s);
            log(s + " " + networkRequest);
        }
        }
    }
    }


@@ -294,16 +254,14 @@ public class TelephonyNetworkFactory extends NetworkFactory {


    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
        pw.println(LOG_TAG + " mSubId=" + mSubscriptionId + " mIsActive=" +
        pw.println("Network Requests:");
                mIsActive + " mIsActiveForDefault=" + mIsActiveForDefault);
        pw.println("Default Requests:");
        pw.increaseIndent();
        pw.increaseIndent();
        for (NetworkRequest nr : mDefaultRequests.keySet()) {
        for (HashMap.Entry<NetworkRequest, Boolean> entry : mNetworkRequests.entrySet()) {
            pw.println(nr);
            NetworkRequest nr = entry.getKey();
            pw.increaseIndent();
            boolean applied = entry.getValue();
            mDefaultRequests.get(nr).dump(fd, pw, args);
            pw.println((applied ? "Applied: " : "Not applied: ") + nr);
            pw.decreaseIndent();
        }
        }
        mLocalLog.dump(fd, pw, args);
        pw.decreaseIndent();
        pw.decreaseIndent();
    }
    }
}
}
+18 −22
Original line number Original line Diff line number Diff line
@@ -103,14 +103,14 @@ public class PhoneSwitcherTest extends TelephonyTest {


        // verify nothing has been done while there are no inputs
        // verify nothing has been done while there are no inputs
        assertFalse("data allowed initially", mDataAllowed[0]);
        assertFalse("data allowed initially", mDataAllowed[0]);
        assertFalse("data allowed initially", mDataAllowed[0]);
        assertFalse("data allowed initially", mDataAllowed[1]);
        assertFalse("phone active initially", mPhoneSwitcher.shouldApplySpecifiedRequests(0));


        NetworkRequest internetNetworkRequest = addInternetNetworkRequest(null, 50);
        NetworkRequest internetNetworkRequest = addInternetNetworkRequest(null, 50);
        waitABit();
        waitABit();


        assertFalse("data allowed after request", mDataAllowed[0]);
        assertFalse("data allowed after request", mDataAllowed[0]);
        assertFalse("phone active after request", mPhoneSwitcher.shouldApplySpecifiedRequests(0));
        assertFalse("phone active after request", mPhoneSwitcher
                .shouldApplyNetworkRequest(internetNetworkRequest, 0));


        // not registered yet - shouldn't inc
        // not registered yet - shouldn't inc
        verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
        verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
@@ -413,38 +413,34 @@ public class PhoneSwitcherTest extends TelephonyTest {
        setSlotIndexToSubId(1, 2);
        setSlotIndexToSubId(1, 2);
        setDefaultDataSubId(1);
        setDefaultDataSubId(1);
        waitABit();
        waitABit();
        // Phone 0 (sub 1) should preferredDataModem it has default data sub.
        // Phone 0 (sub 1) should be preferred data phone as it has default data sub.
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(0));
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(1));
        assertTrue(mPhoneSwitcher.shouldApplyUnspecifiedRequests(0));
        assertFalse(mPhoneSwitcher.shouldApplyUnspecifiedRequests(1));


        clearInvocations(mMockRadioConfig);
        clearInvocations(mMockRadioConfig);
        clearInvocations(mActivePhoneSwitchHandler);
        clearInvocations(mActivePhoneSwitchHandler);


        // Notify phoneSwitcher about default data sub and default network request.
        // Notify phoneSwitcher about default data sub and default network request.
        // It shouldn't change anything.
        // It shouldn't change anything.
        addInternetNetworkRequest(null, 50);
        NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
        addMmsNetworkRequest(2);
        NetworkRequest mmsRequest = addMmsNetworkRequest(2);
        waitABit();
        waitABit();
        verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
        verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
        verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
        verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(0));
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(1));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 0));
        assertTrue(mPhoneSwitcher.shouldApplyUnspecifiedRequests(0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        assertFalse(mPhoneSwitcher.shouldApplyUnspecifiedRequests(1));
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 1));


        // Set sub 2 as preferred sub should make phone 1 preferredDataModem
        // Set sub 2 as preferred sub should make phone 1 preferredDataModem
        mPhoneSwitcher.setPreferredData(2);
        mPhoneSwitcher.setPreferredData(2);
        waitABit();
        waitABit();
        verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
        verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(1));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyUnspecifiedRequests(0));
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        assertTrue(mPhoneSwitcher.shouldApplyUnspecifiedRequests(1));
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 1));


        clearInvocations(mMockRadioConfig);
        clearInvocations(mMockRadioConfig);
        clearInvocations(mActivePhoneSwitchHandler);
        clearInvocations(mActivePhoneSwitchHandler);
@@ -454,10 +450,10 @@ public class PhoneSwitcherTest extends TelephonyTest {
        waitABit();
        waitABit();
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(0));
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(1));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 0));
        assertTrue(mPhoneSwitcher.shouldApplyUnspecifiedRequests(0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        assertFalse(mPhoneSwitcher.shouldApplyUnspecifiedRequests(1));
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 1));


        // SetDataAllowed should never be triggered.
        // SetDataAllowed should never be triggered.
        verify(mCommandsInterface0, never()).setDataAllowed(anyBoolean(), any());
        verify(mCommandsInterface0, never()).setDataAllowed(anyBoolean(), any());
+8 −6
Original line number Original line Diff line number Diff line
@@ -76,7 +76,7 @@ public class TelephonyNetworkFactoryTest extends TelephonyTest {
        Rlog.d(LOG_TAG + " " + mTestName, str);
        Rlog.d(LOG_TAG + " " + mTestName, str);
    }
    }


    private NetworkRequest makeSubSpecificDefaultRequest(int subId) {
    private NetworkRequest makeSubSpecificInternetRequest(int subId) {
        NetworkCapabilities netCap = (new NetworkCapabilities()).
        NetworkCapabilities netCap = (new NetworkCapabilities()).
                addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).
                addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).
                addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED).
                addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED).
@@ -183,8 +183,8 @@ public class TelephonyNetworkFactoryTest extends TelephonyTest {
        waitForMs(250);
        waitForMs(250);
        assertEquals(1, mNetworkRequestList.size());
        assertEquals(1, mNetworkRequestList.size());


        log("makeSubSpecificDefaultRequest: subId = " + subId);
        log("makeSubSpecificInternetRequest: subId = " + subId);
        NetworkRequest subSpecificDefault = makeSubSpecificDefaultRequest(subId);
        NetworkRequest subSpecificDefault = makeSubSpecificInternetRequest(subId);
        waitForMs(250);
        waitForMs(250);
        assertEquals(2, mNetworkRequestList.size());
        assertEquals(2, mNetworkRequestList.size());


@@ -193,7 +193,7 @@ public class TelephonyNetworkFactoryTest extends TelephonyTest {
        waitForMs(250);
        waitForMs(250);
        assertEquals(0, mNetworkRequestList.size());
        assertEquals(0, mNetworkRequestList.size());


        log("makeSubSpecificDefaultRequest: subId = " + subId);
        log("makeSubSpecificInternetRequest: subId = " + subId);
        NetworkRequest subSpecificMms = makeSubSpecificMmsRequest(subId);
        NetworkRequest subSpecificMms = makeSubSpecificMmsRequest(subId);
        waitForMs(250);
        waitForMs(250);
        assertEquals(0, mNetworkRequestList.size());
        assertEquals(0, mNetworkRequestList.size());
@@ -276,14 +276,16 @@ public class TelephonyNetworkFactoryTest extends TelephonyTest {
        waitForMs(250);
        waitForMs(250);
        assertEquals(0, mNetworkRequestList.size());
        assertEquals(0, mNetworkRequestList.size());


        makeSubSpecificDefaultRequest(subId);
        makeSubSpecificInternetRequest(subId);
        waitForMs(250);
        waitForMs(250);
        assertEquals(0, mNetworkRequestList.size());
        assertEquals(0, mNetworkRequestList.size());


        mSubscriptionControllerMock.setSlotSubId(phoneId, subId);
        mSubscriptionControllerMock.setSlotSubId(phoneId, subId);
        mSubscriptionMonitorMock.notifySubscriptionChanged(phoneId);
        mSubscriptionMonitorMock.notifySubscriptionChanged(phoneId);
        waitForMs(250);
        waitForMs(250);
        assertEquals(2, mNetworkRequestList.size());
        // Although specified a subId, Internet request is only handled by
        // preferred data phone.
        assertEquals(1, mNetworkRequestList.size());


        mSubscriptionControllerMock.setDefaultDataSubId(subId);
        mSubscriptionControllerMock.setDefaultDataSubId(subId);
        mPhoneSwitcherMock.setPreferredDataPhoneId(phoneId);
        mPhoneSwitcherMock.setPreferredDataPhoneId(phoneId);
+2 −15
Original line number Original line Diff line number Diff line
@@ -27,14 +27,12 @@ import com.android.internal.telephony.PhoneSwitcher;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicBoolean;


public class PhoneSwitcherMock extends PhoneSwitcher {
public class PhoneSwitcherMock extends PhoneSwitcher {
    private final int mNumPhones;
    private final RegistrantList mActivePhoneRegistrants;
    private final RegistrantList mActivePhoneRegistrants;
    private final AtomicBoolean mIsActive[];
    private final AtomicBoolean mIsActive[];


    public PhoneSwitcherMock(int numPhones, Looper looper) {
    public PhoneSwitcherMock(int numPhones, Looper looper) {
        super(looper);
        super(numPhones, looper);


        mNumPhones = numPhones;
        mActivePhoneRegistrants = new RegistrantList();
        mActivePhoneRegistrants = new RegistrantList();
        mIsActive = new AtomicBoolean[numPhones];
        mIsActive = new AtomicBoolean[numPhones];
        for(int i = 0; i < numPhones; i++) {
        for(int i = 0; i < numPhones; i++) {
@@ -48,15 +46,10 @@ public class PhoneSwitcherMock extends PhoneSwitcher {
    }
    }


    @Override
    @Override
    public boolean shouldApplySpecifiedRequests(int phoneId) {
    protected boolean isPhoneActive(int phoneId) {
        return mIsActive[phoneId].get();
        return mIsActive[phoneId].get();
    }
    }


    @Override
    public boolean shouldApplyUnspecifiedRequests(int phoneId) {
        return mIsActive[phoneId].get() && phoneId == mPreferredDataPhoneId;
    }

    @Override
    @Override
    public void registerForActivePhoneSwitch(Handler h, int what, Object o) {
    public void registerForActivePhoneSwitch(Handler h, int what, Object o) {
        Registrant r = new Registrant(h, what, o);
        Registrant r = new Registrant(h, what, o);
@@ -69,12 +62,6 @@ public class PhoneSwitcherMock extends PhoneSwitcher {
        mActivePhoneRegistrants.remove(h);
        mActivePhoneRegistrants.remove(h);
    }
    }


    private void validatePhoneId(int phoneId) {
        if (phoneId < 0 || phoneId >= mNumPhones) {
            throw new IllegalArgumentException("Invalid PhoneId");
        }
    }

    @VisibleForTesting
    @VisibleForTesting
    public void setPhoneActive(int phoneId, boolean active) {
    public void setPhoneActive(int phoneId, boolean active) {
        validatePhoneId(phoneId);
        validatePhoneId(phoneId);