Skip to content

Commit

Permalink
Add more options in the Select menu
Browse files Browse the repository at this point in the history
Allow users to select all/none and automatically include new applications.
Close #93 as completed.

Co-authored-by: mywalk <[email protected]>
  • Loading branch information
JingMatrix and mywalkb committed Dec 4, 2024
1 parent c5ff4c0 commit 1339fc7
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 25 deletions.
19 changes: 19 additions & 0 deletions app/src/main/java/org/lsposed/manager/ConfigManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -390,4 +390,23 @@ public static int getDex2OatWrapperCompatibility() {
return ILSPManagerService.DEX2OAT_CRASHED;
}
}

public static boolean getAutoInclude(String packageName) {
try {
return LSPManagerServiceHolder.getService().getAutoInclude(packageName);
} catch (RemoteException e) {
Log.e(App.TAG, Log.getStackTraceString(e));
return false;
}
}

public static boolean setAutoInclude(String packageName, boolean enable) {
try {
LSPManagerServiceHolder.getService().setAutoInclude(packageName, enable);
return true;
} catch (RemoteException e) {
Log.e(App.TAG, Log.getStackTraceString(e));
return false;
}
}
}
21 changes: 21 additions & 0 deletions app/src/main/java/org/lsposed/manager/adapters/ScopeAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,26 @@ public boolean onOptionsItemSelected(MenuItem item) {
fragment.showHint(R.string.enable_documentui, true);
return false;
}
} else if (itemId == R.id.select_all) {
var tmpChkList = new HashSet<ApplicationWithEquals>(ConfigManager.getModuleScope(module.packageName));
for (AppInfo info : searchList) {
if (info.packageName.equals("android")) {
fragment.showHint(R.string.reboot_required, true, R.string.reboot, v -> ConfigManager.reboot());
}
tmpChkList.add(info.application);
}
ConfigManager.setModuleScope(module.packageName, module.legacy, tmpChkList);
} else if (itemId == R.id.select_none) {
var tmpChkList = new HashSet<ApplicationWithEquals>(ConfigManager.getModuleScope(module.packageName));
for (AppInfo info : searchList) {
if (tmpChkList.remove(info.application) && info.packageName.equals("android")) {
fragment.showHint(R.string.reboot_required, true, R.string.reboot, v -> ConfigManager.reboot());
}
}
ConfigManager.setModuleScope(module.packageName, module.legacy, tmpChkList);
} else if (itemId == R.id.auto_include) {
item.setChecked(!item.isChecked());
ConfigManager.setAutoInclude(module.packageName, item.isChecked());
} else if (!AppHelper.onOptionsItemSelected(item, preferences)) {
return false;
}
Expand Down Expand Up @@ -371,6 +391,7 @@ public void onPrepareOptionsMenu(@NonNull Menu menu) {
}
case 0 -> menu.findItem(R.id.item_sort_by_name).setChecked(true);
}
menu.findItem(R.id.auto_include).setChecked(ConfigManager.getAutoInclude(module.packageName));
}

@Override
Expand Down
24 changes: 18 additions & 6 deletions app/src/main/res/menu/menu_app_list.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,44 @@
android:title="@android:string/search_go" />

<item
android:id="@+id/use_recommended"
android:title="@string/use_recommended" />
android:showAsAction="never"
android:title="@string/menu_select">
<menu>
<item
android:id="@+id/use_recommended"
android:title="@string/use_recommended" />
<item
android:id="@+id/select_all"
android:title="@string/menu_select_all" />
<item
android:id="@+id/select_none"
android:title="@string/menu_select_none" />
<item
android:id="@+id/auto_include"
android:checkable="true"
android:title="@string/menu_auto_include" />
</menu>
</item>

<item
android:showAsAction="never"
android:title="@string/menu_hide">
<menu>

<item
android:id="@+id/item_filter_games"
android:checkable="true"
android:checked="true"
android:title="@string/menu_show_games" />

