diff options
| author | 2022-10-12 14:34:59 +0000 | |
|---|---|---|
| committer | 2022-10-12 14:34:59 +0000 | |
| commit | bf20b85b3130cff17e82ab8de96022ae4f4ac699 (patch) | |
| tree | 0d4b07c28024f5ede50304e929c749265c79ecfe | |
| parent | 172e2c5a3160e0ed1d9676b98b3d28a8eae6d964 (diff) | |
| parent | 97db242349add4293520db6e73259a6422a1e309 (diff) | |
Merge "Perform MOBIKE when data stall is suspected" am: 97db242349
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2171149
Change-Id: I5490b3e29c79e4ef83ff8229a7be084433873d90
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
| -rw-r--r-- | services/core/java/com/android/server/connectivity/Vpn.java | 73 |
1 files changed, 59 insertions, 14 deletions
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 6a53978175af..6795b6b4158d 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -21,6 +21,7 @@ import static android.Manifest.permission.CONTROL_VPN; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; +import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.RouteInfo.RTN_THROW; import static android.net.RouteInfo.RTN_UNREACHABLE; import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; @@ -51,6 +52,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; +import android.net.ConnectivityDiagnosticsManager; import android.net.ConnectivityManager; import android.net.DnsResolver; import android.net.INetd; @@ -234,6 +236,7 @@ public class Vpn { private final Context mContext; private final ConnectivityManager mConnectivityManager; private final AppOpsManager mAppOpsManager; + private final ConnectivityDiagnosticsManager mConnectivityDiagnosticsManager; // The context is for specific user which is created from mUserId private final Context mUserIdContext; @VisibleForTesting final Dependencies mDeps; @@ -549,6 +552,8 @@ public class Vpn { mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); mAppOpsManager = mContext.getSystemService(AppOpsManager.class); mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */); + mConnectivityDiagnosticsManager = + mContext.getSystemService(ConnectivityDiagnosticsManager.class); mDeps = deps; mNms = netService; mNetd = netd; @@ -2739,6 +2744,7 @@ public class Vpn { @Nullable private IkeSessionWrapper mSession; @Nullable private IkeSessionConnectionInfo mIkeConnectionInfo; + @Nullable private VpnConnectivityDiagnosticsCallback mDiagnosticsCallback; // mMobikeEnabled can only be updated after IKE AUTH is finished. private boolean mMobikeEnabled = false; @@ -2797,6 +2803,15 @@ public class Vpn { mConnectivityManager.registerSystemDefaultNetworkCallback(mNetworkCallback, new Handler(mLooper)); } + + // DiagnosticsCallback may return more than one alive VPNs, but VPN will filter based on + // Network object. + final NetworkRequest diagRequest = new NetworkRequest.Builder() + .addTransportType(TRANSPORT_VPN) + .removeCapability(NET_CAPABILITY_NOT_VPN).build(); + mDiagnosticsCallback = new VpnConnectivityDiagnosticsCallback(); + mConnectivityDiagnosticsManager.registerConnectivityDiagnosticsCallback( + diagRequest, mExecutor, mDiagnosticsCallback); } private boolean isActiveNetwork(@Nullable Network network) { @@ -3066,22 +3081,28 @@ public class Vpn { return; } - try { - if (mSession != null && mMobikeEnabled) { - // IKE session can schedule a migration event only when IKE AUTH is finished - // and mMobikeEnabled is true. - Log.d( - TAG, - "Migrate IKE Session with token " - + mCurrentToken - + " to network " - + underlyingNetwork); - mSession.setNetwork(underlyingNetwork); - return; - } + if (maybeMigrateIkeSession(underlyingNetwork)) return; + + startIkeSession(underlyingNetwork); + } - Log.d(TAG, "Start new IKE session on network " + underlyingNetwork); + boolean maybeMigrateIkeSession(@NonNull Network underlyingNetwork) { + if (mSession == null || !mMobikeEnabled) return false; + // IKE session can schedule a migration event only when IKE AUTH is finished + // and mMobikeEnabled is true. + Log.d(TAG, "Migrate IKE Session with token " + + mCurrentToken + + " to network " + + underlyingNetwork); + mSession.setNetwork(underlyingNetwork); + return true; + } + + private void startIkeSession(@NonNull Network underlyingNetwork) { + Log.d(TAG, "Start new IKE session on network " + underlyingNetwork); + + try { // Clear mInterface to prevent Ikev2VpnRunner being cleared when // interfaceRemoved() is called. synchronized (Vpn.this) { @@ -3169,6 +3190,28 @@ public class Vpn { mUnderlyingLinkProperties = lp; } + class VpnConnectivityDiagnosticsCallback + extends ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback { + // The callback runs in the executor thread. + @Override + public void onDataStallSuspected( + ConnectivityDiagnosticsManager.DataStallReport report) { + synchronized (Vpn.this) { + // Ignore stale runner. + if (mVpnRunner != Vpn.IkeV2VpnRunner.this) return; + + // Handle the report only for current VPN network. + if (mNetworkAgent != null + && mNetworkAgent.getNetwork().equals(report.getNetwork())) { + Log.d(TAG, "Data stall suspected"); + + // Trigger MOBIKE. + maybeMigrateIkeSession(mActiveNetwork); + } + } + } + } + /** * Handles loss of the default underlying network * @@ -3463,6 +3506,8 @@ public class Vpn { resetIkeState(); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); + mConnectivityDiagnosticsManager.unregisterConnectivityDiagnosticsCallback( + mDiagnosticsCallback); mExecutor.shutdown(); } |