From 8a684b8d0dc21f7c435deed6d688db1c952dd562 Mon Sep 17 00:00:00 2001 From: Howard Wu <40033067+Howard20181@users.noreply.github.com> Date: Tue, 30 Nov 2021 09:19:18 +0800 Subject: [PATCH] [core] Use EXTRA_REMOVED_FOR_ALL_USERS (#1460) Android 12 fixes the behavior of ACTION_PACKAGE_FULLY_REMOVED, which is defined to function as a single-user level full uninstall. For full uninstallation by all users and apk deletion, use EXTRA_REMOVED_FOR_ALL_USERS. https://android.googlesource.com/platform/frameworks/base/+/e74e961711cf83c97d26d55f1698fe96bbae4064%5E%21/ --- .../lsposed/lspd/service/LSPosedService.java | 26 +++++++++++-------- .../lsposed/lspd/service/PackageService.java | 4 +-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/org/lsposed/lspd/service/LSPosedService.java b/core/src/main/java/org/lsposed/lspd/service/LSPosedService.java index 1404d756..db85cdb4 100644 --- a/core/src/main/java/org/lsposed/lspd/service/LSPosedService.java +++ b/core/src/main/java/org/lsposed/lspd/service/LSPosedService.java @@ -78,6 +78,8 @@ public class LSPosedService extends ILSPosedService.Stub { int uid = intent.getIntExtra(Intent.EXTRA_UID, AID_NOBODY); if (uid == AID_NOBODY || uid <= 0) return; int userId = intent.getIntExtra("android.intent.extra.user_handle", USER_NULL); + var intentAction = intent.getAction(); + var allUsers = intent.getBooleanExtra("android.intent.extra.REMOVED_FOR_ALL_USERS", false); if (userId == USER_NULL) userId = uid % PER_USER_RANGE; Uri uri = intent.getData(); String moduleName = (uri != null) ? uri.getSchemeSpecificPart() : ConfigManager.getInstance().getModule(uid); @@ -93,14 +95,14 @@ public class LSPosedService extends ILSPosedService.Stub { boolean isXposedModule = applicationInfo != null && applicationInfo.metaData != null && applicationInfo.metaData.containsKey("xposedminversion"); - var intentAction = intent.getAction(); + switch (intentAction) { case Intent.ACTION_PACKAGE_FULLY_REMOVED: { // for module, remove module // because we only care about when the apk is gone - if (moduleName != null) + if (moduleName != null && allUsers) if (ConfigManager.getInstance().removeModule(moduleName)) { - broadcastOrShowNotification(moduleName, userId, intentAction); + broadcastOrShowNotification(moduleName, userId, intent); isXposedModule = true; } break; @@ -114,7 +116,7 @@ public class LSPosedService extends ILSPosedService.Stub { return; } if (isXposedModule) { - broadcastOrShowNotification(moduleName, userId, intentAction); + broadcastOrShowNotification(moduleName, userId, intent); // When installing a new Xposed module, we update the apk path to mark it as a // module to send a broadcast when modules that have not been activated are // uninstalled. @@ -131,7 +133,7 @@ public class LSPosedService extends ILSPosedService.Stub { // when a package is removed (rather than hide) for a single user // (apk may still be there because of multi-user) if (isXposedModule) { - broadcastOrShowNotification(moduleName, userId, intentAction); + broadcastOrShowNotification(moduleName, userId, intent); // it will automatically remove obsolete scope from database ConfigManager.getInstance().updateCache(); } else if (ConfigManager.getInstance().isUidHooked(uid)) { @@ -141,10 +143,10 @@ public class LSPosedService extends ILSPosedService.Stub { break; } } - boolean removed = intentAction.equals(Intent.ACTION_PACKAGE_FULLY_REMOVED) || - intentAction.equals(Intent.ACTION_UID_REMOVED); + boolean removed = Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(intentAction) || + Intent.ACTION_UID_REMOVED.equals(intentAction); - Log.d(TAG, "Package changed: uid=" + uid + " userId=" + userId + " action=" + intent.getAction() + " isXposedModule=" + isXposedModule); + Log.d(TAG, "Package changed: uid=" + uid + " userId=" + userId + " action=" + intentAction + " isXposedModule=" + isXposedModule + " isAllUsers=" + allUsers); if (BuildConfig.DEFAULT_MANAGER_PACKAGE_NAME.equals(moduleName) && userId == 0) { Log.d(TAG, "Manager updated"); @@ -157,15 +159,17 @@ public class LSPosedService extends ILSPosedService.Stub { } } - private void broadcastOrShowNotification(String moduleName, int userId, String intentAction) { + private void broadcastOrShowNotification(String moduleName, int userId, Intent intent) { Log.d(TAG, "module " + moduleName + " changed, dispatching to manager"); - LSPManagerService.broadcastIntent(moduleName, userId, intentAction.equals(Intent.ACTION_PACKAGE_FULLY_REMOVED)); + var internAction = intent.getAction(); + var allUsers = intent.getBooleanExtra("android.intent.extra.REMOVED_FOR_ALL_USERS", false); + LSPManagerService.broadcastIntent(moduleName, userId, allUsers); var enabledModules = ConfigManager.getInstance().enabledModules(); var scope = ConfigManager.getInstance().getModuleScope(moduleName); boolean systemModule = scope != null && scope.parallelStream().anyMatch(app -> app.packageName.equals("android")); boolean enabled = Arrays.asList(enabledModules).contains(moduleName); - if (!(intentAction.equals(Intent.ACTION_PACKAGE_FULLY_REMOVED) || intentAction.equals(Intent.ACTION_UID_REMOVED))) + if (!(Intent.ACTION_UID_REMOVED.equals(internAction) || Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(internAction) || allUsers)) LSPManagerService.showNotification(moduleName, userId, enabled, systemModule); } diff --git a/core/src/main/java/org/lsposed/lspd/service/PackageService.java b/core/src/main/java/org/lsposed/lspd/service/PackageService.java index 4f5bf5d3..9a622044 100644 --- a/core/src/main/java/org/lsposed/lspd/service/PackageService.java +++ b/core/src/main/java/org/lsposed/lspd/service/PackageService.java @@ -39,7 +39,6 @@ import android.content.pm.VersionedPackage; import android.os.Build; import android.os.Bundle; import android.os.IBinder; -import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; @@ -68,8 +67,9 @@ public class PackageService { static final int INSTALL_FAILED_INTERNAL_ERROR = -110; static final int INSTALL_REASON_UNKNOWN = 0; + static final int MATCH_ANY_USER = 0x00400000; // PackageManager.MATCH_ANY_USER - static final int MATCH_ALL_FLAGS = PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_UNINSTALLED_PACKAGES; + static final int MATCH_ALL_FLAGS = PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER; public static final int PER_USER_RANGE = 100000; private static IPackageManager pm = null;