Merge "Send a proxy broadcast when apps moved from/to a VPN"

This commit is contained in:
Lucas Lin
2021-06-15 09:26:21 +00:00
committed by Gerrit Code Review
3 changed files with 162 additions and 19 deletions

View File

@@ -484,6 +484,7 @@ public class ConnectivityServiceTest {
@Mock VpnProfileStore mVpnProfileStore;
@Mock SystemConfigManager mSystemConfigManager;
@Mock Resources mResources;
@Mock ProxyTracker mProxyTracker;
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -1278,10 +1279,14 @@ public class ConnectivityServiceTest {
return mMockNetworkAgent;
}
public void establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated,
boolean hasInternet, boolean isStrictMode) throws Exception {
private void setOwnerAndAdminUid(int uid) throws Exception {
mNetworkCapabilities.setOwnerUid(uid);
mNetworkCapabilities.setAdministratorUids(new int[]{uid});
}
public void establish(LinkProperties lp, int uid, Set<UidRange> ranges, boolean validated,
boolean hasInternet, boolean isStrictMode) throws Exception {
setOwnerAndAdminUid(uid);
registerAgent(false, ranges, lp);
connect(validated, hasInternet, isStrictMode);
waitForIdle();
@@ -1636,7 +1641,7 @@ public class ConnectivityServiceTest {
doReturn(mNetIdManager).when(deps).makeNetIdManager();
doReturn(mNetworkStack).when(deps).getNetworkStack();
doReturn(mSystemProperties).when(deps).getSystemProperties();
doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
doReturn(mProxyTracker).when(deps).makeProxyTracker(any(), any());
doReturn(true).when(deps).queryUserAccess(anyInt(), any(), any());
doAnswer(inv -> {
mPolicyTracker = new WrappedMultinetworkPolicyTracker(
@@ -10262,16 +10267,23 @@ public class ConnectivityServiceTest {
@Test
public void testVpnUidRangesUpdate() throws Exception {
LinkProperties lp = new LinkProperties();
// Set up a WiFi network without proxy.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
assertNull(mService.getProxyForNetwork(null));
assertNull(mCm.getDefaultProxy());
final LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
final UidRange vpnRange = PRIMARY_UIDRANGE;
Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
mMockVpn.establish(lp, VPN_UID, vpnRanges);
assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
// VPN is connected but proxy is not set, so there is no need to send proxy broadcast.
verify(mProxyTracker, never()).sendProxyBroadcast();
reset(mMockNetd);
// Update to new range which is old range minus APP1, i.e. only APP2
final Set<UidRange> newRanges = new HashSet<>(Arrays.asList(
new UidRange(vpnRange.start, APP1_UID - 1),
@@ -10281,6 +10293,101 @@ public class ConnectivityServiceTest {
assertVpnUidRangesUpdated(true, newRanges, VPN_UID);
assertVpnUidRangesUpdated(false, vpnRanges, VPN_UID);
// Uid has changed but proxy is not set, so there is no need to send proxy broadcast.
verify(mProxyTracker, never()).sendProxyBroadcast();
final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
lp.setHttpProxy(testProxyInfo);
mMockVpn.sendLinkProperties(lp);
waitForIdle();
// Proxy is set, so send a proxy broadcast.
verify(mProxyTracker, times(1)).sendProxyBroadcast();
reset(mProxyTracker);
mMockVpn.setUids(vpnRanges);
waitForIdle();
// Uid has changed and proxy is already set, so send a proxy broadcast.
verify(mProxyTracker, times(1)).sendProxyBroadcast();
reset(mProxyTracker);
// Proxy is removed, send a proxy broadcast.
lp.setHttpProxy(null);
mMockVpn.sendLinkProperties(lp);
waitForIdle();
verify(mProxyTracker, times(1)).sendProxyBroadcast();
reset(mProxyTracker);
// Proxy is added in WiFi(default network), setDefaultProxy will be called.
final LinkProperties wifiLp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
assertNotNull(wifiLp);
wifiLp.setHttpProxy(testProxyInfo);
mWiFiNetworkAgent.sendLinkProperties(wifiLp);
waitForIdle();
verify(mProxyTracker, times(1)).setDefaultProxy(eq(testProxyInfo));
reset(mProxyTracker);
}
@Test
public void testProxyBroadcastWillBeSentWhenVpnHasProxyAndConnects() throws Exception {
// Set up a WiFi network without proxy.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
assertNull(mService.getProxyForNetwork(null));
assertNull(mCm.getDefaultProxy());
final LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
lp.setHttpProxy(testProxyInfo);
final UidRange vpnRange = PRIMARY_UIDRANGE;
final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
mMockVpn.setOwnerAndAdminUid(VPN_UID);
mMockVpn.registerAgent(false, vpnRanges, lp);
// In any case, the proxy broadcast won't be sent before VPN goes into CONNECTED state.
// Otherwise, the app that calls ConnectivityManager#getDefaultProxy() when it receives the
// proxy broadcast will get null.
verify(mProxyTracker, never()).sendProxyBroadcast();
mMockVpn.connect(true /* validated */, true /* hasInternet */, false /* isStrictMode */);
waitForIdle();
assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
// Vpn is connected with proxy, so the proxy broadcast will be sent to inform the apps to
// update their proxy data.
verify(mProxyTracker, times(1)).sendProxyBroadcast();
}
@Test
public void testProxyBroadcastWillBeSentWhenTheProxyOfNonDefaultNetworkHasChanged()
throws Exception {
// Set up a CELLULAR network without proxy.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
assertNull(mService.getProxyForNetwork(null));
assertNull(mCm.getDefaultProxy());
// CELLULAR network should be the default network.
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Set up a WiFi network without proxy.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
assertNull(mService.getProxyForNetwork(null));
assertNull(mCm.getDefaultProxy());
// WiFi network should be the default network.
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// CELLULAR network is not the default network.
assertNotEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// CELLULAR network is not the system default network, but it might be a per-app default
// network. The proxy broadcast should be sent once its proxy has changed.
final LinkProperties cellularLp = new LinkProperties();
cellularLp.setInterfaceName(MOBILE_IFNAME);
final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
cellularLp.setHttpProxy(testProxyInfo);
mCellNetworkAgent.sendLinkProperties(cellularLp);
waitForIdle();
verify(mProxyTracker, times(1)).sendProxyBroadcast();
}
@Test