From 03f0d12480b72780e67cce33473e8c55befc2669 Mon Sep 17 00:00:00 2001 From: chiachangwang Date: Wed, 29 Jun 2022 03:08:15 +0000 Subject: [PATCH] Stop VPN profiles by exiting VpnRunner instead of prepareInternal Change to call the VpnRunner.exit to stop vpn profile instead of using prepareInternal to leave the package intact. This aligns with the way that VpnServices are disconnected so that the package and other related information will not be reset unexpectedly. In current design, Vpn will examine if the current prepared package matches to prevent an existing always-on VPN from being dethroned by other apps when the VPN always-on is enabled. However, when the VPN is disabled using stopVpnProfile, the current package name will be updated to [LEGACY VPN]. The current package will no longer be the same with the VPN package. This resulted in the rejection of the VPN app to start the VPN using VpnManager.startVpnProfile again. Test: atest FrameworksNetTests Test: manually test with VPN app to reconnect VPN when always-on is enabled. Bug: 235322391 Change-Id: I83e1e1edf6c3a6653d87216afcd397f296f59cf2 --- .../com/android/server/connectivity/Vpn.java | 35 +++++++++++-------- 1 file changed, 21 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 50b6d77cfd5c2..c3fc8e0a7535e 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -1182,20 +1182,9 @@ public class Vpn { cleanupVpnStateLocked(); } else if (mVpnRunner != null) { if (!VpnConfig.LEGACY_VPN.equals(mPackage)) { - mAppOpsManager.finishOp( - AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null); - // The underlying network, NetworkCapabilities and LinkProperties are not - // necessary to send to VPN app since the purpose of this event is to notify - // VPN app that VPN is deactivated by the user. - // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from - // ConnectivityServiceTest. - if (SdkLevel.isAtLeastT()) { - sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER, - -1 /* errorClass */, -1 /* errorCode*/, mPackage, - getSessionKeyLocked(), makeVpnProfileStateLocked(), - null /* underlyingNetwork */, null /* nc */, null /* lp */); - } + notifyVpnManagerVpnStopped(mPackage, mOwnerUID); } + // cleanupVpnStateLocked() is called from mVpnRunner.exit() mVpnRunner.exit(); } @@ -4043,7 +4032,25 @@ public class Vpn { // To stop the VPN profile, the caller must be the current prepared package and must be // running an Ikev2VpnProfile. if (isCurrentIkev2VpnLocked(packageName)) { - prepareInternal(VpnConfig.LEGACY_VPN); + notifyVpnManagerVpnStopped(packageName, mOwnerUID); + + mVpnRunner.exit(); + } + } + + private synchronized void notifyVpnManagerVpnStopped(String packageName, int ownerUID) { + mAppOpsManager.finishOp( + AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, ownerUID, packageName, null); + // The underlying network, NetworkCapabilities and LinkProperties are not + // necessary to send to VPN app since the purpose of this event is to notify + // VPN app that VPN is deactivated by the user. + // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from + // ConnectivityServiceTest. + if (SdkLevel.isAtLeastT()) { + sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER, + -1 /* errorClass */, -1 /* errorCode*/, packageName, + getSessionKeyLocked(), makeVpnProfileStateLocked(), + null /* underlyingNetwork */, null /* nc */, null /* lp */); } }