Merge "Exclude NET_CAP_LOCAL_NETWORK when listening for upstream network events" into main

This commit is contained in:
Junyu Lai 2024-12-17 23:25:01 -08:00 • committed by Gerrit Code Review
commit cd53bb07fd
5 changed files with 64 additions and 46 deletions

View file

@ -2089,7 +2089,7 @@ public class Tethering {
}
mRoutingCoordinator.maybeRemoveDeprecatedUpstreams();
mUpstreamNetworkMonitor.startObserveAllNetworks();
mUpstreamNetworkMonitor.startObserveUpstreamNetworks();
// TODO: De-duplicate with updateUpstreamWanted() below.
if (upstreamWanted()) {

View file

@ -24,6 +24,7 @@ import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@ -44,6 +45,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.SharedLog;
import com.android.networkstack.apishim.ConnectivityManagerShimImpl;
import com.android.networkstack.apishim.common.ConnectivityManagerShim;
@ -62,9 +64,10 @@ import java.util.Set;
* The owner of UNM gets it to register network callbacks by calling the
* following methods :
* Calling #startTrackDefaultNetwork() to track the system default network.
* Calling #startObserveAllNetworks() to observe all networks. Listening all
* networks is necessary while the expression of preferred upstreams remains
* a list of legacy connectivity types. In future, this can be revisited.
* Calling #startObserveUpstreamNetworks() to observe upstream networks.
* Listening all upstream networks is necessary while the expression of
* preferred upstreams remains a list of legacy connectivity types.
* In future, this can be revisited.
* Calling #setTryCell() to request bringing up mobile DUN or HIPRI.
*
* The methods and data members of this class are only to be accessed and
@ -94,7 +97,7 @@ public class UpstreamNetworkMonitor {
@VisibleForTesting
public static final int TYPE_NONE = -1;
private static final int CALLBACK_LISTEN_ALL = 1;
private static final int CALLBACK_LISTEN_UPSTREAM = 1;
private static final int CALLBACK_DEFAULT_INTERNET = 2;
private static final int CALLBACK_MOBILE_REQUEST = 3;
@ -116,7 +119,7 @@ public class UpstreamNetworkMonitor {
private HashSet<IpPrefix> mLocalPrefixes;
private ConnectivityManager mCM;
private EntitlementManager mEntitlementMgr;
private NetworkCallback mListenAllCallback;
private NetworkCallback mListenUpstreamCallback;
private NetworkCallback mDefaultNetworkCallback;
private NetworkCallback mMobileNetworkCallback;
@ -157,20 +160,29 @@ public class UpstreamNetworkMonitor {
}
ConnectivityManagerShim mCmShim = ConnectivityManagerShimImpl.newInstance(mContext);
mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET);
// TODO (b/382413665): By definition, a local network cannot be the system default,
// because it does not provide internet capability. Figure out whether this
// is enforced in ConnectivityService. Or what will happen for tethering if it happens.
mCmShim.registerSystemDefaultNetworkCallback(mDefaultNetworkCallback, mHandler);
if (mEntitlementMgr == null) {
mEntitlementMgr = entitle;
}
}
/** Listen all networks. */
public void startObserveAllNetworks() {
/** Listen upstream networks. */
public void startObserveUpstreamNetworks() {
stop();
final NetworkRequest listenAllRequest = new NetworkRequest.Builder()
.clearCapabilities().build();
mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL);
cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler);
final NetworkRequest listenUpstreamRequest;
// Before V, only TV supports local agent on U, which doesn't support tethering.
if (SdkLevel.isAtLeastV()) {
listenUpstreamRequest = new NetworkRequest.Builder().clearCapabilities()
.addForbiddenCapability(NET_CAPABILITY_LOCAL_NETWORK).build();
} else {
listenUpstreamRequest = new NetworkRequest.Builder().clearCapabilities().build();
}
mListenUpstreamCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_UPSTREAM);
cm().registerNetworkCallback(listenUpstreamRequest, mListenUpstreamCallback, mHandler);
}
/**
@ -183,8 +195,8 @@ public class UpstreamNetworkMonitor {
public void stop() {
setTryCell(false);
releaseCallback(mListenAllCallback);
mListenAllCallback = null;
releaseCallback(mListenUpstreamCallback);
mListenUpstreamCallback = null;
mNetworkMap.clear();
}
@ -535,10 +547,10 @@ public class UpstreamNetworkMonitor {
return;
}
// Any non-LISTEN_ALL callback will necessarily concern a network that will
// also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback.
// So it's not useful to do this work for non-LISTEN_ALL callbacks.
if (mCallbackType == CALLBACK_LISTEN_ALL) {
// Any non-LISTEN_UPSTREAM callback will necessarily concern a network that will
// also match the LISTEN_UPSTREAM callback by construction of the LISTEN_UPSTREAM
// callback. So it's not useful to do this work for non-LISTEN_UPSTREAM callbacks.
if (mCallbackType == CALLBACK_LISTEN_UPSTREAM) {
recomputeLocalPrefixes();
}
}
@ -555,10 +567,11 @@ public class UpstreamNetworkMonitor {
}
handleLost(network);
// Any non-LISTEN_ALL callback will necessarily concern a network that will
// also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback.
// So it's not useful to do this work for non-LISTEN_ALL callbacks.
if (mCallbackType == CALLBACK_LISTEN_ALL) {
// Any non-LISTEN_UPSTREAM callback will necessarily concern a network that will
// also match the LISTEN_UPSTREAM callback by construction of the
// LISTEN_UPSTREAM callback. So it's not useful to do this work for
// non-LISTEN_UPSTREAM callbacks.
if (mCallbackType == CALLBACK_LISTEN_UPSTREAM) {
recomputeLocalPrefixes();
}
}

View file

@ -18,6 +18,7 @@ package com.android.networkstack.tethering;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static com.android.networkstack.apishim.common.ShimUtils.isAtLeastS;
@ -41,6 +42,8 @@ import android.util.ArrayMap;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.modules.utils.build.SdkLevel;
import java.util.Map;
import java.util.Objects;
@ -119,12 +122,15 @@ public class TestConnectivityManager extends ConnectivityManager {
&& mLegacyTypeMap.isEmpty();
}
boolean isListeningForAll() {
final NetworkCapabilities empty = new NetworkCapabilities();
empty.clearAll();
boolean isListeningForUpstream() {
final NetworkCapabilities upstreamNc = new NetworkCapabilities();
upstreamNc.clearAll();
if (SdkLevel.isAtLeastV()) {
upstreamNc.addForbiddenCapability(NET_CAPABILITY_LOCAL_NETWORK);
}
for (NetworkRequestInfo nri : mListening.values()) {
if (nri.request.networkCapabilities.equalRequestableCapabilities(empty)) {
if (nri.request.networkCapabilities.equalRequestableCapabilities(upstreamNc)) {
return true;
}
}

View file

@ -1032,7 +1032,7 @@ public class TetheringTest {
verify(mWifiManager).updateInterfaceIpState(TEST_WLAN_IFNAME, expectedState);
verifyNoMoreInteractions(mWifiManager);
verify(mUpstreamNetworkMonitor).startObserveAllNetworks();
verify(mUpstreamNetworkMonitor).startObserveUpstreamNetworks();
if (isLocalOnly) {
// There are 2 IpServer state change events: STATE_AVAILABLE -> STATE_LOCAL_ONLY.
verify(mNotificationUpdater, times(2)).onDownstreamChanged(DOWNSTREAM_NONE);
@ -1260,7 +1260,7 @@ public class TetheringTest {
// Start USB tethering with no current upstream.
prepareUsbTethering();
sendUsbBroadcast(true, true, TETHER_USB_RNDIS_FUNCTION);
inOrder.verify(mUpstreamNetworkMonitor).startObserveAllNetworks();
inOrder.verify(mUpstreamNetworkMonitor).startObserveUpstreamNetworks();
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
// Pretend cellular connected and expect the upstream to be set.
@ -1859,7 +1859,7 @@ public class TetheringTest {
// Start USB tethering with no current upstream.
prepareUsbTethering();
sendUsbBroadcast(true, true, TETHER_USB_RNDIS_FUNCTION);
inOrder.verify(mUpstreamNetworkMonitor).startObserveAllNetworks();
inOrder.verify(mUpstreamNetworkMonitor).startObserveUpstreamNetworks();
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
ArgumentCaptor<NetworkCallback> captor = ArgumentCaptor.forClass(NetworkCallback.class);
inOrder.verify(mCm).requestNetwork(any(), eq(0), eq(TYPE_MOBILE_DUN), any(),
@ -2587,7 +2587,7 @@ public class TetheringTest {
verify(mNetd, times(1)).tetherStartWithConfiguration(any());
verifyNoMoreInteractions(mNetd);
verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
verify(mUpstreamNetworkMonitor, times(1)).startObserveUpstreamNetworks();
// There are 2 IpServer state change events: STATE_AVAILABLE -> STATE_LOCAL_ONLY
verify(mNotificationUpdater, times(2)).onDownstreamChanged(DOWNSTREAM_NONE);
@ -3757,7 +3757,7 @@ public class TetheringTest {
verifyInterfaceServingModeStarted(TEST_P2P_IFNAME);
verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_AVAILABLE_TETHER);
verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
verify(mUpstreamNetworkMonitor).startObserveAllNetworks();
verify(mUpstreamNetworkMonitor).startObserveUpstreamNetworks();
// Verify never enable upstream if only P2P active.
verify(mUpstreamNetworkMonitor, never()).setTryCell(true);
assertEquals(TETHER_ERROR_NO_ERROR, mTethering.getLastErrorForTest(TEST_P2P_IFNAME));

View file

@ -36,7 +36,6 @@ import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@ -141,7 +140,7 @@ public class UpstreamNetworkMonitorTest {
assertTrue(mCM.hasNoCallbacks());
mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
mUNM.startObserveUpstreamNetworks();
assertEquals(1, mCM.mTrackingDefault.size());
mUNM.stop();
@ -149,13 +148,13 @@ public class UpstreamNetworkMonitorTest {
}
@Test
public void testListensForAllNetworks() throws Exception {
public void testListensForUpstreamNetworks() throws Exception {
assertTrue(mCM.mListening.isEmpty());
mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
mUNM.startObserveUpstreamNetworks();
assertFalse(mCM.mListening.isEmpty());
assertTrue(mCM.isListeningForAll());
assertTrue(mCM.isListeningForUpstream());
mUNM.stop();
assertTrue(mCM.onlyHasDefaultCallbacks());
@ -179,7 +178,7 @@ public class UpstreamNetworkMonitorTest {
assertTrue(TestConnectivityManager.looksLikeDefaultRequest(requestCaptor.getValue()));
}
mUNM.startObserveAllNetworks();
mUNM.startObserveUpstreamNetworks();
verify(mCM, times(1)).registerNetworkCallback(
any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
@ -192,7 +191,7 @@ public class UpstreamNetworkMonitorTest {
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.mRequested.size());
mUNM.startObserveAllNetworks();
mUNM.startObserveUpstreamNetworks();
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.mRequested.size());
@ -215,7 +214,7 @@ public class UpstreamNetworkMonitorTest {
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.mRequested.size());
mUNM.startObserveAllNetworks();
mUNM.startObserveUpstreamNetworks();
verify(mCM, times(1)).registerNetworkCallback(
any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
assertFalse(mUNM.mobileNetworkRequested());
@ -251,7 +250,7 @@ public class UpstreamNetworkMonitorTest {
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.mRequested.size());
mUNM.startObserveAllNetworks();
mUNM.startObserveUpstreamNetworks();
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.mRequested.size());
@ -271,7 +270,7 @@ public class UpstreamNetworkMonitorTest {
@Test
public void testUpdateMobileRequiresDun() throws Exception {
mUNM.startObserveAllNetworks();
mUNM.startObserveUpstreamNetworks();
// Test going from no-DUN to DUN correctly re-registers callbacks.
mUNM.setUpstreamConfig(false /* autoUpstream */, false /* dunRequired */);
@ -301,7 +300,7 @@ public class UpstreamNetworkMonitorTest {
preferredTypes.add(TYPE_WIFI);
mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
mUNM.startObserveUpstreamNetworks();
// There are no networks, so there is nothing to select.
assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
@ -374,7 +373,7 @@ public class UpstreamNetworkMonitorTest {
@Test
public void testGetCurrentPreferredUpstream() throws Exception {
mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
mUNM.startObserveUpstreamNetworks();
mUNM.setUpstreamConfig(true /* autoUpstream */, false /* dunRequired */);
mUNM.setTryCell(true);
@ -446,7 +445,7 @@ public class UpstreamNetworkMonitorTest {
@Test
public void testLocalPrefixes() throws Exception {
mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
mUNM.startObserveUpstreamNetworks();
// [0] Test minimum set of local prefixes.
Set<IpPrefix> local = mUNM.getLocalPrefixes();
@ -558,7 +557,7 @@ public class UpstreamNetworkMonitorTest {
preferredTypes.add(TYPE_MOBILE_HIPRI);
preferredTypes.add(TYPE_WIFI);
mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
mUNM.startObserveUpstreamNetworks();
// Setup wifi and make wifi as default network.
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, WIFI_CAPABILITIES);
wifiAgent.fakeConnect();
@ -579,7 +578,7 @@ public class UpstreamNetworkMonitorTest {
final String ipv6Addr1 = "2001:db8:4:fd00:827a:bfff:fe6f:374d/64";
final String ipv6Addr2 = "2003:aa8:3::123/64";
mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
mUNM.startObserveUpstreamNetworks();
mUNM.setUpstreamConfig(true /* autoUpstream */, false /* dunRequired */);
mUNM.setTryCell(true);