Check notification channels only when necessary (#2635)
This commit is contained in:
parent
645d7cfadf
commit
db8927ac01
|
|
@ -102,7 +102,7 @@ public class LSPNotificationManager {
|
|||
} else {
|
||||
channel = nm.getNotificationChannelForPackage("android", 1000, channelId, false);
|
||||
}
|
||||
if(channel != null) {
|
||||
if (channel != null) {
|
||||
Log.d(TAG, "hasNotificationChannelForSystem: " + channel);
|
||||
}
|
||||
return channel != null;
|
||||
|
|
@ -178,6 +178,7 @@ public class LSPNotificationManager {
|
|||
static void cancelStatusNotification() {
|
||||
try {
|
||||
var nm = getNotificationManager();
|
||||
createNotificationChannel(nm);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
nm.cancelNotificationWithTag("android", "android", null, STATUS_NOTIFICATION_ID, 0);
|
||||
} else {
|
||||
|
|
@ -224,89 +225,85 @@ public class LSPNotificationManager {
|
|||
int moduleUserId,
|
||||
boolean enabled,
|
||||
boolean systemModule) {
|
||||
var context = new FakeContext();
|
||||
var userName = UserService.getUserName(moduleUserId);
|
||||
String title = context.getString(enabled ? systemModule ?
|
||||
R.string.xposed_module_updated_notification_title_system :
|
||||
R.string.xposed_module_updated_notification_title :
|
||||
R.string.module_is_not_activated_yet);
|
||||
String content = context.getString(enabled ? systemModule ?
|
||||
R.string.xposed_module_updated_notification_content_system :
|
||||
R.string.xposed_module_updated_notification_content :
|
||||
(moduleUserId == 0 ?
|
||||
R.string.module_is_not_activated_yet_main_user_detailed :
|
||||
R.string.module_is_not_activated_yet_multi_user_detailed), modulePackageName, userName);
|
||||
|
||||
var style = new Notification.BigTextStyle();
|
||||
style.bigText(content);
|
||||
|
||||
var notification = new Notification.Builder(context, UPDATED_CHANNEL_ID)
|
||||
.setContentTitle(title)
|
||||
.setContentText(content)
|
||||
.setSmallIcon(getNotificationIcon())
|
||||
.setContentIntent(getModuleIntent(modulePackageName, moduleUserId))
|
||||
.setVisibility(Notification.VISIBILITY_SECRET)
|
||||
.setColor(0xFFF48FB1)
|
||||
.setAutoCancel(true)
|
||||
.setStyle(style)
|
||||
.build();
|
||||
notification.extras.putString("android.substName", "LSPosed");
|
||||
try {
|
||||
var context = new FakeContext();
|
||||
var userInfo = UserService.getUserInfo(moduleUserId);
|
||||
String userName = userInfo != null ? userInfo.name : String.valueOf(moduleUserId);
|
||||
String title = context.getString(enabled ? systemModule ?
|
||||
R.string.xposed_module_updated_notification_title_system :
|
||||
R.string.xposed_module_updated_notification_title :
|
||||
R.string.module_is_not_activated_yet);
|
||||
String content = context.getString(enabled ? systemModule ?
|
||||
R.string.xposed_module_updated_notification_content_system :
|
||||
R.string.xposed_module_updated_notification_content :
|
||||
(moduleUserId == 0 ?
|
||||
R.string.module_is_not_activated_yet_main_user_detailed :
|
||||
R.string.module_is_not_activated_yet_multi_user_detailed), modulePackageName, userName);
|
||||
|
||||
var style = new Notification.BigTextStyle();
|
||||
style.bigText(content);
|
||||
|
||||
var notification = new Notification.Builder(context, UPDATED_CHANNEL_ID)
|
||||
.setContentTitle(title)
|
||||
.setContentText(content)
|
||||
.setSmallIcon(getNotificationIcon())
|
||||
.setContentIntent(getModuleIntent(modulePackageName, moduleUserId))
|
||||
.setVisibility(Notification.VISIBILITY_SECRET)
|
||||
.setColor(0xFFF48FB1)
|
||||
.setAutoCancel(true)
|
||||
.setStyle(style)
|
||||
.build();
|
||||
notification.extras.putString("android.substName", "LSPosed");
|
||||
var nm = getNotificationManager();
|
||||
createNotificationChannel(nm);
|
||||
nm.enqueueNotificationWithTag("android", opPkg, modulePackageName,
|
||||
pushAndGetNotificationId(UPDATED_CHANNEL_ID, modulePackageName, moduleUserId),
|
||||
notification, 0);
|
||||
} catch (Throwable e) {
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "notify module updated", e);
|
||||
}
|
||||
}
|
||||
|
||||
static void requestModuleScope(String modulePackageName, int moduleUserId, String scopePackageName, IXposedScopeCallback callback) {
|
||||
var context = new FakeContext();
|
||||
var userName = UserService.getUserName(moduleUserId);
|
||||
String title = context.getString(R.string.xposed_module_request_scope_title);
|
||||
String content = context.getString(R.string.xposed_module_request_scope_content, modulePackageName, userName, scopePackageName);
|
||||
|
||||
var style = new Notification.BigTextStyle();
|
||||
style.bigText(content);
|
||||
|
||||
var notification = new Notification.Builder(context, SCOPE_CHANNEL_ID)
|
||||
.setContentTitle(title)
|
||||
.setContentText(content)
|
||||
.setSmallIcon(getNotificationIcon())
|
||||
.setVisibility(Notification.VISIBILITY_SECRET)
|
||||
.setColor(0xFFF48FB1)
|
||||
.setAutoCancel(true)
|
||||
.setTimeoutAfter(1000 * 60 * 60)
|
||||
.setStyle(style)
|
||||
.setDeleteIntent(getModuleScopeIntent(modulePackageName, moduleUserId, scopePackageName, "delete", callback))
|
||||
.setActions(new Notification.Action.Builder(
|
||||
Icon.createWithResource(context, R.drawable.ic_baseline_check_24),
|
||||
context.getString(R.string.scope_approve),
|
||||
getModuleScopeIntent(modulePackageName, moduleUserId, scopePackageName, "approve", callback))
|
||||
.build(),
|
||||
new Notification.Action.Builder(
|
||||
Icon.createWithResource(context, R.drawable.ic_baseline_close_24),
|
||||
context.getString(R.string.scope_deny),
|
||||
getModuleScopeIntent(modulePackageName, moduleUserId, scopePackageName, "deny", callback))
|
||||
.build(),
|
||||
new Notification.Action.Builder(
|
||||
Icon.createWithResource(context, R.drawable.ic_baseline_block_24),
|
||||
context.getString(R.string.nerver_ask_again),
|
||||
getModuleScopeIntent(modulePackageName, moduleUserId, scopePackageName, "block", callback))
|
||||
.build()
|
||||
).build();
|
||||
notification.extras.putString("android.substName", "LSPosed");
|
||||
try {
|
||||
var context = new FakeContext();
|
||||
var userInfo = UserService.getUserInfo(moduleUserId);
|
||||
String userName = userInfo != null ? userInfo.name : String.valueOf(moduleUserId);
|
||||
String title = context.getString(R.string.xposed_module_request_scope_title);
|
||||
String content = context.getString(R.string.xposed_module_request_scope_content, modulePackageName, userName, scopePackageName);
|
||||
|
||||
var style = new Notification.BigTextStyle();
|
||||
style.bigText(content);
|
||||
|
||||
var notification = new Notification.Builder(context, SCOPE_CHANNEL_ID)
|
||||
.setContentTitle(title)
|
||||
.setContentText(content)
|
||||
.setSmallIcon(getNotificationIcon())
|
||||
.setVisibility(Notification.VISIBILITY_SECRET)
|
||||
.setColor(0xFFF48FB1)
|
||||
.setAutoCancel(true)
|
||||
.setTimeoutAfter(1000 * 60 * 60)
|
||||
.setStyle(style)
|
||||
.setDeleteIntent(getModuleScopeIntent(modulePackageName, moduleUserId, scopePackageName, "delete", callback))
|
||||
.setActions(new Notification.Action.Builder(
|
||||
Icon.createWithResource(context, R.drawable.ic_baseline_check_24),
|
||||
context.getString(R.string.scope_approve),
|
||||
getModuleScopeIntent(modulePackageName, moduleUserId, scopePackageName, "approve", callback))
|
||||
.build(),
|
||||
new Notification.Action.Builder(
|
||||
Icon.createWithResource(context, R.drawable.ic_baseline_close_24),
|
||||
context.getString(R.string.scope_deny),
|
||||
getModuleScopeIntent(modulePackageName, moduleUserId, scopePackageName, "deny", callback))
|
||||
.build(),
|
||||
new Notification.Action.Builder(
|
||||
Icon.createWithResource(context, R.drawable.ic_baseline_block_24),
|
||||
context.getString(R.string.nerver_ask_again),
|
||||
getModuleScopeIntent(modulePackageName, moduleUserId, scopePackageName, "block", callback))
|
||||
.build()
|
||||
).build();
|
||||
notification.extras.putString("android.substName", "LSPosed");
|
||||
var nm = getNotificationManager();
|
||||
createNotificationChannel(nm);
|
||||
nm.enqueueNotificationWithTag("android", opPkg, modulePackageName,
|
||||
pushAndGetNotificationId(SCOPE_CHANNEL_ID, modulePackageName, moduleUserId),
|
||||
notification, 0);
|
||||
} catch (Throwable e) {
|
||||
} catch (RemoteException e) {
|
||||
try {
|
||||
callback.onScopeRequestFailed(scopePackageName, e.getMessage());
|
||||
} catch (RemoteException ignored) {
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ public class LSPosedService extends ILSPosedService.Stub {
|
|||
if (uid == AID_NOBODY || uid <= 0) return;
|
||||
int userId = intent.getIntExtra("android.intent.extra.user_handle", USER_NULL);
|
||||
var intentAction = intent.getAction();
|
||||
if (intentAction == null) return;
|
||||
var allUsers = intent.getBooleanExtra(EXTRA_REMOVED_FOR_ALL_USERS, false);
|
||||
if (userId == USER_NULL) userId = uid % PER_USER_RANGE;
|
||||
Uri uri = intent.getData();
|
||||
|
|
@ -132,26 +133,23 @@ public class LSPosedService extends ILSPosedService.Stub {
|
|||
boolean isXposedModule = applicationInfo != null && ((applicationInfo.metaData != null && applicationInfo.metaData.containsKey("xposedminversion")) || isModernModules(applicationInfo));
|
||||
|
||||
switch (intentAction) {
|
||||
case Intent.ACTION_PACKAGE_FULLY_REMOVED: {
|
||||
case Intent.ACTION_PACKAGE_FULLY_REMOVED -> {
|
||||
// for module, remove module
|
||||
// because we only care about when the apk is gone
|
||||
if (moduleName != null && allUsers)
|
||||
if (ConfigManager.getInstance().removeModule(moduleName)) {
|
||||
if (moduleName != null) {
|
||||
if (allUsers && ConfigManager.getInstance().removeModule(moduleName)) {
|
||||
isXposedModule = true;
|
||||
broadcastAndShowNotification(moduleName, userId, intent, true);
|
||||
}
|
||||
if (moduleName != null) {
|
||||
LSPNotificationManager.cancelNotification(UPDATED_CHANNEL_ID, moduleName, userId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Intent.ACTION_PACKAGE_REMOVED:
|
||||
case Intent.ACTION_PACKAGE_REMOVED -> {
|
||||
if (moduleName != null) {
|
||||
LSPNotificationManager.cancelNotification(UPDATED_CHANNEL_ID, moduleName, userId);
|
||||
}
|
||||
break;
|
||||
case Intent.ACTION_PACKAGE_ADDED:
|
||||
case Intent.ACTION_PACKAGE_CHANGED: {
|
||||
}
|
||||
case Intent.ACTION_PACKAGE_ADDED, 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);
|
||||
|
|
@ -165,24 +163,22 @@ public class LSPosedService extends ILSPosedService.Stub {
|
|||
// If cache not updated, assume it's not xposed module
|
||||
isXposedModule = ConfigManager.getInstance().updateModuleApkPath(moduleName, ConfigManager.getInstance().getModuleApkPath(applicationInfo), false);
|
||||
} else if (ConfigManager.getInstance().isUidHooked(uid)) {
|
||||
// it will automatically remove obsolete app from database
|
||||
// it will auto update obsolete scope from database
|
||||
ConfigManager.getInstance().updateAppCache();
|
||||
}
|
||||
broadcastAndShowNotification(moduleName, userId, intent, isXposedModule);
|
||||
break;
|
||||
}
|
||||
case Intent.ACTION_UID_REMOVED: {
|
||||
case Intent.ACTION_UID_REMOVED -> {
|
||||
// when a package is removed (rather than hide) for a single user
|
||||
// (apk may still be there because of multi-user)
|
||||
broadcastAndShowNotification(moduleName, userId, intent, isXposedModule);
|
||||
if (isXposedModule) {
|
||||
// it will automatically remove obsolete scope from database
|
||||
// it will auto remove obsolete app and scope from database
|
||||
ConfigManager.getInstance().updateCache();
|
||||
} else if (ConfigManager.getInstance().isUidHooked(uid)) {
|
||||
// it will automatically remove obsolete app from database
|
||||
// it will auto remove obsolete scope from database
|
||||
ConfigManager.getInstance().updateAppCache();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
boolean removed = Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(intentAction) || Intent.ACTION_UID_REMOVED.equals(intentAction);
|
||||
|
|
@ -230,6 +226,8 @@ public class LSPosedService extends ILSPosedService.Stub {
|
|||
var configManager = ConfigManager.getInstance();
|
||||
if (configManager.enableStatusNotification()) {
|
||||
LSPNotificationManager.notifyStatusNotification();
|
||||
} else {
|
||||
LSPNotificationManager.cancelStatusNotification();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -238,6 +236,8 @@ public class LSPosedService extends ILSPosedService.Stub {
|
|||
var configManager = ConfigManager.getInstance();
|
||||
if (configManager.enableStatusNotification()) {
|
||||
LSPNotificationManager.notifyStatusNotification();
|
||||
} else {
|
||||
LSPNotificationManager.cancelStatusNotification();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -255,7 +255,10 @@ public class LSPosedService extends ILSPosedService.Stub {
|
|||
var extras = intent.getExtras();
|
||||
if (extras == null || data == null) return;
|
||||
var callback = extras.getBinder("callback");
|
||||
var s = data.getEncodedAuthority().split(":", 2);
|
||||
if (callback == null || !callback.isBinderAlive()) return;
|
||||
var authority = data.getEncodedAuthority();
|
||||
if (authority == null) return;
|
||||
var s = authority.split(":", 2);
|
||||
if (s.length != 2) return;
|
||||
var packageName = s[0];
|
||||
int userId;
|
||||
|
|
@ -272,37 +275,29 @@ public class LSPosedService extends ILSPosedService.Stub {
|
|||
|
||||
var iCallback = IXposedScopeCallback.Stub.asInterface(callback);
|
||||
try {
|
||||
ApplicationInfo applicationInfo = null;
|
||||
try {
|
||||
applicationInfo = PackageService.getApplicationInfo(scopePackageName, 0, userId);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
var applicationInfo = PackageService.getApplicationInfo(scopePackageName, 0, userId);
|
||||
if (applicationInfo == null) {
|
||||
iCallback.onScopeRequestFailed(scopePackageName, "Package not found");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case "approve":
|
||||
case "approve" -> {
|
||||
ConfigManager.getInstance().setModuleScope(packageName, scopePackageName, userId);
|
||||
iCallback.onScopeRequestApproved(scopePackageName);
|
||||
break;
|
||||
case "deny":
|
||||
iCallback.onScopeRequestDenied(scopePackageName);
|
||||
break;
|
||||
case "delete":
|
||||
iCallback.onScopeRequestTimeout(scopePackageName);
|
||||
break;
|
||||
case "block":
|
||||
}
|
||||
case "deny" -> iCallback.onScopeRequestDenied(scopePackageName);
|
||||
case "delete" -> iCallback.onScopeRequestTimeout(scopePackageName);
|
||||
case "block" -> {
|
||||
ConfigManager.getInstance().blockScopeRequest(packageName);
|
||||
iCallback.onScopeRequestDenied(scopePackageName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Log.i(TAG, action + " scope " + scopePackageName + " for " + packageName + " in user " + userId);
|
||||
} catch (Throwable e) {
|
||||
} catch (RemoteException e) {
|
||||
try {
|
||||
iCallback.onScopeRequestFailed(scopePackageName, e.getMessage());
|
||||
} catch (Throwable ignored) {
|
||||
} catch (RemoteException ignored) {
|
||||
// callback died
|
||||
}
|
||||
}
|
||||
|
|
@ -337,16 +332,9 @@ public class LSPosedService extends ILSPosedService.Stub {
|
|||
}
|
||||
}
|
||||
|
||||
private void registerReceiver(List<IntentFilter> filters, String requiredPermission, int userId, Consumer<Intent> task) {
|
||||
registerReceiver(filters, requiredPermission, userId, task, Context.RECEIVER_NOT_EXPORTED);
|
||||
}
|
||||
|
||||
private void registerReceiver(List<IntentFilter> filters, int userId, Consumer<Intent> task) {
|
||||
registerReceiver(filters, null, userId, task, Context.RECEIVER_NOT_EXPORTED);
|
||||
}
|
||||
|
||||
private void registerReceiver(List<IntentFilter> filters, int userId, Consumer<Intent> task, int flag) {
|
||||
registerReceiver(filters, null, userId, task, flag);
|
||||
//noinspection InlinedApi
|
||||
registerReceiver(filters, "android.permission.BRICK", userId, task, Context.RECEIVER_NOT_EXPORTED);
|
||||
}
|
||||
|
||||
private void registerPackageReceiver() {
|
||||
|
|
@ -380,7 +368,9 @@ public class LSPosedService extends ILSPosedService.Stub {
|
|||
intentFilter.addDataAuthority("5776733", null);
|
||||
intentFilter.addDataScheme("android_secret_code");
|
||||
|
||||
registerReceiver(List.of(intentFilter), 0, this::dispatchSecretCodeReceive, Context.RECEIVER_EXPORTED);
|
||||
//noinspection InlinedApi
|
||||
registerReceiver(List.of(intentFilter), "android.permission.CONTROL_INCALL_EXPERIENCE",
|
||||
0, this::dispatchSecretCodeReceive, Context.RECEIVER_EXPORTED);
|
||||
Log.d(TAG, "registered secret code receiver");
|
||||
}
|
||||
|
||||
|
|
@ -405,7 +395,7 @@ public class LSPosedService extends ILSPosedService.Stub {
|
|||
var moduleFilter = new IntentFilter(intentFilter);
|
||||
moduleFilter.addDataScheme("module");
|
||||
|
||||
registerReceiver(List.of(intentFilter, moduleFilter), "android.permission.BRICK", 0, this::dispatchOpenManager);
|
||||
registerReceiver(List.of(intentFilter, moduleFilter), 0, this::dispatchOpenManager);
|
||||
Log.d(TAG, "registered open manager receiver");
|
||||
}
|
||||
|
||||
|
|
@ -413,7 +403,7 @@ public class LSPosedService extends ILSPosedService.Stub {
|
|||
var intentFilter = new IntentFilter(LSPNotificationManager.moduleScope);
|
||||
intentFilter.addDataScheme("module");
|
||||
|
||||
registerReceiver(List.of(intentFilter), "android.permission.BRICK", 0, this::dispatchModuleScope);
|
||||
registerReceiver(List.of(intentFilter), 0, this::dispatchModuleScope);
|
||||
Log.d(TAG, "registered module scope receiver");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,6 +102,15 @@ public class UserService {
|
|||
return um.getUserInfo(userId);
|
||||
}
|
||||
|
||||
public static String getUserName(int userId) {
|
||||
try {
|
||||
var userInfo = getUserInfo(userId);
|
||||
if (userInfo != null) return userInfo.name;
|
||||
} catch (RemoteException ignored) {
|
||||
}
|
||||
return String.valueOf(userId);
|
||||
}
|
||||
|
||||
public static int getProfileParent(int userId) throws RemoteException {
|
||||
IUserManager um = getUserManager();
|
||||
if (um == null) return -1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue