[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.
e74e961711%5E%21/
This commit is contained in:
Howard Wu 2021-11-30 09:19:18 +08:00 committed by vvb2060
parent 86a20f7eef
commit 8a684b8d0d
No known key found for this signature in database
GPG Key ID: 59B2BF15A79E26FA
2 changed files with 17 additions and 13 deletions

View File

@ -78,6 +78,8 @@ public class LSPosedService extends ILSPosedService.Stub {
int uid = intent.getIntExtra(Intent.EXTRA_UID, AID_NOBODY); int uid = intent.getIntExtra(Intent.EXTRA_UID, AID_NOBODY);
if (uid == AID_NOBODY || uid <= 0) return; if (uid == AID_NOBODY || uid <= 0) return;
int userId = intent.getIntExtra("android.intent.extra.user_handle", USER_NULL); 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; if (userId == USER_NULL) userId = uid % PER_USER_RANGE;
Uri uri = intent.getData(); Uri uri = intent.getData();
String moduleName = (uri != null) ? uri.getSchemeSpecificPart() : ConfigManager.getInstance().getModule(uid); String moduleName = (uri != null) ? uri.getSchemeSpecificPart() : ConfigManager.getInstance().getModule(uid);
@ -93,14 +95,14 @@ public class LSPosedService extends ILSPosedService.Stub {
boolean isXposedModule = applicationInfo != null && boolean isXposedModule = applicationInfo != null &&
applicationInfo.metaData != null && applicationInfo.metaData != null &&
applicationInfo.metaData.containsKey("xposedminversion"); applicationInfo.metaData.containsKey("xposedminversion");
var intentAction = intent.getAction();
switch (intentAction) { switch (intentAction) {
case Intent.ACTION_PACKAGE_FULLY_REMOVED: { case Intent.ACTION_PACKAGE_FULLY_REMOVED: {
// for module, remove module // for module, remove module
// because we only care about when the apk is gone // because we only care about when the apk is gone
if (moduleName != null) if (moduleName != null && allUsers)
if (ConfigManager.getInstance().removeModule(moduleName)) { if (ConfigManager.getInstance().removeModule(moduleName)) {
broadcastOrShowNotification(moduleName, userId, intentAction); broadcastOrShowNotification(moduleName, userId, intent);
isXposedModule = true; isXposedModule = true;
} }
break; break;
@ -114,7 +116,7 @@ public class LSPosedService extends ILSPosedService.Stub {
return; return;
} }
if (isXposedModule) { 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 // 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 // module to send a broadcast when modules that have not been activated are
// uninstalled. // uninstalled.
@ -131,7 +133,7 @@ public class LSPosedService extends ILSPosedService.Stub {
// when a package is removed (rather than hide) for a single user // when a package is removed (rather than hide) for a single user
// (apk may still be there because of multi-user) // (apk may still be there because of multi-user)
if (isXposedModule) { if (isXposedModule) {
broadcastOrShowNotification(moduleName, userId, intentAction); broadcastOrShowNotification(moduleName, userId, intent);
// it will automatically remove obsolete scope from database // it will automatically remove obsolete scope from database
ConfigManager.getInstance().updateCache(); ConfigManager.getInstance().updateCache();
} else if (ConfigManager.getInstance().isUidHooked(uid)) { } else if (ConfigManager.getInstance().isUidHooked(uid)) {
@ -141,10 +143,10 @@ public class LSPosedService extends ILSPosedService.Stub {
break; break;
} }
} }
boolean removed = intentAction.equals(Intent.ACTION_PACKAGE_FULLY_REMOVED) || boolean removed = Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(intentAction) ||
intentAction.equals(Intent.ACTION_UID_REMOVED); 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) { if (BuildConfig.DEFAULT_MANAGER_PACKAGE_NAME.equals(moduleName) && userId == 0) {
Log.d(TAG, "Manager updated"); 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"); 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 enabledModules = ConfigManager.getInstance().enabledModules();
var scope = ConfigManager.getInstance().getModuleScope(moduleName); var scope = ConfigManager.getInstance().getModuleScope(moduleName);
boolean systemModule = scope != null && boolean systemModule = scope != null &&
scope.parallelStream().anyMatch(app -> app.packageName.equals("android")); scope.parallelStream().anyMatch(app -> app.packageName.equals("android"));
boolean enabled = Arrays.asList(enabledModules).contains(moduleName); 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); LSPManagerService.showNotification(moduleName, userId, enabled, systemModule);
} }

View File

@ -39,7 +39,6 @@ import android.content.pm.VersionedPackage;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.os.SystemProperties; import android.os.SystemProperties;
@ -68,8 +67,9 @@ public class PackageService {
static final int INSTALL_FAILED_INTERNAL_ERROR = -110; static final int INSTALL_FAILED_INTERNAL_ERROR = -110;
static final int INSTALL_REASON_UNKNOWN = 0; 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; public static final int PER_USER_RANGE = 100000;
private static IPackageManager pm = null; private static IPackageManager pm = null;