summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author junyulai <junyulai@google.com> 2018-11-12 22:39:30 +0800
committer junyulai <junyulai@google.com> 2018-12-11 14:04:02 +0800
commitefb04d36601c72e0c3b753c133f4ef26bfea89b3 (patch)
tree44841d99c1b969a229a0afdf83c9e91c3099a041
parent0882543a128a7f1289d54600dd48a4f2df3a30df (diff)
VPN: Move package intent receiver to ConnectivityService.
Currently, PermissionMonitor listen to user add/remove and package add/remove intent respectively, and so does VPN. Thus, races might occurr between them. This commit refactor VPN part by using ConnectivityService to listen to intents and dispatch events to VPN. Bug: 118811303 Test: 1. atest FrameworksNetTests 2. manually add/remove package 3. cts-tradefed run cts -m CtsHostsideNetworkTests Change-Id: Id76fd77c5fcfb2b0e21f211f63f007b1ea1aa53f
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java43
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java66
2 files changed, 41 insertions, 68 deletions
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 14503f9d7379..eda9fe15fe36 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -902,6 +902,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Listen to package add and removal events for all users.
intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addDataScheme("package");
mContext.registerReceiverAsUser(
@@ -4203,12 +4204,46 @@ public class ConnectivityService extends IConnectivityManager.Stub
mPermissionMonitor.onPackageAdded(packageName, uid);
}
- private void onPackageRemoved(String packageName, int uid) {
+ private void onPackageReplaced(String packageName, int uid) {
+ if (TextUtils.isEmpty(packageName) || uid < 0) {
+ Slog.wtf(TAG, "Invalid package in onPackageReplaced: " + packageName + " | " + uid);
+ return;
+ }
+ final int userId = UserHandle.getUserId(uid);
+ synchronized (mVpns) {
+ final Vpn vpn = mVpns.get(userId);
+ if (vpn == null) {
+ return;
+ }
+ // Legacy always-on VPN won't be affected since the package name is not set.
+ if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) {
+ Slog.d(TAG, "Restarting always-on VPN package " + packageName + " for user "
+ + userId);
+ vpn.startAlwaysOnVpn();
+ }
+ }
+ }
+
+ private void onPackageRemoved(String packageName, int uid, boolean isReplacing) {
if (TextUtils.isEmpty(packageName) || uid < 0) {
Slog.wtf(TAG, "Invalid package in onPackageRemoved: " + packageName + " | " + uid);
return;
}
mPermissionMonitor.onPackageRemoved(uid);
+
+ final int userId = UserHandle.getUserId(uid);
+ synchronized (mVpns) {
+ final Vpn vpn = mVpns.get(userId);
+ if (vpn == null) {
+ return;
+ }
+ // Legacy always-on VPN won't be affected since the package name is not set.
+ if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) {
+ Slog.d(TAG, "Removing always-on VPN package " + packageName + " for user "
+ + userId);
+ vpn.setAlwaysOnPackage(null, false);
+ }
+ }
}
private void onUserUnlocked(int userId) {
@@ -4245,8 +4280,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
onUserUnlocked(userId);
} else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
onPackageAdded(packageName, uid);
+ } else if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
+ onPackageReplaced(packageName, uid);
} else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
- onPackageRemoved(packageName, uid);
+ final boolean isReplacing = intent.getBooleanExtra(
+ Intent.EXTRA_REPLACING, false);
+ onPackageRemoved(packageName, uid, isReplacing);
}
}
};
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index b7ed2f9bd473..602aedbc2d00 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -206,45 +206,6 @@ public class Vpn {
// Handle of the user initiating VPN.
private final int mUserHandle;
- // Listen to package removal and change events (update/uninstall) for this user
- private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final Uri data = intent.getData();
- final String packageName = data == null ? null : data.getSchemeSpecificPart();
- if (packageName == null) {
- return;
- }
-
- synchronized (Vpn.this) {
- // Avoid race where always-on package has been unset
- if (!packageName.equals(getAlwaysOnPackage())) {
- return;
- }
-
- final String action = intent.getAction();
- Log.i(TAG, "Received broadcast " + action + " for always-on VPN package "
- + packageName + " in user " + mUserHandle);
-
- switch(action) {
- case Intent.ACTION_PACKAGE_REPLACED:
- // Start vpn after app upgrade
- startAlwaysOnVpn();
- break;
- case Intent.ACTION_PACKAGE_REMOVED:
- final boolean isPackageRemoved = !intent.getBooleanExtra(
- Intent.EXTRA_REPLACING, false);
- if (isPackageRemoved) {
- setAlwaysOnPackage(null, false);
- }
- break;
- }
- }
- }
- };
-
- private boolean mIsPackageIntentReceiverRegistered = false;
-
public Vpn(Looper looper, Context context, INetworkManagementService netService,
@UserIdInt int userHandle) {
this(looper, context, netService, userHandle, new SystemServices(context));
@@ -500,7 +461,6 @@ public class Vpn {
// Prepare this app. The notification will update as a side-effect of updateState().
prepareInternal(packageName);
}
- maybeRegisterPackageChangeReceiverLocked(packageName);
setVpnForcedLocked(mLockdown);
return true;
}
@@ -509,31 +469,6 @@ public class Vpn {
return packageName == null || VpnConfig.LEGACY_VPN.equals(packageName);
}
- private void unregisterPackageChangeReceiverLocked() {
- if (mIsPackageIntentReceiverRegistered) {
- mContext.unregisterReceiver(mPackageIntentReceiver);
- mIsPackageIntentReceiverRegistered = false;
- }
- }
-
- private void maybeRegisterPackageChangeReceiverLocked(String packageName) {
- // Unregister IntentFilter listening for previous always-on package change
- unregisterPackageChangeReceiverLocked();
-
- if (!isNullOrLegacyVpn(packageName)) {
- mIsPackageIntentReceiverRegistered = true;
-
- IntentFilter intentFilter = new IntentFilter();
- // Protected intent can only be sent by system. No permission required in register.
- intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
- intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- intentFilter.addDataScheme("package");
- intentFilter.addDataSchemeSpecificPart(packageName, PatternMatcher.PATTERN_LITERAL);
- mContext.registerReceiverAsUser(
- mPackageIntentReceiver, UserHandle.of(mUserHandle), intentFilter, null, null);
- }
- }
-
/**
* @return the package name of the VPN controller responsible for always-on VPN,
* or {@code null} if none is set or always-on VPN is controlled through
@@ -1302,7 +1237,6 @@ public class Vpn {
setLockdown(false);
mAlwaysOn = false;
- unregisterPackageChangeReceiverLocked();
// Quit any active connections
agentDisconnect();
}