Fix the module status in the manager after module changes (#1202)

This commit is contained in:
Howard Wu 2021-10-03 10:43:17 +08:00 committed by GitHub
parent 5c27c55720
commit 67d3fe82ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 26 deletions

View File

@ -38,7 +38,6 @@ import androidx.preference.PreferenceManager;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import org.lsposed.hiddenapibypass.HiddenApiBypass; import org.lsposed.hiddenapibypass.HiddenApiBypass;
import org.lsposed.manager.receivers.LSPManagerServiceHolder;
import org.lsposed.manager.repo.RepoLoader; import org.lsposed.manager.repo.RepoLoader;
import org.lsposed.manager.ui.activity.CrashReportActivity; import org.lsposed.manager.ui.activity.CrashReportActivity;
import org.lsposed.manager.util.DoHDNS; import org.lsposed.manager.util.DoHDNS;
@ -168,8 +167,9 @@ public class App extends Application {
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
int userId = intent.getIntExtra(Intent.EXTRA_USER, 0); int userId = intent.getIntExtra(Intent.EXTRA_USER, 0);
String packageName = intent.getStringExtra("android.intent.extra.PACKAGES"); String packageName = intent.getStringExtra("android.intent.extra.PACKAGES");
boolean packageFullyRemoved = intent.getBooleanExtra(Intent.ACTION_PACKAGE_FULLY_REMOVED, false);
if (packageName != null) { if (packageName != null) {
ModuleUtil.getInstance().reloadSingleModule(packageName, userId); ModuleUtil.getInstance().reloadSingleModule(packageName, userId, packageFullyRemoved);
} }
} }
}, new IntentFilter(Intent.ACTION_PACKAGE_CHANGED)); }, new IntentFilter(Intent.ACTION_PACKAGE_CHANGED));

View File