<item
android:id="@+id/item_filter_modules"
android:checkable="true"
android:checked="true"
android:title="@string/menu_show_modules" />

<item
android:id="@+id/item_filter_system"
android:checkable="true"
android:checked="true"
android:title="@string/menu_show_system_apps" />

<item
android:id="@+id/item_filter_denylist"
android:checkable="true"
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,13 @@
<string name="menu_show_denylist">Denylist</string>
<string name="failed_to_save_scope_list">Failed to save scope list</string>
<string name="app_version">Version: %1$s</string>
<string name="menu_select">Select</string>
<string name="use_recommended">Recommended</string>
<string name="no_scope_selected_has_recommended">You did not select any app. Select recommended apps?</string>
<string name="use_recommended_message">Select recommended apps?</string>
<string name="menu_select_all">All</string>
<string name="menu_select_none">None</string>
<string name="menu_auto_include">Auto-Include</string>
<string name="module_is_not_activated_yet">Xposed module is not activated yet</string>
<string name="requested_by_module">Recommended</string>
<string name="update_available">Update available: %1$s</string>
Expand Down
71 changes: 56 additions & 15 deletions daemon/src/main/java/org/lsposed/lspd/service/ConfigManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import android.content.pm.PackageParser;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteStatement;
import android.os.Build;
import android.os.Bundle;
Expand Down Expand Up @@ -141,7 +142,9 @@ public int hashCode() {
"module_pkg_name text NOT NULL UNIQUE," +
"apk_path text NOT NULL, " +
"enabled BOOLEAN DEFAULT 0 " +
"CHECK (enabled IN (0, 1))" +
"CHECK (enabled IN (0, 1))," +
"auto_include BOOLEAN DEFAULT 0 " +
"CHECK (auto_include IN (0, 1))" +
");");
private final SQLiteStatement createScopeTable = db.compileStatement("CREATE TABLE IF NOT EXISTS scope (" +
"mid integer," +
Expand Down Expand Up @@ -420,6 +423,20 @@ private void initDB() {
db.compileStatement("UPDATE scope SET app_pkg_name = 'system' WHERE app_pkg_name = 'android';").execute();
db.setVersion(3);
});
case 3:
try {
executeInTransaction(() -> {
db.compileStatement("ALTER TABLE modules ADD COLUMN auto_include BOOLEAN DEFAULT 0 CHECK (auto_include IN (0, 1));").execute();
db.setVersion(4);
});
} catch (SQLiteException ex) {
// Fix wrong init code for new column auto_include
if (ex.getMessage().startsWith("duplicate column name: auto_include")) {
db.setVersion(4);
} else {
throw ex;
}
}
default:
break;
}
Expand Down Expand Up @@ -894,20 +911,7 @@ public boolean removeModuleScope(String packageName, String scopePackageName, in


public String[] enabledModules() {
try (Cursor cursor = db.query("modules", new String[]{"module_pkg_name"}, "enabled = 1", null, null, null, null)) {
if (cursor == null) {
Log.e(TAG, "query enabled modules failed");
return null;
}
int modulePkgNameIdx = cursor.getColumnIndex("module_pkg_name");
HashSet<String> result = new HashSet<>();
while (cursor.moveToNext()) {
var pkgName = cursor.getString(modulePkgNameIdx);
if (pkgName.equals("lspd")) continue;
result.add(pkgName);
}
return result.toArray(new String[0]);
}
return listModules("enabled");
}

public boolean removeModule(String packageName) {
Expand Down Expand Up @@ -1223,4 +1227,41 @@ public void exportScopes(ZipOutputStream os) throws IOException {
synchronized SharedMemory getPreloadDex() {
return ConfigFileManager.getPreloadDex(dexObfuscate);
}

public boolean getAutoInclude(String packageName) {
try (Cursor cursor = db.query("modules", new String[]{"auto_include"},
"module_pkg_name = ? and auto_include = 1", new String[]{packageName}, null, null, null, null)) {
return cursor == null || cursor.moveToNext();
}
}

public boolean setAutoInclude(String packageName, boolean enable) {
boolean changed = executeInTransaction(() -> {
ContentValues values = new ContentValues();
values.put("auto_include", enable ? 1 : 0);
return db.update("modules", values, "module_pkg_name = ?", new String[]{packageName}) > 0;
});
return true;
}

public String[] getAutoIncludeModules() {
return listModules("auto_include");
}

private String[] listModules(String column) {
try (Cursor cursor = db.query("modules", new String[]{"module_pkg_name"}, column + " = 1", null, null, null, null)) {
if (cursor == null) {
Log.e(TAG, "query " + column + " modules failed");
return null;
}
int modulePkgNameIdx = cursor.getColumnIndex("module_pkg_name");
HashSet<String> result = new HashSet<>();
while (cursor.moveToNext()) {
var pkgName = cursor.getString(modulePkgNameIdx);
if (pkgName.equals("lspd")) continue;
result.add(pkgName);
}
return result.toArray(new String[0]);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -556,4 +556,14 @@ public void setLogWatchdog(boolean enabled) {
public boolean isLogWatchdogEnabled() {
return ConfigManager.getInstance().isLogWatchdogEnabled();
}

@Override
public boolean setAutoInclude(String packageName, boolean enabled) {
return ConfigManager.getInstance().setAutoInclude(packageName, enabled);
}

@Override
public boolean getAutoInclude(String packageName) {
return ConfigManager.getInstance().getAutoInclude(packageName);
}
}
33 changes: 29 additions & 4 deletions daemon/src/main/java/org/lsposed/lspd/service/LSPosedService.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import android.util.Log;

import org.lsposed.daemon.BuildConfig;
import org.lsposed.lspd.models.Application;

import java.io.IOException;
import java.util.Arrays;
Expand Down Expand Up @@ -151,8 +152,10 @@ private void dispatchPackageChanged(Intent intent) {
if (moduleName != null) {
LSPNotificationManager.cancelNotification(UPDATED_CHANNEL_ID, moduleName, userId);
}
break;
}
case Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_CHANGED -> {
var configManager = ConfigManager.getInstance();
// make sure that the change is for the complete package, not only a
// component
String[] components = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
Expand All @@ -164,10 +167,32 @@ private void dispatchPackageChanged(Intent intent) {
// module to send a broadcast when modules that have not been activated are
// uninstalled.
// 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 auto update obsolete scope from database
ConfigManager.getInstance().updateAppCache();
isXposedModule = configManager.updateModuleApkPath(moduleName, ConfigManager.getInstance().getModuleApkPath(applicationInfo), false);
} else {
if (configManager.isUidHooked(uid)) {
// it will automatically remove obsolete app from database
configManager.updateAppCache();
}
if (intentAction.equals(Intent.ACTION_PACKAGE_ADDED) && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
for (String xposedModule : configManager.getAutoIncludeModules()) {
// For Xposed modules with auto_include set, we always add new applications
// to its scope
var list = configManager.getModuleScope(xposedModule);
if (list != null) {
Application scope = new Application();
scope.packageName = moduleName;
scope.userId = userId;
list.add(scope);
try {
if (!configManager.setModuleScope(xposedModule, list)) {
Log.e(TAG, "failed to set scope for " + xposedModule);
}
} catch(RemoteException re) {
Log.e(TAG, "failed to set scope for " + xposedModule, re);
}
}
}
}
}
broadcastAndShowNotification(moduleName, userId, intent, isXposedModule);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,8 @@ interface ILSPManagerService {
void setLogWatchdog(boolean enable) = 49;

boolean isLogWatchdogEnabled() = 50;

boolean getAutoInclude(String packageName) = 51;

boolean setAutoInclude(String packageName, boolean enable) = 52;
}

0 comments on commit 1339fc7

Please sign in to comment.