diff options
| -rw-r--r-- | services/core/java/com/android/server/connectivity/Vpn.java | 84 |
1 files 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 1e9352d10956..21773ccd4356 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -271,6 +271,13 @@ public class Vpn { 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; } } |