@ -108,6 +108,12 @@ public final class ModuleUtil {
} }
public InstalledModule reloadSingleModule(String packageName, int userId) { public InstalledModule reloadSingleModule(String packageName, int userId) {
return reloadSingleModule(packageName, userId, false);
}
public InstalledModule reloadSingleModule(String packageName, int userId, boolean packageFullyRemoved) {
if (packageFullyRemoved && isModuleEnabled(packageName))
enabledModules.remove(packageName);
PackageInfo pkg; PackageInfo pkg;
try { try {
@ -115,7 +121,6 @@ public final class ModuleUtil {
} catch (NameNotFoundException e) { } catch (NameNotFoundException e) {
InstalledModule old = installedModules.remove(Pair.create(packageName, userId)); InstalledModule old = installedModules.remove(Pair.create(packageName, userId));
if (old != null) { if (old != null) {
enabledModules.remove(packageName);
for (ModuleListener listener : listeners) { for (ModuleListener listener : listeners) {
listener.onSingleInstalledModuleReloaded(); listener.onSingleInstalledModuleReloaded();
} }

View File

@ -670,7 +670,10 @@ public class ConfigManager {
public boolean removeModule(String packageName) { public boolean removeModule(String packageName) {
if (removeModuleWithoutCache(packageName)) { if (removeModuleWithoutCache(packageName)) {
// called by oneway binder // called by oneway binder
updateCaches(true); // Called only when the application is completely uninstalled
// If it's a module we need to return as soon as possible to broadcast to the manager
// for updating the module status
updateCaches(false);
return true; return true;
} }
return false; return false;

View File

@ -42,6 +42,7 @@ import android.graphics.Canvas;
import android.graphics.drawable.Icon; import android.graphics.drawable.Icon;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.IBinder; import android.os.IBinder;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
@ -59,7 +60,6 @@ import org.lsposed.lspd.ILSPManagerService;
import org.lsposed.lspd.models.Application; import org.lsposed.lspd.models.Application;
import org.lsposed.lspd.models.UserInfo; import org.lsposed.lspd.models.UserInfo;
import org.lsposed.lspd.util.FakeContext; import org.lsposed.lspd.util.FakeContext;
import android.os.Handler;
import org.lsposed.lspd.util.Utils; import org.lsposed.lspd.util.Utils;
import java.io.File; import java.io.File;
@ -253,12 +253,13 @@ public class LSPManagerService extends ILSPManagerService.Stub {
} }
} }
public static void broadcastIntent(String modulePackageName, int moduleUserId) { public static void broadcastIntent(String modulePackageName, int moduleUserId, boolean packageFullyRemoved) {
Intent intent = new Intent(Intent.ACTION_PACKAGE_CHANGED); Intent intent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
intent.addFlags(0x01000000); //Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND intent.addFlags(0x01000000); //Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
intent.addFlags(0x00400000); //Intent.FLAG_RECEIVER_FROM_SHELL intent.addFlags(0x00400000); //Intent.FLAG_RECEIVER_FROM_SHELL
intent.putExtra("android.intent.extra.PACKAGES", modulePackageName); intent.putExtra("android.intent.extra.PACKAGES", modulePackageName);
intent.putExtra(Intent.EXTRA_USER, moduleUserId); intent.putExtra(Intent.EXTRA_USER, moduleUserId);
intent.putExtra(Intent.ACTION_PACKAGE_FULLY_REMOVED, packageFullyRemoved);
intent.setPackage(BuildConfig.MANAGER_INJECTED_PKG_NAME); intent.setPackage(BuildConfig.MANAGER_INJECTED_PKG_NAME);
try { try {
ActivityManagerService.broadcastIntentWithFeature(null, intent, ActivityManagerService.broadcastIntentWithFeature(null, intent,
@ -277,7 +278,7 @@ public class LSPManagerService extends ILSPManagerService.Stub {
public static void createOrUpdateShortcut(boolean force) { public static void createOrUpdateShortcut(boolean force) {
workerHandler.post(()->createOrUpdateShortcutInternal(force)); workerHandler.post(() -> createOrUpdateShortcutInternal(force));
} }
private synchronized static void createOrUpdateShortcutInternal(boolean force) { private synchronized static void createOrUpdateShortcutInternal(boolean force) {

View File

@ -79,9 +79,9 @@ public class LSPosedService extends ILSPosedService.Stub {
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);
if (userId == USER_NULL) userId = uid % PER_USER_RANGE; if (userId == USER_NULL) userId = uid % PER_USER_RANGE;
var configManager = ConfigManager.getInstance();
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.getModule(uid);
ApplicationInfo applicationInfo = null; ApplicationInfo applicationInfo = null;
if (moduleName != null) { if (moduleName != null) {
@ -94,15 +94,13 @@ 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();
Log.d(TAG, "Package changed: uid=" + uid + " userId=" + userId + " action=" + intent.getAction() + " isXposedModule=" + isXposedModule); switch (intentAction) {
switch (intent.getAction()) {
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)
if (ConfigManager.getInstance().removeModule(moduleName)) if (configManager.removeModule(moduleName))
isXposedModule = true; isXposedModule = true;
break; break;
} }
@ -116,10 +114,10 @@ public class LSPosedService extends ILSPosedService.Stub {
} }
// when package is changed, we may need to update cache (module cache or process cache) // when package is changed, we may need to update cache (module cache or process cache)
if (isXposedModule) { if (isXposedModule) {
ConfigManager.getInstance().updateCache(); configManager.updateCache();
} else if (ConfigManager.getInstance().isUidHooked(uid)) { } else if (configManager.isUidHooked(uid)) {
// it will automatically remove obsolete app from database // it will automatically remove obsolete app from database
ConfigManager.getInstance().updateAppCache(); configManager.updateAppCache();
} }
break; break;
} }
@ -128,33 +126,36 @@ public class LSPosedService extends ILSPosedService.Stub {
// (apk may still be there because of multi-user) // (apk may still be there because of multi-user)
if (isXposedModule) { if (isXposedModule) {
// it will automatically remove obsolete scope from database // it will automatically remove obsolete scope from database
ConfigManager.getInstance().updateCache(); configManager.updateCache();
} else if (ConfigManager.getInstance().isUidHooked(uid)) { } else if (configManager.isUidHooked(uid)) {
// it will automatically remove obsolete app from database // it will automatically remove obsolete app from database
ConfigManager.getInstance().updateAppCache(); configManager.updateAppCache();
} }
break; break;
} }
} }
boolean removed = intent.getAction().equals(Intent.ACTION_PACKAGE_FULLY_REMOVED) || boolean removed = intentAction.equals(Intent.ACTION_PACKAGE_FULLY_REMOVED) ||
intent.getAction().equals(Intent.ACTION_UID_REMOVED); intentAction.equals(Intent.ACTION_UID_REMOVED);
Log.d(TAG, "Package changed: uid=" + uid + " userId=" + userId + " action=" + intent.getAction() + " isXposedModule=" + isXposedModule);
if (isXposedModule) { if (isXposedModule) {
Log.d(TAG, "module " + moduleName + " changed, dispatching to manager"); Log.d(TAG, "module " + moduleName + " changed, dispatching to manager");
var enabledModules = ConfigManager.getInstance().enabledModules(); var enabledModules = configManager.enabledModules();
var scope = ConfigManager.getInstance().getModuleScope(moduleName); var scope = configManager.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 (!removed) { if (!removed) {
LSPManagerService.showNotification(moduleName, userId, enabled, systemModule); LSPManagerService.showNotification(moduleName, userId, enabled, systemModule);
} }
LSPManagerService.broadcastIntent(moduleName, userId); LSPManagerService.broadcastIntent(moduleName, userId, intentAction.equals(Intent.ACTION_PACKAGE_FULLY_REMOVED));
} }
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");
try { try {
ConfigManager.getInstance().updateManager(removed); configManager.updateManager(removed);
LSPManagerService.createOrUpdateShortcut(false); LSPManagerService.createOrUpdateShortcut(false);
} catch (Throwable e) { } catch (Throwable e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));