From 645d7cfadf7db5b2bacf64d1005dc0323ac7a234 Mon Sep 17 00:00:00 2001 From: anonymix007 <48598263+anonymix007@users.noreply.github.com> Date: Sun, 16 Jul 2023 06:29:57 +0300 Subject: [PATCH 1/3] Fix Native Hook for modern API modules (#2632) --- core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java b/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java index bcef3f04c..75d392139 100644 --- a/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java +++ b/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java @@ -212,11 +212,11 @@ public String getProcessName() { } } Log.d(TAG, "Loaded module " + module.packageName + ": " + ctx); + module.file.moduleLibraryNames.forEach(NativeAPI::recordNativeEntrypoint); return true; } catch (Throwable e) { Log.d(TAG, "Loading module " + module.packageName, e); } - module.file.moduleLibraryNames.forEach(NativeAPI::recordNativeEntrypoint); return false; } From db8927ac01a79413aaeb14d7dc4525b2c8d43a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E5=AE=AB=E9=9B=AA=E7=8F=8A?= Date: Tue, 18 Jul 2023 14:45:49 +0800 Subject: [PATCH 2/3] Check notification channels only when necessary (#2635) --- .../lspd/service/LSPNotificationManager.java | 135 +++++++++--------- .../lsposed/lspd/service/LSPosedService.java | 80 +++++------ .../org/lsposed/lspd/service/UserService.java | 9 ++ 3 files changed, 110 insertions(+), 114 deletions(-) diff --git a/daemon/src/main/java/org/lsposed/lspd/service/LSPNotificationManager.java b/daemon/src/main/java/org/lsposed/lspd/service/LSPNotificationManager.java index ab913fa16..878837eee 100644 --- a/daemon/src/main/java/org/lsposed/lspd/service/LSPNotificationManager.java +++ b/daemon/src/main/java/org/lsposed/lspd/service/LSPNotificationManager.java @@ -102,7 +102,7 @@ private static boolean hasNotificationChannelForSystem( } 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 @@ static void notifyStatusNotification() { 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 @@ static void notifyModuleUpdated(String modulePackageName, 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) { 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 2d92a1250..5468eaaf9 100644 --- a/daemon/src/main/java/org/lsposed/lspd/service/LSPosedService.java +++ b/daemon/src/main/java/org/lsposed/lspd/service/LSPosedService.java @@ -115,6 +115,7 @@ private void dispatchPackageChanged(Intent intent) { 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 @@ private void dispatchPackageChanged(Intent intent) { 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 @@ private void dispatchPackageChanged(Intent intent) { // 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 @@ private void dispatchBootCompleted(Intent intent) { var configManager = ConfigManager.getInstance(); if (configManager.enableStatusNotification()) { LSPNotificationManager.notifyStatusNotification(); + } else { + LSPNotificationManager.cancelStatusNotification(); } } @@ -238,6 +236,8 @@ private void dispatchConfigurationChanged(Intent intent) { var configManager = ConfigManager.getInstance(); if (configManager.enableStatusNotification()) { LSPNotificationManager.notifyStatusNotification(); + } else { + LSPNotificationManager.cancelStatusNotification(); } } @@ -255,7 +255,10 @@ private void dispatchModuleScope(Intent intent) { 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 @@ private void dispatchModuleScope(Intent intent) { 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 void performReceive(Intent intent, int resultCode, String data, Bundle ex } } - private void registerReceiver(List filters, String requiredPermission, int userId, Consumer task) { - registerReceiver(filters, requiredPermission, userId, task, Context.RECEIVER_NOT_EXPORTED); - } - private void registerReceiver(List filters, int userId, Consumer task) { - registerReceiver(filters, null, userId, task, Context.RECEIVER_NOT_EXPORTED); - } - - private void registerReceiver(List filters, int userId, Consumer 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 @@ private void registerSecretCodeReceiver() { 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 @@ private void registerOpenManagerReceiver() { 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 @@ private void registerModuleScopeReceiver() { 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"); } diff --git a/daemon/src/main/java/org/lsposed/lspd/service/UserService.java b/daemon/src/main/java/org/lsposed/lspd/service/UserService.java index ee98969e0..ce9c40aae 100644 --- a/daemon/src/main/java/org/lsposed/lspd/service/UserService.java +++ b/daemon/src/main/java/org/lsposed/lspd/service/UserService.java @@ -102,6 +102,15 @@ public static UserInfo getUserInfo(int userId) throws RemoteException { 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; From bd7a9b91b265ddb1361052296dd1715598296310 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Wed, 19 Jul 2023 15:46:41 +0800 Subject: [PATCH 3/3] [skip ci] Update CI build link (#2639) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c609e0d6b..01c5fcdf9 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Android 8.1 ~ 13 ## Download - For stable releases, please go to [Github Releases page](https://github.com/LSPosed/LSPosed/releases) -- For canary build, please check [Github Actions](https://github.com/LSPosed/LSPosed/actions) +- For canary build, please check [Github Actions](https://github.com/LSPosed/LSPosed/actions/workflows/core.yml?query=branch%3Amaster) Note: debug builds are only available in Github Actions.