Loading services/core/java/com/android/server/connectivity/Vpn.java +59 −14 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -3066,22 +3081,28 @@ public class Vpn { return; } try { if (mSession != null && mMobikeEnabled) { 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 " Log.d(TAG, "Migrate IKE Session with token " + mCurrentToken + " to network " + underlyingNetwork); mSession.setNetwork(underlyingNetwork); return; 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) { Loading Loading @@ -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 * Loading Loading @@ -3463,6 +3506,8 @@ public class Vpn { resetIkeState(); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); mConnectivityDiagnosticsManager.unregisterConnectivityDiagnosticsCallback( mDiagnosticsCallback); mExecutor.shutdown(); } Loading Loading
services/core/java/com/android/server/connectivity/Vpn.java +59 −14 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -3066,22 +3081,28 @@ public class Vpn { return; } try { if (mSession != null && mMobikeEnabled) { 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 " Log.d(TAG, "Migrate IKE Session with token " + mCurrentToken + " to network " + underlyingNetwork); mSession.setNetwork(underlyingNetwork); return; 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) { Loading Loading @@ -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 * Loading Loading @@ -3463,6 +3506,8 @@ public class Vpn { resetIkeState(); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); mConnectivityDiagnosticsManager.unregisterConnectivityDiagnosticsCallback( mDiagnosticsCallback); mExecutor.shutdown(); } Loading