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

Commit 24c7814f authored by Remi NGUYEN VAN's avatar Remi NGUYEN VAN Committed by android-build-merger
Browse files

Merge "Clamp multipath quota to 0 if roaming." into pi-dev

am: ed0da518

Change-Id: Ic09fd092db018023e737a33e6d0e4c6563fd8f91
parents 326d04fc ed0da518
Loading
Loading
Loading
Loading
+27 −4
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
@@ -504,6 +505,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
    @GuardedBy("mNetworkPoliciesSecondLock")
    private final SparseBooleanArray mNetworkMetered = new SparseBooleanArray();

    /** Map from network ID to last observed roaming state */
    @GuardedBy("mNetworkPoliciesSecondLock")
    private final SparseBooleanArray mNetworkRoaming = new SparseBooleanArray();

    /** Map from netId to subId as of last update */
    @GuardedBy("mNetworkPoliciesSecondLock")
    private final SparseIntArray mNetIdToSubId = new SparseIntArray();
@@ -1019,6 +1024,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        }
    };

    private static boolean updateCapabilityChange(SparseBooleanArray lastValues, boolean newValue,
            Network network) {
        final boolean lastValue = lastValues.get(network.netId, false);
        final boolean changed = (lastValue != newValue) || lastValues.indexOfKey(network.netId) < 0;
        if (changed) {
            lastValues.put(network.netId, newValue);
        }
        return changed;
    }

    private final NetworkCallback mNetworkCallback = new NetworkCallback() {
        @Override
        public void onCapabilitiesChanged(Network network,
@@ -1026,13 +1041,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
            if (network == null || networkCapabilities == null) return;

            synchronized (mNetworkPoliciesSecondLock) {
                final boolean oldMetered = mNetworkMetered.get(network.netId, false);
                final boolean newMetered = !networkCapabilities
                        .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
                final boolean meteredChanged = updateCapabilityChange(
                        mNetworkMetered, newMetered, network);

                final boolean newRoaming = !networkCapabilities
                        .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
                final boolean roamingChanged = updateCapabilityChange(
                        mNetworkRoaming, newRoaming, network);

                if ((oldMetered != newMetered) || mNetworkMetered.indexOfKey(network.netId) < 0) {
                if (meteredChanged || roamingChanged) {
                    mLogger.meterednessChanged(network.netId, newMetered);
                    mNetworkMetered.put(network.netId, newMetered);
                    updateNetworkRulesNL();
                }
            }
@@ -1771,7 +1791,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {

            final long quotaBytes;
            final long limitBytes = plan.getDataLimitBytes();
            if (limitBytes == SubscriptionPlan.BYTES_UNKNOWN) {
            if (!state.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING)) {
                // Clamp to 0 when roaming
                quotaBytes = 0;
            } else if (limitBytes == SubscriptionPlan.BYTES_UNKNOWN) {
                quotaBytes = OPPORTUNISTIC_QUOTA_UNKNOWN;
            } else if (limitBytes == SubscriptionPlan.BYTES_UNLIMITED) {
                // Unlimited data; let's use 20MiB/day (600MiB/month)
+99 −40
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server;

import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
@@ -30,6 +31,7 @@ import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
@@ -43,6 +45,7 @@ import static android.text.format.Time.TIMEZONE_UTC;

import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_JOBS;
import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH;
import static com.android.server.net.NetworkPolicyManagerService.OPPORTUNISTIC_QUOTA_UNKNOWN;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_RAPID;
@@ -65,6 +68,7 @@ import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -201,7 +205,8 @@ public class NetworkPolicyManagerServiceTest {
    private static final int TEST_SUB_ID = 42;
    private static final int TEST_NET_ID = 24;

    private static NetworkTemplate sTemplateWifi = NetworkTemplate.buildTemplateWifi(TEST_SSID);
    private static NetworkTemplate sTemplateWifi = buildTemplateWifi(TEST_SSID);
    private static NetworkTemplate sTemplateMobileAll = buildTemplateMobileAll(TEST_IMSI);

    /**
     * Path on assets where files used by {@link NetPolicyXml} are located.
@@ -221,6 +226,7 @@ public class NetworkPolicyManagerServiceTest {
    private @Mock IActivityManager mActivityManager;
    private @Mock INetworkManagementService mNetworkManager;
    private @Mock IConnectivityManager mConnManager;
    private @Mock ConnectivityManager mConnectivityManager;
    private @Mock NotificationManager mNotifManager;
    private @Mock PackageManager mPackageManager;
    private @Mock IPackageManager mIpm;
@@ -228,6 +234,9 @@ public class NetworkPolicyManagerServiceTest {
    private @Mock CarrierConfigManager mCarrierConfigManager;
    private @Mock TelephonyManager mTelephonyManager;

    private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor =
            ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);

    private ActivityManagerInternal mActivityManagerInternal;
    private NetworkStatsManagerInternal mStatsService;

@@ -331,6 +340,8 @@ public class NetworkPolicyManagerServiceTest {
                        return mTelephonyManager;
                    case Context.NOTIFICATION_SERVICE:
                        return mNotifManager;
                    case Context.CONNECTIVITY_SERVICE:
                        return mConnectivityManager;
                    default:
                        return super.getSystemService(name);
                }
@@ -394,6 +405,8 @@ public class NetworkPolicyManagerServiceTest {
                .thenReturn(buildApplicationInfo(PKG_NAME_C));
        when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true);
        when(mNetworkManager.setDataSaverModeEnabled(anyBoolean())).thenReturn(true);
        doNothing().when(mConnectivityManager)
                .registerNetworkCallback(any(), mNetworkCallbackCaptor.capture());

        // Prepare NPMS.
        mService.systemReady(mService.networkScoreAndNetworkManagementServiceReady());
@@ -1015,10 +1028,8 @@ public class NetworkPolicyManagerServiceTest {
        mService.updateNetworks();

        // Define simple data plan
        final SubscriptionPlan plan = SubscriptionPlan.Builder
                .createRecurringMonthly(ZonedDateTime.parse("2015-11-01T00:00:00.00Z"))
                .setDataLimit(DataUnit.MEGABYTES.toBytes(1800), LIMIT_BEHAVIOR_DISABLED)
                .build();
        final SubscriptionPlan plan = buildMonthlyDataPlan(
                ZonedDateTime.parse("2015-11-01T00:00:00.00Z"), DataUnit.MEGABYTES.toBytes(1800));
        mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[] { plan },
                mServiceContext.getOpPackageName());

@@ -1122,10 +1133,8 @@ public class NetworkPolicyManagerServiceTest {
        mService.updateNetworks();

        // Define simple data plan which gives us effectively 60MB/day
        final SubscriptionPlan plan = SubscriptionPlan.Builder
                .createRecurringMonthly(ZonedDateTime.parse("2015-11-01T00:00:00.00Z"))
                .setDataLimit(DataUnit.MEGABYTES.toBytes(1800), LIMIT_BEHAVIOR_DISABLED)
                .build();
        final SubscriptionPlan plan = buildMonthlyDataPlan(
                ZonedDateTime.parse("2015-11-01T00:00:00.00Z"), DataUnit.MEGABYTES.toBytes(1800));
        mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[] { plan },
                mServiceContext.getOpPackageName());

@@ -1497,21 +1506,13 @@ public class NetworkPolicyManagerServiceTest {
        final NetworkStatsHistory history = new NetworkStatsHistory(TimeUnit.HOURS.toMillis(1));
        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
        when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
                .thenAnswer(new Answer<Long>() {
                    @Override
                    public Long answer(InvocationOnMock invocation) throws Throwable {
                .thenAnswer(invocation -> {
                    final NetworkStatsHistory.Entry entry = history.getValues(
                            invocation.getArgument(1), invocation.getArgument(2), null);
                    return entry.rxBytes + entry.txBytes;
                    }
                });
        when(mStatsService.getNetworkUidBytes(any(), anyLong(), anyLong()))
                .thenAnswer(new Answer<NetworkStats>() {
                    @Override
                    public NetworkStats answer(InvocationOnMock invocation) throws Throwable {
                        return stats;
                    }
                });
                .thenReturn(stats);

        // Get active mobile network in place
        expectMobileDefaults();
@@ -1535,16 +1536,17 @@ public class NetworkPolicyManagerServiceTest {
            mService.updateNetworks();

            // No quotas
            assertEquals(-1, internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_JOBS));
            assertEquals(-1, internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_MULTIPATH));
            assertEquals(OPPORTUNISTIC_QUOTA_UNKNOWN,
                    internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_JOBS));
            assertEquals(OPPORTUNISTIC_QUOTA_UNKNOWN,
                    internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_MULTIPATH));
        }

        // Limited data plan
        {
            final SubscriptionPlan plan = SubscriptionPlan.Builder
                    .createRecurringMonthly(ZonedDateTime.parse("2015-11-01T00:00:00.00Z"))
                    .setDataLimit(DataUnit.MEGABYTES.toBytes(1800), LIMIT_BEHAVIOR_DISABLED)
                    .build();
            final SubscriptionPlan plan = buildMonthlyDataPlan(
                    ZonedDateTime.parse("2015-11-01T00:00:00.00Z"),
                    DataUnit.MEGABYTES.toBytes(1800));
            mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
                    mServiceContext.getOpPackageName());

@@ -1561,12 +1563,44 @@ public class NetworkPolicyManagerServiceTest {
                    internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_MULTIPATH));
        }

        // Limited data plan, over quota
        {
            final SubscriptionPlan plan = buildMonthlyDataPlan(
                    ZonedDateTime.parse("2015-11-01T00:00:00.00Z"),
                    DataUnit.MEGABYTES.toBytes(100));
            mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
                    mServiceContext.getOpPackageName());

            reset(mTelephonyManager, mNetworkManager, mNotifManager);
            expectMobileDefaults();

            mService.updateNetworks();

            assertEquals(0L, internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_JOBS));
            assertEquals(0L, internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_MULTIPATH));
        }

        // Roaming
        {
            final SubscriptionPlan plan = buildMonthlyDataPlan(
                    ZonedDateTime.parse("2015-11-01T00:00:00.00Z"), BYTES_UNLIMITED);
            mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
                    mServiceContext.getOpPackageName());

            reset(mTelephonyManager, mNetworkManager, mNotifManager);
            expectMobileDefaults();
            expectNetworkState(true /* roaming */);

            mService.updateNetworks();

            assertEquals(0L, internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_JOBS));
            assertEquals(0L, internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_MULTIPATH));
        }

        // Unlimited data plan
        {
            final SubscriptionPlan plan = SubscriptionPlan.Builder
                    .createRecurringMonthly(ZonedDateTime.parse("2015-11-01T00:00:00.00Z"))
                    .setDataLimit(BYTES_UNLIMITED, LIMIT_BEHAVIOR_DISABLED)
                    .build();
            final SubscriptionPlan plan = buildMonthlyDataPlan(
                    ZonedDateTime.parse("2015-11-01T00:00:00.00Z"), BYTES_UNLIMITED);
            mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
                    mServiceContext.getOpPackageName());

@@ -1580,9 +1614,27 @@ public class NetworkPolicyManagerServiceTest {
                    internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_JOBS));
            assertEquals(DataUnit.MEBIBYTES.toBytes(10),
                    internal.getSubscriptionOpportunisticQuota(net, QUOTA_TYPE_MULTIPATH));

            // Capabilities change to roaming
            final ConnectivityManager.NetworkCallback callback = mNetworkCallbackCaptor.getValue();
            assertNotNull(callback);
            expectNetworkState(true /* roaming */);
            callback.onCapabilitiesChanged(
                    new Network(TEST_NET_ID),
                    buildNetworkCapabilities(TEST_SUB_ID, true /* roaming */));

            assertEquals(0, internal.getSubscriptionOpportunisticQuota(
                    new Network(TEST_NET_ID), NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH));
        }
    }

    private SubscriptionPlan buildMonthlyDataPlan(ZonedDateTime start, long limitBytes) {
        return SubscriptionPlan.Builder
                .createRecurringMonthly(start)
                .setDataLimit(limitBytes, LIMIT_BEHAVIOR_DISABLED)
                .build();
    }

    private ApplicationInfo buildApplicationInfo(String label) {
        final ApplicationInfo ai = new ApplicationInfo();
        ai.nonLocalizedLabel = label;
@@ -1602,9 +1654,12 @@ public class NetworkPolicyManagerServiceTest {
        return lp;
    }

    private NetworkCapabilities buildNetworkCapabilities(int subId) {
    private NetworkCapabilities buildNetworkCapabilities(int subId, boolean roaming) {
        final NetworkCapabilities nc = new NetworkCapabilities();
        nc.addTransportType(TRANSPORT_CELLULAR);
        if (!roaming) {
            nc.addCapability(NET_CAPABILITY_NOT_ROAMING);
        }
        nc.setNetworkSpecifier(new StringNetworkSpecifier(String.valueOf(subId)));
        return nc;
    }
@@ -1658,18 +1713,22 @@ public class NetworkPolicyManagerServiceTest {
                hasIt ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
    }

    private void expectMobileDefaults() throws Exception {
        when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(
                new int[] { TEST_SUB_ID });
        when(mTelephonyManager.getSubscriberId(TEST_SUB_ID)).thenReturn(TEST_IMSI);
    private void expectNetworkState(boolean roaming) throws Exception {
        when(mConnManager.getAllNetworkState()).thenReturn(new NetworkState[] {
                new NetworkState(buildNetworkInfo(),
                        buildLinkProperties(TEST_IFACE),
                        buildNetworkCapabilities(TEST_SUB_ID),
                        buildNetworkCapabilities(TEST_SUB_ID, roaming),
                        new Network(TEST_NET_ID), TEST_IMSI, null)
        });
    }

    private void expectMobileDefaults() throws Exception {
        when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(
                new int[] { TEST_SUB_ID });
        when(mTelephonyManager.getSubscriberId(TEST_SUB_ID)).thenReturn(TEST_IMSI);
        expectNetworkState(false /* roaming */);
    }

    private void verifyAdvisePersistThreshold() throws Exception {
        verify(mStatsService).advisePersistThreshold(anyLong());
    }