Merge "Perform MOBIKE when data stall is suspected"

This commit is contained in:
Chiachang Wang
2022-10-12 14:04:39 +00:00
committed by Gerrit Code Review

View File

@@ -21,6 +21,7 @@ import static android.Manifest.permission.CONTROL_VPN;
import static android.content.pm.PackageManager.PERMISSION_GRANTED; 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_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; 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_THROW;
import static android.net.RouteInfo.RTN_UNREACHABLE; import static android.net.RouteInfo.RTN_UNREACHABLE;
import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; 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.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.DnsResolver; import android.net.DnsResolver;
import android.net.INetd; import android.net.INetd;
@@ -234,6 +236,7 @@ public class Vpn {
private final Context mContext; private final Context mContext;
private final ConnectivityManager mConnectivityManager; private final ConnectivityManager mConnectivityManager;
private final AppOpsManager mAppOpsManager; private final AppOpsManager mAppOpsManager;
private final ConnectivityDiagnosticsManager mConnectivityDiagnosticsManager;
// The context is for specific user which is created from mUserId // The context is for specific user which is created from mUserId
private final Context mUserIdContext; private final Context mUserIdContext;
@VisibleForTesting final Dependencies mDeps; @VisibleForTesting final Dependencies mDeps;
@@ -549,6 +552,8 @@ public class Vpn {
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
mAppOpsManager = mContext.getSystemService(AppOpsManager.class); mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */); mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
mConnectivityDiagnosticsManager =
mContext.getSystemService(ConnectivityDiagnosticsManager.class);
mDeps = deps; mDeps = deps;
mNms = netService; mNms = netService;
mNetd = netd; mNetd = netd;
@@ -2739,6 +2744,7 @@ public class Vpn {
@Nullable private IkeSessionWrapper mSession; @Nullable private IkeSessionWrapper mSession;
@Nullable private IkeSessionConnectionInfo mIkeConnectionInfo; @Nullable private IkeSessionConnectionInfo mIkeConnectionInfo;
@Nullable private VpnConnectivityDiagnosticsCallback mDiagnosticsCallback;
// mMobikeEnabled can only be updated after IKE AUTH is finished. // mMobikeEnabled can only be updated after IKE AUTH is finished.
private boolean mMobikeEnabled = false; private boolean mMobikeEnabled = false;
@@ -2797,6 +2803,15 @@ public class Vpn {
mConnectivityManager.registerSystemDefaultNetworkCallback(mNetworkCallback, mConnectivityManager.registerSystemDefaultNetworkCallback(mNetworkCallback,
new Handler(mLooper)); 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) { private boolean isActiveNetwork(@Nullable Network network) {
@@ -3066,22 +3081,28 @@ public class Vpn {
return; return;
} }
if (maybeMigrateIkeSession(underlyingNetwork)) return;
startIkeSession(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 { 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;
}
Log.d(TAG, "Start new IKE session on network " + underlyingNetwork);
// Clear mInterface to prevent Ikev2VpnRunner being cleared when // Clear mInterface to prevent Ikev2VpnRunner being cleared when
// interfaceRemoved() is called. // interfaceRemoved() is called.
synchronized (Vpn.this) { synchronized (Vpn.this) {
@@ -3169,6 +3190,28 @@ public class Vpn {
mUnderlyingLinkProperties = lp; 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 * Handles loss of the default underlying network
* *
@@ -3463,6 +3506,8 @@ public class Vpn {
resetIkeState(); resetIkeState();
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
mConnectivityDiagnosticsManager.unregisterConnectivityDiagnosticsCallback(
mDiagnosticsCallback);
mExecutor.shutdown(); mExecutor.shutdown();
} }