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
This commit is contained in:
Fankesyooni 2022-04-22 14:40:03 +08:00 committed by GitHub
parent 90d5afcc1a
commit 44e15da227
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 2 deletions

View File

@ -75,6 +75,7 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -87,11 +88,13 @@ public class LSPManagerService extends ILSPManagerService.Stub {
// this maybe useful when obtaining the manager binder // this maybe useful when obtaining the manager binder
private static String RANDOM_UUID = null; private static String RANDOM_UUID = null;
private static final String SHORTCUT_ID = "org.lsposed.manager.shortcut"; 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_ID = "lsposed";
public static final String CHANNEL_NAME = "LSPosed Manager"; public static final String CHANNEL_NAME = "LSPosed Manager";
public static final int CHANNEL_IMP = NotificationManager.IMPORTANCE_HIGH; public static final int CHANNEL_IMP = NotificationManager.IMPORTANCE_HIGH;
private static final HashMap<String, Integer> notificationIds = new HashMap<>();
private static int previousNotificationId = 2000;
private static final HandlerThread worker = new HandlerThread("manager worker"); private static final HandlerThread worker = new HandlerThread("manager worker");
private static final Handler workerHandler; private static final Handler workerHandler;
private static Intent managerIntent = null; 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, public static void showNotification(String modulePackageName,
int moduleUserId, int moduleUserId,
boolean enabled, boolean enabled,
@ -253,12 +291,27 @@ public class LSPManagerService extends ILSPManagerService.Stub {
new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, CHANNEL_IMP); new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, CHANNEL_IMP);
im.createNotificationChannels("android", im.createNotificationChannels("android",
new android.content.pm.ParceledListSlice<>(Collections.singletonList(channel))); 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) { } catch (Throwable e) {
Log.e(TAG, "post notification", 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") @SuppressLint("WrongConstant")
public static void broadcastIntent(Intent inIntent) { public static void broadcastIntent(Intent inIntent) {
var intent = new Intent("org.lsposed.manager.NOTIFICATION"); var intent = new Intent("org.lsposed.manager.NOTIFICATION");

View File

@ -178,6 +178,8 @@ public class LSPosedService extends ILSPosedService.Stub {
boolean enabled = Arrays.asList(enabledModules).contains(packageName); boolean enabled = Arrays.asList(enabledModules).contains(packageName);
if (!(Intent.ACTION_UID_REMOVED.equals(action) || Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action) || allUsers)) if (!(Intent.ACTION_UID_REMOVED.equals(action) || Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action) || allUsers))
LSPManagerService.showNotification(packageName, userId, enabled, systemModule); 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);
} }
} }

View File

@ -9,6 +9,7 @@ import android.os.RemoteException;
public interface INotificationManager extends IInterface { public interface INotificationManager extends IInterface {
void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id, void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
Notification notification, int userId) throws RemoteException; 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<NotificationChannel> channelsList) throws RemoteException; void createNotificationChannels(String pkg, ParceledListSlice<NotificationChannel> channelsList) throws RemoteException;
abstract class Stub extends Binder implements INotificationManager { abstract class Stub extends Binder implements INotificationManager {