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
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 14503f9..eda9fe1 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -902,6 +902,7 @@
// 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 @@
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 @@
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);
}
}
};