From 1170a0fb45d748ee798626df6e73177bb556bd19 Mon Sep 17 00:00:00 2001 From: chiachangwang Date: Wed, 15 Mar 2023 07:24:29 +0000 Subject: [PATCH] Update longLivedTcpConnectionsExpensive value in VpnTransportInfo The longLivedTcpConnectionsExpensive value relies on the keepalive value, so the Vpn should send network capabilities update to renew the VpnTransportInfo. The applications that may bypass VPN based on the value could update with it accordingly. The VpnTransportInfo should be recreated when 1. The NeworkAgent is created 2. The underlying network of the VPN network is updated 3. The carrierconfig is changed The NetworkCapabilities may be updated more frequently than these 3 events. But the others does not affect the keepalive value so it's fine to used the TransportInfo from existing NetworkCapabilities. Bug: 273422889 Test: atest FrameworksNetTests Change-Id: Ia1a124fc06d2d882eb154f24a75493ad0a308a78 --- .../com/android/server/connectivity/Vpn.java | 84 ++++++++++++++----- 1 file changed, 65 insertions(+), 19 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 1e9352d109565..21773ccd43565 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -270,6 +270,13 @@ public class Vpn { @VisibleForTesting static final int DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT = 5 * 60; + /** + * Default keepalive value to consider long-lived TCP connections are expensive on the + * VPN network from battery usage point of view. + * TODO: consider reading from setting. + */ + @VisibleForTesting + static final int DEFAULT_LONG_LIVED_TCP_CONNS_EXPENSIVE_TIMEOUT_SEC = 60; /** * Prefer using {@link IkeSessionParams.ESP_IP_VERSION_AUTO} and * {@link IkeSessionParams.ESP_ENCAP_TYPE_AUTO} for ESP packets. @@ -1670,9 +1677,12 @@ public class Vpn { capsBuilder.setUids(createUserAndRestrictedProfilesRanges(mUserId, mConfig.allowedApplications, mConfig.disallowedApplications)); - capsBuilder.setTransportInfo( - new VpnTransportInfo(getActiveVpnType(), mConfig.session, mConfig.allowBypass, - false /* longLivedTcpConnectionsExpensive */)); + final boolean expensive = areLongLivedTcpConnectionsExpensive(mVpnRunner); + capsBuilder.setTransportInfo(new VpnTransportInfo( + getActiveVpnType(), + mConfig.session, + mConfig.allowBypass, + expensive)); // Only apps targeting Q and above can explicitly declare themselves as metered. // These VPNs are assumed metered unless they state otherwise. @@ -1704,6 +1714,17 @@ public class Vpn { updateState(DetailedState.CONNECTED, "agentConnect"); } + private static boolean areLongLivedTcpConnectionsExpensive(@NonNull VpnRunner runner) { + if (!(runner instanceof IkeV2VpnRunner)) return false; + + final int delay = ((IkeV2VpnRunner) runner).getOrGuessKeepaliveDelaySeconds(); + return areLongLivedTcpConnectionsExpensive(delay); + } + + private static boolean areLongLivedTcpConnectionsExpensive(int keepaliveDelaySec) { + return keepaliveDelaySec < DEFAULT_LONG_LIVED_TCP_CONNS_EXPENSIVE_TIMEOUT_SEC; + } + private boolean canHaveRestrictedProfile(int userId) { final long token = Binder.clearCallingIdentity(); try { @@ -2988,10 +3009,8 @@ public class Vpn { // Ignore stale runner. if (mVpnRunner != Vpn.IkeV2VpnRunner.this) return; - maybeMigrateIkeSession(mActiveNetwork); + maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork); } - // TODO: update the longLivedTcpConnectionsExpensive value in the - // networkcapabilities of the VPN network. } }; @@ -3442,7 +3461,7 @@ public class Vpn { return; } - if (maybeMigrateIkeSession(underlyingNetwork)) return; + if (maybeMigrateIkeSessionAndUpdateVpnTransportInfo(underlyingNetwork)) return; startIkeSession(underlyingNetwork); } @@ -3549,7 +3568,43 @@ public class Vpn { return new CarrierConfigInfo(mccMnc, natKeepalive, encapType, ipVersion); } - boolean maybeMigrateIkeSession(@NonNull Network underlyingNetwork) { + private int getOrGuessKeepaliveDelaySeconds() { + if (mProfile.isAutomaticNattKeepaliveTimerEnabled()) { + return guessNattKeepaliveTimerForNetwork(); + } else if (mProfile.getIkeTunnelConnectionParams() != null) { + return mProfile.getIkeTunnelConnectionParams() + .getIkeSessionParams().getNattKeepAliveDelaySeconds(); + } + return DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT; + } + + boolean maybeMigrateIkeSessionAndUpdateVpnTransportInfo( + @NonNull Network underlyingNetwork) { + final int keepaliveDelaySec = getOrGuessKeepaliveDelaySeconds(); + final boolean migrated = maybeMigrateIkeSession(underlyingNetwork, keepaliveDelaySec); + if (migrated) { + updateVpnTransportInfoAndNetCap(keepaliveDelaySec); + } + return migrated; + } + + public void updateVpnTransportInfoAndNetCap(int keepaliveDelaySec) { + final VpnTransportInfo info = new VpnTransportInfo( + getActiveVpnType(), + mConfig.session, + mConfig.allowBypass, + areLongLivedTcpConnectionsExpensive(keepaliveDelaySec)); + final boolean ncUpdateRequired = !info.equals(mNetworkCapabilities.getTransportInfo()); + if (ncUpdateRequired) { + mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities) + .setTransportInfo(info) + .build(); + doSendNetworkCapabilities(mNetworkAgent, mNetworkCapabilities); + } + } + + private boolean maybeMigrateIkeSession(@NonNull Network underlyingNetwork, + int keepaliveDelaySeconds) { if (mSession == null || !mMobikeEnabled) return false; // IKE session can schedule a migration event only when IKE AUTH is finished @@ -3574,15 +3629,6 @@ public class Vpn { encapType = ESP_ENCAP_TYPE_AUTO; } - final int keepaliveDelaySeconds; - if (mProfile.isAutomaticNattKeepaliveTimerEnabled()) { - keepaliveDelaySeconds = guessNattKeepaliveTimerForNetwork(); - } else if (mProfile.getIkeTunnelConnectionParams() != null) { - keepaliveDelaySeconds = mProfile.getIkeTunnelConnectionParams() - .getIkeSessionParams().getNattKeepAliveDelaySeconds(); - } else { - keepaliveDelaySeconds = DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT; - } mSession.setNetwork(underlyingNetwork, ipVersion, encapType, keepaliveDelaySeconds); return true; } @@ -3663,7 +3709,7 @@ public class Vpn { startOrMigrateIkeSession(mActiveNetwork); } else if (!nc.getSubscriptionIds().equals(oldNc.getSubscriptionIds())) { // Renew carrierConfig values. - maybeMigrateIkeSession(mActiveNetwork); + maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork); } } @@ -3691,7 +3737,7 @@ public class Vpn { Log.d(TAG, "Data stall suspected"); // Trigger MOBIKE. - maybeMigrateIkeSession(mActiveNetwork); + maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork); mDataStallSuspected = true; } }