Fix: VPNs update caps upon underlying network disconnect.

Clean cherry-pick of ag/4083954

Bug: 79748782
Test: ConnectivityServiceTests still pass
Change-Id: I21e866c723099e5c3dee54ff13e830d44427fc7a
Merged-In: I12c948ebeb2b74290908f8320ff77220dc4a9fb9
This commit is contained in:
Chalard Jean
2018-05-18 22:02:56 +09:00
parent 32f9daa029
commit 22670f9b93
2 changed files with 40 additions and 24 deletions

View File

@@ -2465,6 +2465,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
ensureNetworkTransitionWakelock(nai.name());
}
mLegacyTypeTracker.remove(nai, wasDefault);
if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
updateAllVpnsCapabilities();
}
rematchAllNetworksAndRequests(null, 0);
mLingerMonitor.noteDisconnect(nai);
if (nai.created) {
@@ -3734,6 +3737,26 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
/**
* Ask all VPN objects to recompute and update their capabilities.
*
* When underlying networks change, VPNs may have to update capabilities to reflect things
* like the metered bit, their transports, and so on. This asks the VPN objects to update
* their capabilities, and as this will cause them to send messages to the ConnectivityService
* handler thread through their agent, this is asynchronous. When the capabilities objects
* are computed they will be up-to-date as they are computed synchronously from here and
* this is running on the ConnectivityService thread.
* TODO : Fix this and call updateCapabilities inline to remove out-of-order events.
*/
private void updateAllVpnsCapabilities() {
synchronized (mVpns) {
for (int i = 0; i < mVpns.size(); i++) {
final Vpn vpn = mVpns.valueAt(i);
vpn.updateCapabilities();
}
}
}
@Override
public boolean updateLockdownVpn() {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
@@ -4891,12 +4914,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (!newNc.hasTransport(TRANSPORT_VPN)) {
// Tell VPNs about updated capabilities, since they may need to
// bubble those changes through.
synchronized (mVpns) {
for (int i = 0; i < mVpns.size(); i++) {
final Vpn vpn = mVpns.valueAt(i);
vpn.updateCapabilities();
}
}
updateAllVpnsCapabilities();
}
}

View File

@@ -4401,24 +4401,22 @@ public class ConnectivityServiceTest {
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
vpnNetworkAgent);
if (false) { // TODO : reactivate this ; in the current state, the below fail.
// Disconnect cell. Receive update without even removing the dead network from the
// underlying networks it's dead anyway. Not metered any more.
mCellNetworkAgent.disconnect();
vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& caps.hasCapability(NET_CAPABILITY_NOT_METERED),
vpnNetworkAgent);
// Disconnect cell. Receive update without even removing the dead network from the
// underlying networks it's dead anyway. Not metered any more.
mCellNetworkAgent.disconnect();
vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& caps.hasCapability(NET_CAPABILITY_NOT_METERED),
vpnNetworkAgent);
// Disconnect wifi too. No underlying networks should mean this is now metered,
// unfortunately a discrepancy in the current implementation has this unmetered.
// TODO : fix this.
mWiFiNetworkAgent.disconnect();
vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& caps.hasCapability(NET_CAPABILITY_NOT_METERED),
vpnNetworkAgent);
}
// Disconnect wifi too. No underlying networks should mean this is now metered,
// unfortunately a discrepancy in the current implementation has this unmetered.
// TODO : fix this.
mWiFiNetworkAgent.disconnect();
vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& caps.hasCapability(NET_CAPABILITY_NOT_METERED),
vpnNetworkAgent);
mMockVpn.disconnect();
}