From 44e15da227b4f143042d6d36292b807bf0bcc879 Mon Sep 17 00:00:00 2001 From: Fankesyooni <37344460+fankes@users.noreply.github.com> Date: Fri, 22 Apr 2022 14:40:03 +0800 Subject: [PATCH] Fix the notification push issue after Xposed Module installation or removed (#1882) * Canceled the notification when Xposed Module removed * Fix the packageName confusion notification push problem * Ignore the addition of duplicate ids * Add the packageName into notification tag * Revise the notification id into auto-increment id * Add the conflict ids templates web url * Revise only the package name and userId are reserved for judging the uniqueness of the notification id * Fix code style --- .../lspd/service/LSPManagerService.java | 57 ++++++++++++++++++- .../lsposed/lspd/service/LSPosedService.java | 2 + .../android/app/INotificationManager.java | 1 + 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/daemon/src/main/java/org/lsposed/lspd/service/LSPManagerService.java b/daemon/src/main/java/org/lsposed/lspd/service/LSPManagerService.java index 9c22d3aa..c214856c 100644 --- a/daemon/src/main/java/org/lsposed/lspd/service/LSPManagerService.java +++ b/daemon/src/main/java/org/lsposed/lspd/service/LSPManagerService.java @@ -75,6 +75,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.UUID; @@ -87,11 +88,13 @@ public class LSPManagerService extends ILSPManagerService.Stub { // this maybe useful when obtaining the manager binder private static String RANDOM_UUID = null; private static final String SHORTCUT_ID = "org.lsposed.manager.shortcut"; - public static final int NOTIFICATION_ID = 114514; public static final String CHANNEL_ID = "lsposed"; public static final String CHANNEL_NAME = "LSPosed Manager"; public static final int CHANNEL_IMP = NotificationManager.IMPORTANCE_HIGH; + private static final HashMap notificationIds = new HashMap<>(); + private static int previousNotificationId = 2000; + private static final HandlerThread worker = new HandlerThread("manager worker"); private static final Handler workerHandler; private static Intent managerIntent = null; @@ -220,6 +223,41 @@ public class LSPManagerService extends ILSPManagerService.Stub { } } + private static String getNotificationIdKey(String modulePackageName, int moduleUserId) { + return modulePackageName + ":" + moduleUserId; + } + + private static int getAutoIncrementNotificationId() { + // previousNotificationId start with 2001 + var idValue = previousNotificationId++; + // Templates that may conflict with system ids after 2000 + // Copied from https://android.googlesource.com/platform/frameworks/base/+/master/proto/src/system_messages.proto + var NOTE_NETWORK_AVAILABLE = 17303299; + var NOTE_REMOTE_BUGREPORT = 678432343; + var NOTE_STORAGE_PUBLIC = 0x53505542; + var NOTE_STORAGE_PRIVATE = 0x53505256; + var NOTE_STORAGE_DISK = 0x5344534b; + var NOTE_STORAGE_MOVE = 0x534d4f56; + // If auto created id is conflict, recreate it + if (idValue == NOTE_NETWORK_AVAILABLE || + idValue == NOTE_REMOTE_BUGREPORT || + idValue == NOTE_STORAGE_PUBLIC || + idValue == NOTE_STORAGE_PRIVATE || + idValue == NOTE_STORAGE_DISK || + idValue == NOTE_STORAGE_MOVE) { + return getAutoIncrementNotificationId(); + } else { + return idValue; + } + } + + private static int pushAndGetNotificationId(String modulePackageName, int moduleUserId) { + var idKey = getNotificationIdKey(modulePackageName, moduleUserId); + var idValue = getAutoIncrementNotificationId(); + notificationIds.putIfAbsent(idKey, idValue); + return idValue; + } + public static void showNotification(String modulePackageName, int moduleUserId, boolean enabled, @@ -253,12 +291,27 @@ public class LSPManagerService extends ILSPManagerService.Stub { new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, CHANNEL_IMP); im.createNotificationChannels("android", new android.content.pm.ParceledListSlice<>(Collections.singletonList(channel))); - im.enqueueNotificationWithTag("android", "android", "114514", NOTIFICATION_ID, notification, 0); + im.enqueueNotificationWithTag("android", "android", modulePackageName, + pushAndGetNotificationId(modulePackageName, moduleUserId), + notification, 0); } catch (Throwable e) { Log.e(TAG, "post notification", e); } } + public static void cancelNotification(String modulePackageName, int moduleUserId) { + try { + var idKey = getNotificationIdKey(modulePackageName, moduleUserId); + var notificationId = notificationIds.get(idKey); + if (notificationId == null) return; + var im = INotificationManager.Stub.asInterface(android.os.ServiceManager.getService("notification")); + im.cancelNotificationWithTag("android", "android", modulePackageName, notificationId, 0); + notificationIds.remove(idKey); + } catch (Throwable e) { + Log.e(TAG, "cancel notification", e); + } + } + @SuppressLint("WrongConstant") public static void broadcastIntent(Intent inIntent) { var intent = new Intent("org.lsposed.manager.NOTIFICATION"); diff --git a/daemon/src/main/java/org/lsposed/lspd/service/LSPosedService.java b/daemon/src/main/java/org/lsposed/lspd/service/LSPosedService.java index 4bd32166..1075bcb0 100644 --- a/daemon/src/main/java/org/lsposed/lspd/service/LSPosedService.java +++ b/daemon/src/main/java/org/lsposed/lspd/service/LSPosedService.java @@ -178,6 +178,8 @@ public class LSPosedService extends ILSPosedService.Stub { boolean enabled = Arrays.asList(enabledModules).contains(packageName); if (!(Intent.ACTION_UID_REMOVED.equals(action) || Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action) || allUsers)) LSPManagerService.showNotification(packageName, userId, enabled, systemModule); + // Canceled the notification when Xposed Module removed + if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) LSPManagerService.cancelNotification(packageName, userId); } } diff --git a/hiddenapi/stubs/src/main/java/android/app/INotificationManager.java b/hiddenapi/stubs/src/main/java/android/app/INotificationManager.java index afd47239..191b0b4c 100644 --- a/hiddenapi/stubs/src/main/java/android/app/INotificationManager.java +++ b/hiddenapi/stubs/src/main/java/android/app/INotificationManager.java @@ -9,6 +9,7 @@ import android.os.RemoteException; public interface INotificationManager extends IInterface { void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id, Notification notification, int userId) throws RemoteException; + void cancelNotificationWithTag(String pkg, String opPkg, String tag, int id, int userId) throws RemoteException; void createNotificationChannels(String pkg, ParceledListSlice channelsList) throws RemoteException; abstract class Stub extends Binder implements INotificationManager {