From e3b2731cd348b787d99fb6b02e722084ca706852 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Wed, 17 Feb 2021 02:27:43 +0800 Subject: [PATCH] [core] Bring back package receiver --- .../lsposed/lspd/service/ILSPosedService.aidl | 2 + .../lsposed/lspd/service/BridgeService.java | 18 +- .../lsposed/lspd/service/ConfigManager.java | 7 +- .../lsposed/lspd/service/LSPosedService.java | 29 +++ .../lsposed/lspd/service/PackageReceiver.java | 171 +----------------- 5 files changed, 51 insertions(+), 176 deletions(-) diff --git a/core/src/main/aidl/io/github/lsposed/lspd/service/ILSPosedService.aidl b/core/src/main/aidl/io/github/lsposed/lspd/service/ILSPosedService.aidl index 38983988..13c937fb 100644 --- a/core/src/main/aidl/io/github/lsposed/lspd/service/ILSPosedService.aidl +++ b/core/src/main/aidl/io/github/lsposed/lspd/service/ILSPosedService.aidl @@ -4,4 +4,6 @@ import io.github.lsposed.lspd.service.ILSPApplicationService; interface ILSPosedService { ILSPApplicationService requestApplicationService(int uid, int pid) = 1; + + oneway void dispatchPackageChanged(in Intent intent) = 2; } \ No newline at end of file diff --git a/core/src/main/java/io/github/lsposed/lspd/service/BridgeService.java b/core/src/main/java/io/github/lsposed/lspd/service/BridgeService.java index e5746383..c2f64721 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/BridgeService.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/BridgeService.java @@ -1,5 +1,8 @@ package io.github.lsposed.lspd.service; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.Parcel; @@ -146,7 +149,20 @@ public class BridgeService { } if (serviceBinder == null) { - PackageReceiver.register(); + PackageReceiver.register(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (service == null) { + Log.e(TAG, "Service is dead, missing package changed: " + intent); + return; + } + try { + service.dispatchPackageChanged(intent); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(e)); + } + } + }); } else { serviceBinder.unlinkToDeath(LSPSERVICE_DEATH_RECIPIENT, 0); } diff --git a/core/src/main/java/io/github/lsposed/lspd/service/ConfigManager.java b/core/src/main/java/io/github/lsposed/lspd/service/ConfigManager.java index aa75bb16..8bc8127a 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/ConfigManager.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/ConfigManager.java @@ -4,7 +4,6 @@ import android.content.ContentValues; import android.content.pm.PackageInfo; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteQueryBuilder; import android.database.sqlite.SQLiteStatement; import android.os.FileObserver; import android.os.ParcelFileDescriptor; @@ -188,10 +187,6 @@ public class ConfigManager { // This is called when a new process created, use the cached result // The signature matches Riru's public boolean shouldSkipUid(int uid) { - Log.d(TAG, modulesForUid.keySet().size() + ""); - for (Integer id : modulesForUid.keySet()) { - Log.d(TAG, id.toString()); - } return !modulesForUid.containsKey(uid) && !isManager(uid); } @@ -270,7 +265,7 @@ public class ConfigManager { public String[] enabledModules() { try (Cursor cursor = db.query("modules", new String[]{"package_name"}, "enabled = ?", new String[]{"1"}, null, null, null)) { if (cursor == null) { - Log.e(TAG, "db cache failed"); + Log.e(TAG, "query enabled modules failed"); return null; } int pkg_idx = cursor.getColumnIndex("package_name"); diff --git a/core/src/main/java/io/github/lsposed/lspd/service/LSPosedService.java b/core/src/main/java/io/github/lsposed/lspd/service/LSPosedService.java index 809aa231..e812440c 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/LSPosedService.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/LSPosedService.java @@ -1,6 +1,11 @@ package io.github.lsposed.lspd.service; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Binder; +import android.os.RemoteException; import android.util.Log; import static io.github.lsposed.lspd.service.ServiceManager.TAG; @@ -42,4 +47,28 @@ public class LSPosedService extends ILSPosedService.Stub { return ServiceManager.getApplicationService(); } + + @Override + public void dispatchPackageChanged(Intent intent) throws RemoteException { + if (Binder.getCallingUid() != 1000 || intent == null) return; + Uri uri = intent.getData(); + String packageName = (uri != null) ? uri.getSchemeSpecificPart() : null; + if (packageName == null) { + Log.e(TAG, "Package name is null"); + } + int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); + boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); + if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED) && uid > 0 && !replacing) { + ConfigManager.getInstance().removeModule(packageName); + ConfigManager.getInstance().removeApp(uid); + } + PackageInfo pkgInfo = PackageService.getPackageInfo(packageName, PackageManager.GET_META_DATA, 0); + boolean isXposedModule = pkgInfo != null && pkgInfo.applicationInfo != null && + pkgInfo.applicationInfo.enabled && pkgInfo.applicationInfo.metaData != null && + pkgInfo.applicationInfo.metaData.containsKey("xposedmodule"); + if (isXposedModule) { + ConfigManager.getInstance().updateModuleApkPath(packageName, pkgInfo.applicationInfo.sourceDir); + } + } + } diff --git a/core/src/main/java/io/github/lsposed/lspd/service/PackageReceiver.java b/core/src/main/java/io/github/lsposed/lspd/service/PackageReceiver.java index 0c2cc835..b234a616 100644 --- a/core/src/main/java/io/github/lsposed/lspd/service/PackageReceiver.java +++ b/core/src/main/java/io/github/lsposed/lspd/service/PackageReceiver.java @@ -26,184 +26,17 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.net.Uri; import android.os.Handler; import android.os.HandlerThread; -import android.os.RemoteException; import android.os.UserHandle; -import android.widget.Toast; import io.github.lsposed.lspd.util.Utils; -import java.io.File; -import java.io.PrintWriter; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Scanner; - -import de.robv.android.xposed.XposedHelpers; public class PackageReceiver { - private static final BroadcastReceiver RECEIVER = new BroadcastReceiver() { - - private final String MODULES_LIST_FILENAME = "conf/modules.list"; - private final String ENABLED_MODULES_LIST_FILENAME = "conf/enabled_modules.list"; - private final String MODULE_UPDATED = "io.github.lsposed.action.MODULE_UPDATED"; - private final String MODULE_NOT_ACTIVATAED = "io.github.lsposed.action.MODULE_NOT_ACTIVATAED"; - - private String getPackageName(Intent intent) { - Uri uri = intent.getData(); - return (uri != null) ? uri.getSchemeSpecificPart() : null; - } - - - private boolean isXposedModule(ApplicationInfo app) { - return app != null && app.enabled && app.metaData != null && app.metaData.containsKey("xposedmodule"); - } - - private PackageInfo getPackageInfo(String packageName, int uid) { - try { - return PackageService.getPackageInfo(packageName, PackageManager.GET_META_DATA, uid); - } catch (RemoteException e) { - return null; - } - } - - private Map loadEnabledModules(int uid) { - HashMap result = new HashMap<>(); - // TODO: FIXME -// try { -// File enabledModules = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME); -// if (!enabledModules.exists()) return result; -// Scanner scanner = new Scanner(enabledModules); -// while (scanner.hasNextLine()) { -// String packageName = scanner.nextLine(); -// PackageInfo info = getPackageInfo(packageName, 0); -// if (info != null && isXposedModule(info.applicationInfo)) -// result.put(packageName, info.applicationInfo.sourceDir); -// else if (info == null) -// result.put(packageName, null); -// } -// } catch (Throwable e) { -// Utils.logE("Unable to read enabled modules", e); -// } - return result; - } - - private boolean updateModuleList(int uid, String packageName) { - Map enabledModules = loadEnabledModules(uid); - // TODO: FIXME -// -// if (!enabledModules.containsKey(packageName)) return false; -// -// try { -// File moduleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + MODULES_LIST_FILENAME); -// File enabledModuleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME); -// if (moduleListFile.exists() && !moduleListFile.canWrite()) { -// moduleListFile.delete(); -// moduleListFile.createNewFile(); -// } -// if (enabledModuleListFile.exists() && !enabledModuleListFile.canWrite()) { -// enabledModuleListFile.delete(); -// enabledModuleListFile.createNewFile(); -// } -// PrintWriter modulesList = new PrintWriter(moduleListFile); -// PrintWriter enabledModulesList = new PrintWriter(enabledModuleListFile); -// for (Map.Entry module : enabledModules.entrySet()) { -// String apkPath = module.getValue(); -// if (apkPath != null) { -// modulesList.println(module.getValue()); -// enabledModulesList.println(module.getKey()); -// } else { -// Utils.logI(String.format("remove obsolete package %s", packageName)); -// File prefsDir = new File(ConfigManager.getMiscPath(), uid + "/prefs/" + packageName); -// File[] fileList = prefsDir.listFiles(); -// if (fileList != null) { -// for (File childFile : fileList) { -// childFile.delete(); -// } -// } -// } -// } -// modulesList.close(); -// enabledModulesList.close(); -// } catch (Throwable e) { -// Utils.logE("Fail to update module list", e); -// } - return true; - } - - @SuppressLint("WrongConstant") - @Override - public void onReceive(Context context, Intent intent) { - if (Objects.requireNonNull(intent.getAction()).equals(Intent.ACTION_PACKAGE_REMOVED) && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) - // Ignore existing packages being removed in order to be updated - return; - String packageName = getPackageName(intent); - if (packageName == null) - return; - - if (intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED)) { - // make sure that the change is for the complete package, not only a - // component - String[] components = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST); - if (components != null) { - boolean isForPackage = false; - for (String component : components) { - if (packageName.equals(component)) { - isForPackage = true; - break; - } - } - if (!isForPackage) - return; - } - } - - PackageInfo pkgInfo = getPackageInfo(packageName, intent.getIntExtra(Intent.EXTRA_USER, 0)); - - if (pkgInfo != null && !isXposedModule(pkgInfo.applicationInfo)) return; - // TODO: FIXME -// -// try { -// for (int uid : UserService.getUsers()) { -// Utils.logI("updating uid: " + uid); -// boolean activated = updateModuleList(uid, packageName); -// UserHandle userHandle = null; -// try { -// userHandle = (UserHandle) XposedHelpers.callStaticMethod(UserHandle.class, "of", uid); -// } catch (Throwable t) { -// Utils.logW("get user handle failed", t); -// } -// if (userHandle != null) { -// try { -// Intent broadCast = new Intent(activated ? MODULE_UPDATED : MODULE_NOT_ACTIVATAED); -// broadCast.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | 0x01000000); -// broadCast.setData(intent.getData()); -// broadCast.setPackage(ConfigManager.getInstallerPackageName()); -// XposedHelpers.callMethod(context, "sendBroadcastAsUser", broadCast, userHandle); -// Utils.logI("broadcast to " + ConfigManager.getInstallerPackageName()); -// } catch (Throwable t) { -// Utils.logW("send broadcast failed", t); -// Toast.makeText(context, "LSPosed: Updated " + packageName, Toast.LENGTH_SHORT).show(); -// } -// } else if (activated) { -// Toast.makeText(context, "LSPosed: Updated " + packageName, Toast.LENGTH_SHORT).show(); -// } -// } -// } catch (Throwable e) { -// Utils.logW("update failed", e); -// } - } - }; - - public static void register() { + public static void register(BroadcastReceiver receiver) { ActivityThread activityThread = ActivityThread.currentActivityThread(); if (activityThread == null) { Utils.logW("ActivityThread is null"); @@ -238,7 +71,7 @@ public class PackageReceiver { try { @SuppressLint("DiscouragedPrivateApi") Method method = Context.class.getDeclaredMethod("registerReceiverAsUser", BroadcastReceiver.class, UserHandle.class, IntentFilter.class, String.class, Handler.class); - method.invoke(context, RECEIVER, userHandleAll, intentFilter, null, handler); + method.invoke(context, receiver, userHandleAll, intentFilter, null, handler); Utils.logI("registered package receiver"); } catch (Throwable e) { Utils.logW("registerReceiver failed", e);