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

Commit 1b6ad140 authored by junyulai's avatar junyulai
Browse files

Attribute data usage to virtual RAT type for 5G non-standalone mode

Test: atest NetworkStatsSubscriptionsMonitorTest#test5g
Bug: 160727498
Change-Id: I8753e68140c0993773017c9a49bd8a666a364071
parent 9ef5558e
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -87,6 +87,15 @@ public class NetworkTemplate implements Parcelable {
     * @hide
     * @hide
     */
     */
    public static final int NETWORK_TYPE_ALL = -1;
    public static final int NETWORK_TYPE_ALL = -1;
    /**
     * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is
     * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along
     * with NR state as connected. This should not be overlapped with any of the
     * {@code TelephonyManager.NETWORK_TYPE_*} constants.
     *
     * @hide
     */
    public static final int NETWORK_TYPE_5G_NSA = -2;


    private static boolean isKnownMatchRule(final int rule) {
    private static boolean isKnownMatchRule(final int rule) {
        switch (rule) {
        switch (rule) {
@@ -475,6 +484,9 @@ public class NetworkTemplate implements Parcelable {
                return TelephonyManager.NETWORK_TYPE_LTE;
                return TelephonyManager.NETWORK_TYPE_LTE;
            case TelephonyManager.NETWORK_TYPE_NR:
            case TelephonyManager.NETWORK_TYPE_NR:
                return TelephonyManager.NETWORK_TYPE_NR;
                return TelephonyManager.NETWORK_TYPE_NR;
            // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
            case NetworkTemplate.NETWORK_TYPE_5G_NSA:
                return NetworkTemplate.NETWORK_TYPE_5G_NSA;
            default:
            default:
                return TelephonyManager.NETWORK_TYPE_UNKNOWN;
                return TelephonyManager.NETWORK_TYPE_UNKNOWN;
        }
        }
+14 −1
Original line number Original line Diff line number Diff line
@@ -16,12 +16,14 @@


package com.android.server.net;
package com.android.server.net;


import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA;
import static android.net.NetworkTemplate.getCollapsedRatType;
import static android.net.NetworkTemplate.getCollapsedRatType;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.content.Context;
import android.content.Context;
import android.os.Looper;
import android.os.Looper;
import android.telephony.Annotation;
import android.telephony.Annotation;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneStateListener;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager;
@@ -196,7 +198,18 @@ public class NetworkStatsSubscriptionsMonitor extends


        @Override
        @Override
        public void onServiceStateChanged(@NonNull ServiceState ss) {
        public void onServiceStateChanged(@NonNull ServiceState ss) {
            final int networkType = ss.getDataNetworkType();
            // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony
            // would report RAT = 5G_NR.
            // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and
            // network allocates a secondary 5G cell so telephony reports RAT = LTE along with
            // NR state as connected. In such case, attributes the data usage to NR.
            // See b/160727498.
            final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE
                    || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA)
                    && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED;

            final int networkType =
                    (is5GNsa ? NETWORK_TYPE_5G_NSA : ss.getDataNetworkType());
            final int collapsedRatType = getCollapsedRatType(networkType);
            final int collapsedRatType = getCollapsedRatType(networkType);
            if (collapsedRatType == mLastCollapsedRatType) return;
            if (collapsedRatType == mLastCollapsedRatType) return;


+5 −2
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@ import android.net.NetworkStats.METERED_ALL
import android.net.NetworkStats.ROAMING_ALL
import android.net.NetworkStats.ROAMING_ALL
import android.net.NetworkTemplate.MATCH_MOBILE
import android.net.NetworkTemplate.MATCH_MOBILE
import android.net.NetworkTemplate.MATCH_WIFI
import android.net.NetworkTemplate.MATCH_WIFI
import android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA
import android.net.NetworkTemplate.NETWORK_TYPE_ALL
import android.net.NetworkTemplate.NETWORK_TYPE_ALL
import android.net.NetworkTemplate.buildTemplateMobileWithRatType
import android.net.NetworkTemplate.buildTemplateMobileWithRatType
import android.telephony.TelephonyManager
import android.telephony.TelephonyManager
@@ -145,11 +146,13 @@ class NetworkTemplateTest {
        assertParcelSane(templateWifi, 8)
        assertParcelSane(templateWifi, 8)
    }
    }


    // Verify NETWORK_TYPE_ALL does not conflict with TelephonyManager#NETWORK_TYPE_* constants.
    // Verify NETWORK_TYPE_* constants in NetworkTemplate do not conflict with
    // TelephonyManager#NETWORK_TYPE_* constants.
    @Test
    @Test
    fun testNetworkTypeAll() {
    fun testNetworkTypeConstants() {
        for (ratType in TelephonyManager.getAllNetworkTypes()) {
        for (ratType in TelephonyManager.getAllNetworkTypes()) {
            assertNotEquals(NETWORK_TYPE_ALL, ratType)
            assertNotEquals(NETWORK_TYPE_ALL, ratType)
            assertNotEquals(NETWORK_TYPE_5G_NSA, ratType)
        }
        }
    }
    }
}
}
+54 −1
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.net;
package com.android.server.net;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyInt;
@@ -30,7 +31,9 @@ import static org.mockito.Mockito.when;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.content.Context;
import android.content.Context;
import android.net.NetworkTemplate;
import android.os.test.TestLooper;
import android.os.test.TestLooper;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneStateListener;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager;
@@ -61,7 +64,6 @@ public final class NetworkStatsSubscriptionsMonitorTest {
    private static final String TEST_IMSI3 = "466929999999999";
    private static final String TEST_IMSI3 = "466929999999999";


    @Mock private Context mContext;
    @Mock private Context mContext;
    @Mock private PhoneStateListener mPhoneStateListener;
    @Mock private SubscriptionManager mSubscriptionManager;
    @Mock private SubscriptionManager mSubscriptionManager;
    @Mock private TelephonyManager mTelephonyManager;
    @Mock private TelephonyManager mTelephonyManager;
    @Mock private NetworkStatsSubscriptionsMonitor.Delegate mDelegate;
    @Mock private NetworkStatsSubscriptionsMonitor.Delegate mDelegate;
@@ -215,4 +217,55 @@ public final class NetworkStatsSubscriptionsMonitorTest {
        verify(mTelephonyManager, times(2)).listen(any(), eq(PhoneStateListener.LISTEN_NONE));
        verify(mTelephonyManager, times(2)).listen(any(), eq(PhoneStateListener.LISTEN_NONE));
        assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
        assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
    }
    }


    @Test
    public void test5g() {
        mMonitor.start();
        // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback
        // before changing RAT type. Also capture listener for later use.
        addTestSub(TEST_SUBID1, TEST_IMSI1);
        assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
        final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
                ArgumentCaptor.forClass(RatTypeListener.class);
        verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(),
                eq(PhoneStateListener.LISTEN_SERVICE_STATE));
        final RatTypeListener listener = CollectionUtils
                .find(ratTypeListenerCaptor.getAllValues(), it -> it.getSubId() == TEST_SUBID1);
        assertNotNull(listener);

        // Set RAT type to 5G NSA (non-standalone) mode, verify the monitor outputs
        // NETWORK_TYPE_5G_NSA.
        final ServiceState serviceState = mock(ServiceState.class);
        when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_LTE);
        when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED);
        listener.onServiceStateChanged(serviceState);
        assertRatTypeChangedForSub(TEST_IMSI1, NetworkTemplate.NETWORK_TYPE_5G_NSA);
        reset(mDelegate);

        // Set RAT type to LTE without NR connected, the RAT type should be downgraded to LTE.
        when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_NONE);
        listener.onServiceStateChanged(serviceState);
        assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_LTE);
        reset(mDelegate);

        // Verify NR connected with other RAT type does not take effect.
        when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_UMTS);
        when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED);
        listener.onServiceStateChanged(serviceState);
        assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
        reset(mDelegate);

        // Set RAT type to 5G standalone mode, the RAT type should be NR.
        setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
                TelephonyManager.NETWORK_TYPE_NR);
        assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR);
        reset(mDelegate);

        // Set NR state to none in standalone mode does not change anything.
        when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_NR);
        when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_NONE);
        listener.onServiceStateChanged(serviceState);
        assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR);
    }
}
}