From 1f4578fa86c02b33841b958632e7b791e382c0a0 Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Mon, 10 Apr 2017 14:32:23 -0700 Subject: [PATCH] Mark Restricted APN connections as restricted. If anything unrestricted is bundled in the whole thing has to be unrestricted (we can't restrict based on destination or intent) but the NOT_METERED flag wasn't taken into account. This wasn't a problem before because telephony set that statically and late, but a change caused it to be marked NOT_METERED earlier which exposed this bug. bug: 37208956 Merged-In: I7b7a1c38621ce0ecde8cf041e82b1ebb7a9c6f15 Test: new NetworkCapabilitiesTest. Fails without fix, works with. Change-Id: I86c1b2854413a94662aa53e697d32380695ab9ac --- .../java/android/net/NetworkCapabilities.java | 33 +++-- .../android/net/NetworkCapabilitiesTest.java | 117 ++++++++++++++++++ 2 files changed, 142 insertions(+), 8 deletions(-) create mode 100644 tests/net/java/android/net/NetworkCapabilitiesTest.java diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index c28294f9fe..5edc7c6427 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -18,7 +18,8 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; -import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; import java.util.Objects; @@ -229,7 +230,8 @@ public final class NetworkCapabilities implements Parcelable { * Capabilities that suggest that a network is restricted. * {@see #maybeMarkCapabilitiesRestricted}. */ - private static final long RESTRICTED_CAPABILITIES = + @VisibleForTesting + /* package */ static final long RESTRICTED_CAPABILITIES = (1 << NET_CAPABILITY_CBS) | (1 << NET_CAPABILITY_DUN) | (1 << NET_CAPABILITY_EIMS) | @@ -239,6 +241,17 @@ public final class NetworkCapabilities implements Parcelable { (1 << NET_CAPABILITY_RCS) | (1 << NET_CAPABILITY_XCAP); + /** + * Capabilities that suggest that a network is unrestricted. + * {@see #maybeMarkCapabilitiesRestricted}. + */ + @VisibleForTesting + /* package */ static final long UNRESTRICTED_CAPABILITIES = + (1 << NET_CAPABILITY_INTERNET) | + (1 << NET_CAPABILITY_MMS) | + (1 << NET_CAPABILITY_SUPL) | + (1 << NET_CAPABILITY_WIFI_P2P); + /** * Adds the given capability to this {@code NetworkCapability} instance. * Multiple capabilities may be applied sequentially. Note that when searching @@ -365,12 +378,16 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public void maybeMarkCapabilitiesRestricted() { - // If all the capabilities are typically provided by restricted networks, conclude that this - // network is restricted. - if ((mNetworkCapabilities & ~(DEFAULT_CAPABILITIES | RESTRICTED_CAPABILITIES)) == 0 && - // Must have at least some restricted capabilities, otherwise a request for an - // internet-less network will get marked restricted. - (mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0) { + // Verify there aren't any unrestricted capabilities. If there are we say + // the whole thing is unrestricted. + final boolean hasUnrestrictedCapabilities = + ((mNetworkCapabilities & UNRESTRICTED_CAPABILITIES) != 0); + + // Must have at least some restricted capabilities. + final boolean hasRestrictedCapabilities = + ((mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0); + + if (hasRestrictedCapabilities && !hasUnrestrictedCapabilities) { removeCapability(NET_CAPABILITY_NOT_RESTRICTED); } } diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java new file mode 100644 index 0000000000..e3b06c8752 --- /dev/null +++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS; +import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS; +import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; +import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES; +import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + + +import android.net.NetworkCapabilities; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class NetworkCapabilitiesTest { + @Test + public void testMaybeMarkCapabilitiesRestricted() { + // verify EIMS is restricted + assertEquals((1 << NET_CAPABILITY_EIMS) & RESTRICTED_CAPABILITIES, + (1 << NET_CAPABILITY_EIMS)); + + // verify CBS is also restricted + assertEquals((1 << NET_CAPABILITY_CBS) & RESTRICTED_CAPABILITIES, + (1 << NET_CAPABILITY_CBS)); + + // verify default is not restricted + assertEquals((1 << NET_CAPABILITY_INTERNET) & RESTRICTED_CAPABILITIES, 0); + + // just to see + assertEquals(RESTRICTED_CAPABILITIES & UNRESTRICTED_CAPABILITIES, 0); + + // check that internet does not get restricted + NetworkCapabilities netCap = new NetworkCapabilities(); + netCap.addCapability(NET_CAPABILITY_INTERNET); + netCap.maybeMarkCapabilitiesRestricted(); + assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + + // metered-ness shouldn't matter + netCap = new NetworkCapabilities(); + netCap.addCapability(NET_CAPABILITY_INTERNET); + netCap.addCapability(NET_CAPABILITY_NOT_METERED); + netCap.maybeMarkCapabilitiesRestricted(); + assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + netCap = new NetworkCapabilities(); + netCap.addCapability(NET_CAPABILITY_INTERNET); + netCap.removeCapability(NET_CAPABILITY_NOT_METERED); + netCap.maybeMarkCapabilitiesRestricted(); + assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + + // add EIMS - bundled with unrestricted means it's unrestricted + netCap = new NetworkCapabilities(); + netCap.addCapability(NET_CAPABILITY_INTERNET); + netCap.addCapability(NET_CAPABILITY_EIMS); + netCap.addCapability(NET_CAPABILITY_NOT_METERED); + netCap.maybeMarkCapabilitiesRestricted(); + assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + netCap = new NetworkCapabilities(); + netCap.addCapability(NET_CAPABILITY_INTERNET); + netCap.addCapability(NET_CAPABILITY_EIMS); + netCap.removeCapability(NET_CAPABILITY_NOT_METERED); + netCap.maybeMarkCapabilitiesRestricted(); + assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + + // just a restricted cap should be restricted regardless of meteredness + netCap = new NetworkCapabilities(); + netCap.addCapability(NET_CAPABILITY_EIMS); + netCap.addCapability(NET_CAPABILITY_NOT_METERED); + netCap.maybeMarkCapabilitiesRestricted(); + assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + netCap = new NetworkCapabilities(); + netCap.addCapability(NET_CAPABILITY_EIMS); + netCap.removeCapability(NET_CAPABILITY_NOT_METERED); + netCap.maybeMarkCapabilitiesRestricted(); + assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + + // try 2 restricted caps + netCap = new NetworkCapabilities(); + netCap.addCapability(NET_CAPABILITY_CBS); + netCap.addCapability(NET_CAPABILITY_EIMS); + netCap.addCapability(NET_CAPABILITY_NOT_METERED); + netCap.maybeMarkCapabilitiesRestricted(); + assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + netCap = new NetworkCapabilities(); + netCap.addCapability(NET_CAPABILITY_CBS); + netCap.addCapability(NET_CAPABILITY_EIMS); + netCap.removeCapability(NET_CAPABILITY_NOT_METERED); + netCap.maybeMarkCapabilitiesRestricted(); + assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); + } + +}