[app] Refactored to use binder

This commit is contained in:
tehcneko 2021-02-17 16:16:16 +08:00
parent 9913da0b24
commit 1dd04b6f31
16 changed files with 500 additions and 295 deletions

View File

@ -143,8 +143,8 @@ dependencies {
implementation 'me.zhanghai.android.appiconloader:appiconloader-glide:1.2.0'
implementation 'me.zhanghai.android.fastscroll:library:1.1.5'
implementation files('libs/WeatherView-2.0.3.aar')
compileOnly project(":hiddenapi-stubs")
implementation project(':manager-service')
compileOnly project(":hiddenapi-stubs")
}
configurations {

View File

@ -42,8 +42,6 @@ import okhttp3.Cache;
import okhttp3.OkHttpClient;
import rikka.material.app.DayNightDelegate;
import static io.github.lsposed.manager.receivers.LSPosedManagerServiceClient.testBinder;
public class App extends Application {
public static final String TAG = "LSPosedManager";
@SuppressLint("StaticFieldLeak")
@ -63,7 +61,6 @@ public class App extends Application {
public void onCreate() {
super.onCreate();
testBinder();
if (!BuildConfig.DEBUG) {
try {
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {

View File

@ -0,0 +1,225 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2021 LSPosed Contributors
*/
package io.github.lsposed.manager;
import android.content.pm.PackageInfo;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import java.util.ArrayList;
import java.util.List;
import io.github.lsposed.manager.receivers.LSPosedManagerServiceClient;
public class ConfigManager {
public static int getXposedApiVersion() {
try {
return LSPosedManagerServiceClient.getXposedApiVersion();
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return -1;
}
}
public static String getXposedVersionName() {
try {
return LSPosedManagerServiceClient.getXposedVersionName();
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return null;
}
}
public static int getXposedVersionCode() {
try {
return LSPosedManagerServiceClient.getXposedVersionCode();
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return -1;
}
}
public static List<PackageInfo> getInstalledPackagesFromAllUsers(int flags) {
List<PackageInfo> list = new ArrayList<>();
try {
list.addAll(LSPosedManagerServiceClient.getInstalledPackagesFromAllUsers(flags));
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
}
return list;
}
public static String[] getEnabledModules() {
try {
return LSPosedManagerServiceClient.enabledModules();
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return new String[0];
}
}
public static boolean setModuleEnabled(String packageName, boolean enable) {
try {
return enable ? LSPosedManagerServiceClient.enableModule(packageName) : LSPosedManagerServiceClient.disableModule(packageName);
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return false;
}
}
public static boolean setModuleScope(String packageName, List<Integer> uidList) {
try {
int[] uids = new int[uidList.size()];
for (int i = 0; i < uidList.size(); i++) {
uids[i] = uidList.get(i);
}
return LSPosedManagerServiceClient.setModuleScope(packageName, uids);
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return false;
}
}
public static List<Integer> getModuleScope(String packageName) {
List<Integer> list = new ArrayList<>();
try {
for (int uid : LSPosedManagerServiceClient.getModuleScope(packageName)) {
list.add(uid);
}
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
}
return list;
}
public static boolean isResourceHookEnabled() {
try {
return LSPosedManagerServiceClient.isResourceHook();
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return false;
}
}
public static boolean setResourceHookEnabled(boolean enabled) {
try {
LSPosedManagerServiceClient.setResourceHook(enabled);
return true;
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return false;
}
}
public static boolean isVerboseLogEnabled() {
try {
return LSPosedManagerServiceClient.isVerboseLog();
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return false;
}
}
public static boolean setVerboseLogEnabled(boolean enabled) {
try {
LSPosedManagerServiceClient.setVerboseLog(enabled);
return true;
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return false;
}
}
public static int getVariant() {
try {
return LSPosedManagerServiceClient.getVariant();
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return 1;
}
}
public static String getVariantString() {
int variant = getVariant();
switch (variant) {
case 1:
return "YAHFA";
case 2:
return "SandHook";
default:
return "Unknown";
}
}
public static boolean setVariant(int variant) {
try {
LSPosedManagerServiceClient.setVariant(variant);
return true;
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return false;
}
}
public static boolean isPermissive() {
try {
return LSPosedManagerServiceClient.isPermissive();
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return true;
}
}
public static ParcelFileDescriptor getVerboseLog() {
try {
return LSPosedManagerServiceClient.getVerboseLog();
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return null;
}
}
public static ParcelFileDescriptor getModulesLog() {
try {
return LSPosedManagerServiceClient.getModulesLog();
} catch (RemoteException | NullPointerException e) {
// TODO:
e.printStackTrace();
return null;
}
}
}

View File

@ -22,61 +22,13 @@ package io.github.lsposed.manager;
import android.widget.Toast;
@SuppressWarnings({"FieldCanBeLocal", "FieldMayBeFinal", "unused"})
public class Constants {
private static int xposedApiVersion = -1;
private static String xposedVersion = null;
private static int xposedVersionCode = -1;
private static String xposedVariant = null;
private static String baseDir = null;
private static String logDir = null;
private static String miscDir = null;
private static boolean permissive = true;
public static int getXposedApiVersion() {
return xposedApiVersion;
}
public static String getXposedVersion() {
return xposedVersion;
}
public static int getXposedVersionCode() {
return xposedVersionCode;
}
public static String getXposedVariant() {
return xposedVariant;
}
public static String getEnabledModulesListFile() {
return getBaseDir() + "conf/enabled_modules.list";
}
public static String getModulesListFile() {
return getBaseDir() + "conf/modules.list";
}
public static String getConfDir() {
return getBaseDir() + "conf/";
}
public static String getBaseDir() {
return baseDir;
}
private static final String logDir = null;
public static String getLogDir() {
return logDir;
}
public static String getMiscDir() {
return miscDir;
}
public static boolean isPermissive() {
return permissive;
}
public static void showErrorToast(int type) {
Toast.makeText(App.getInstance(), R.string.app_destroyed, Toast.LENGTH_LONG).show();
}

View File

@ -28,26 +28,15 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.view.MenuItem;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import io.github.lsposed.manager.Constants;
import io.github.lsposed.manager.R;
public class AppHelper {
public static final String SETTINGS_CATEGORY = "de.robv.android.xposed.category.MODULE_SETTINGS";
private static final String BASE_PATH = Constants.getBaseDir();
private static final String SCOPE_LIST_PATH = "conf/%s.conf";
private static final HashMap<String, List<String>> scopeList = new HashMap<>();
public static Intent getSettingsIntent(String packageName, PackageManager packageManager) {
// taken from
@ -124,52 +113,4 @@ public class AppHelper {
return (PackageInfo a, PackageInfo b) -> displayNameComparator.compare(a.applicationInfo, b.applicationInfo);
}
}
public static List<String> getEnabledModuleList() {
Path path = Paths.get(Constants.getEnabledModulesListFile());
List<String> s = new ArrayList<>();
try {
s = Files.readAllLines(path);
} catch (IOException e) {
e.printStackTrace();
}
return s;
}
public static List<String> getScopeList(String modulePackageName) {
if (scopeList.containsKey(modulePackageName)) {
return scopeList.get(modulePackageName);
}
Path path = Paths.get(BASE_PATH + String.format(SCOPE_LIST_PATH, modulePackageName));
List<String> s = new ArrayList<>();
try {
s = Files.readAllLines(path);
scopeList.put(modulePackageName, s);
} catch (IOException e) {
e.printStackTrace();
}
return s;
}
public static boolean saveScopeList(String modulePackageName, List<String> list) {
Path path = Paths.get(BASE_PATH + String.format(SCOPE_LIST_PATH, modulePackageName));
if (list.size() == 0) {
scopeList.put(modulePackageName, list);
try {
Files.delete(path);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
try {
Files.write(path, list);
} catch (IOException e) {
e.printStackTrace();
return false;
}
scopeList.put(modulePackageName, list);
return true;
}
}

View File

@ -20,6 +20,7 @@
package io.github.lsposed.manager.adapters;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
@ -61,13 +62,15 @@ import com.google.android.material.snackbar.Snackbar;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import io.github.lsposed.manager.App;
import io.github.lsposed.manager.BuildConfig;
import io.github.lsposed.manager.ConfigManager;
import io.github.lsposed.manager.R;
import io.github.lsposed.manager.ui.activity.AppListActivity;
import io.github.lsposed.manager.ui.fragment.CompileDialogFragment;
@ -78,6 +81,7 @@ import rikka.widget.switchbar.SwitchBar;
import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS;
@SuppressLint("NotifyDataSetChanged")
public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder> implements Filterable {
private final AppListActivity activity;
@ -86,9 +90,12 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
private final String modulePackageName;
private final String moduleName;
private final SwitchBar masterSwitch;
private List<PackageInfo> fullList, showList;
private List<String> checkedList;
private final List<String> recommendedList;
private final List<Integer> moduleList = new ArrayList<>();
private final List<Integer> recommendedList = new ArrayList<>();
private final List<PackageInfo> searchList = new ArrayList<>();
private final Map<Integer, ArrayList<PackageInfo>> sharedUidMap = new HashMap<>();
private List<PackageInfo> showList = new ArrayList<>();
private List<Integer> checkedList = new ArrayList<>();
private boolean enabled = true;
private ApplicationInfo selectedInfo;
@ -98,17 +105,15 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
this.modulePackageName = modulePackageName;
this.masterSwitch = masterSwitch;
preferences = App.getPreferences();
fullList = showList = Collections.emptyList();
checkedList = Collections.emptyList();
pm = activity.getPackageManager();
masterSwitch.setOnCheckedChangeListener((view, isChecked) -> {
if (!ModuleUtil.getInstance().setModuleEnabled(modulePackageName, isChecked)) {
return false;
}
enabled = isChecked;
ModuleUtil.getInstance().setModuleEnabled(modulePackageName, enabled);
notifyDataSetChanged();
return true;
});
ModuleUtil.InstalledModule module = ModuleUtil.getInstance().getModule(modulePackageName);
recommendedList = module.getScopeList();
refresh();
}
@ -120,54 +125,79 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
}
private void loadApps() {
List<PackageInfo> appList = ConfigManager.getInstalledPackagesFromAllUsers(PackageManager.GET_META_DATA);
checkedList = ConfigManager.getModuleScope(modulePackageName);
moduleList.clear();
recommendedList.clear();
searchList.clear();
showList.clear();
enabled = ModuleUtil.getInstance().isModuleEnabled(modulePackageName);
activity.runOnUiThread(() -> masterSwitch.setChecked(enabled));
checkedList = AppHelper.getScopeList(modulePackageName);
if (checkedList.isEmpty() && hasRecommended()) {
checkRecommended();
}
fullList = pm.getInstalledPackages(PackageManager.GET_META_DATA);
List<String> installedList = new ArrayList<>();
List<PackageInfo> rmList = new ArrayList<>();
for (PackageInfo info : fullList) {
installedList.add(info.packageName);
if (info.packageName.equals(BuildConfig.APPLICATION_ID) || info.packageName.equals(this.modulePackageName)) {
rmList.add(info);
ArrayList<PackageInfo> removeList = new ArrayList<>();
ArrayList<Integer> installedList = new ArrayList<>();
List<String> recommendedPackageNames = ModuleUtil.getInstance().getModule(modulePackageName).getScopeList();
for (PackageInfo info : appList) {
int uid = info.applicationInfo.uid;
if (!installedList.contains(uid)) installedList.add(uid);
List<PackageInfo> sharedUidList = sharedUidMap.computeIfAbsent(uid, k -> new ArrayList<>());
if (!sharedUidList.contains(info)) sharedUidList.add(info);
if (info.packageName.equals(this.modulePackageName)) {
if (!checkedList.contains(uid)) checkedList.add(uid);
if (!moduleList.contains(uid)) moduleList.add(uid);
removeList.add(info);
continue;
}
if (checkedList.contains(info.packageName) || info.packageName.equals("android")) {
if (recommendedPackageNames != null && recommendedPackageNames.contains(info.packageName) && !recommendedList.contains(uid)) {
recommendedList.add(uid);
continue;
}
if (info.packageName.equals(BuildConfig.APPLICATION_ID)) {
removeList.add(info);
continue;
}
if (checkedList.contains(uid) || info.packageName.equals("android")) {
continue;
}
if (!preferences.getBoolean("show_modules", false)) {
if (info.applicationInfo.metaData != null && info.applicationInfo.metaData.containsKey("xposedmodule")) {
rmList.add(info);
removeList.add(info);
continue;
}
}
if (!preferences.getBoolean("show_games", false)) {
if (info.applicationInfo.category == ApplicationInfo.CATEGORY_GAME) {
rmList.add(info);
removeList.add(info);
continue;
}
//noinspection deprecation
if ((info.applicationInfo.flags & ApplicationInfo.FLAG_IS_GAME) != 0) {
rmList.add(info);
removeList.add(info);
continue;
}
}
if ((info.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) == 0) {
rmList.add(info);
removeList.add(info);
continue;
}
if (!preferences.getBoolean("show_system_apps", false) && (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
rmList.add(info);
removeList.add(info);
}
}
checkedList.retainAll(installedList);
if (rmList.size() > 0) {
fullList.removeAll(rmList);
if (selectedNothing() && hasRecommended()) {
checkRecommended();
}
showList = sortApps(fullList);
searchList.addAll(appList);
if (removeList.size() > 0) {
searchList.removeAll(removeList);
}
showList = sortApps(searchList);
activity.onDataReady();
}
@ -183,8 +213,8 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
}
};
Comparator<PackageInfo> recommendedComparator = (a, b) -> {
boolean aRecommended = hasRecommended() && recommendedList.contains(a.packageName);
boolean bRecommended = hasRecommended() && recommendedList.contains(b.packageName);
boolean aRecommended = hasRecommended() && recommendedList.contains(a.applicationInfo.uid);
boolean bRecommended = hasRecommended() && recommendedList.contains(b.applicationInfo.uid);
if (aRecommended == bRecommended) {
return frameworkComparator.compare(a, b);
} else if (aRecommended) {
@ -194,8 +224,8 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
}
};
list.sort((a, b) -> {
boolean aChecked = checkedList.contains(a.packageName);
boolean bChecked = checkedList.contains(b.packageName);
boolean aChecked = checkedList.contains(a.applicationInfo.uid);
boolean bChecked = checkedList.contains(b.applicationInfo.uid);
if (aChecked == bChecked) {
return recommendedComparator.compare(a, b);
} else if (aChecked) {
@ -208,14 +238,12 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
}
private void checkRecommended() {
checkedList.clear();
checkedList.addAll(recommendedList);
AppHelper.saveScopeList(modulePackageName, checkedList);
notifyDataSetChanged();
ConfigManager.setModuleScope(modulePackageName, checkedList);
}
private boolean hasRecommended() {
return recommendedList != null && !recommendedList.isEmpty();
return !recommendedList.isEmpty();
}
public boolean onOptionsItemSelected(MenuItem item) {
@ -225,11 +253,15 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
new AlertDialog.Builder(activity)
.setTitle(R.string.use_recommended)
.setMessage(R.string.use_recommended_message)
.setPositiveButton(android.R.string.ok, (dialog, which) -> checkRecommended())
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
checkRecommended();
notifyDataSetChanged();
})
.setNegativeButton(android.R.string.cancel, null)
.show();
} else {
checkRecommended();
notifyDataSetChanged();
}
return true;
} else if (itemId == R.id.item_show_system) {
@ -359,7 +391,7 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
});
SpannableStringBuilder sb = new SpannableStringBuilder(android ? "" : activity.getString(R.string.app_description, info.packageName, info.versionName));
holder.appDescription.setVisibility(View.VISIBLE);
if (hasRecommended() && recommendedList.contains(info.packageName)) {
if (hasRecommended() && recommendedList.contains(info.applicationInfo.uid)) {
if (!android) sb.append("\n");
String recommended = activity.getString(R.string.requested_by_module);
sb.append(recommended);
@ -390,9 +422,9 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
});
holder.checkbox.setOnCheckedChangeListener(null);
holder.checkbox.setChecked(checkedList.contains(info.packageName));
holder.checkbox.setChecked(checkedList.contains(info.applicationInfo.uid));
holder.checkbox.setOnCheckedChangeListener((v, isChecked) -> onCheckedChange(v, isChecked, info.packageName));
holder.checkbox.setOnCheckedChangeListener((v, isChecked) -> onCheckedChange(v, isChecked, info.applicationInfo.uid));
holder.itemView.setOnClickListener(v -> {
if (enabled) holder.checkbox.toggle();
});
@ -421,20 +453,27 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
AsyncTask.THREAD_POOL_EXECUTOR.execute(this::loadApps);
}
protected void onCheckedChange(CompoundButton buttonView, boolean isChecked, String packageName) {
protected void onCheckedChange(CompoundButton buttonView, boolean isChecked, int uid) {
if (isChecked) {
checkedList.add(packageName);
checkedList.add(uid);
} else {
checkedList.remove(packageName);
checkedList.remove((Integer) uid);
}
if (!AppHelper.saveScopeList(modulePackageName, checkedList)) {
if (!ConfigManager.setModuleScope(modulePackageName, checkedList)) {
activity.makeSnackBar(R.string.failed_to_save_scope_list, Snackbar.LENGTH_SHORT);
if (!isChecked) {
checkedList.add(packageName);
checkedList.add(uid);
} else {
checkedList.remove(packageName);
checkedList.remove((Integer) uid);
}
buttonView.setChecked(!isChecked);
} else {
List<PackageInfo> sharedUidList = sharedUidMap.get(uid);
if (sharedUidList != null) {
for (PackageInfo info : sharedUidList) {
notifyItemChanged(showList.indexOf(info));
}
}
}
}
@ -466,11 +505,11 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
@Override
protected FilterResults performFiltering(CharSequence constraint) {
if (constraint.toString().isEmpty()) {
showList = fullList;
showList = searchList;
} else {
ArrayList<PackageInfo> filtered = new ArrayList<>();
String filter = constraint.toString().toLowerCase();
for (PackageInfo info : fullList) {
for (PackageInfo info : searchList) {
if (lowercaseContains(getAppLabel(info.applicationInfo, pm), filter)
|| lowercaseContains(info.packageName, filter)) {
filtered.add(info);
@ -487,13 +526,22 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
}
}
private boolean selectedNothing() {
List<Integer> list = new ArrayList<>(checkedList);
list.removeAll(moduleList);
return list.isEmpty();
}
public boolean onBackPressed() {
if (masterSwitch.isChecked() && checkedList.isEmpty()) {
if (masterSwitch.isChecked() && selectedNothing()) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.use_recommended);
builder.setMessage(hasRecommended() ? R.string.no_scope_selected_has_recommended : R.string.no_scope_selected);
if (hasRecommended()) {
builder.setPositiveButton(android.R.string.ok, (dialog, which) -> checkRecommended());
builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
checkRecommended();
notifyDataSetChanged();
});
} else {
builder.setPositiveButton(android.R.string.cancel, null);
}

View File

@ -2,40 +2,148 @@ package io.github.lsposed.manager.receivers;
import android.content.pm.PackageInfo;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
import java.util.List;
import io.github.lsposed.lspd.ILSPManagerService;
import io.github.lsposed.manager.App;
import io.github.lsposed.lspd.utils.ParceledListSlice;
public class LSPosedManagerServiceClient {
@SuppressWarnings("FieldMayBeFinal")
private static IBinder binder = null;
private static ILSPManagerService service = null;
public static void testBinder() {
if (service == null && binder != null) {
service = ILSPManagerService.Stub.asInterface(binder);
}
if (service == null) {
return;
}
int ver = -1;
try {
ver = service.getVersion();
} catch (RemoteException e) {
e.printStackTrace();
}
Log.i(App.TAG, "Got version " + ver);
/*
public static void testBinder() {
if (binder == null) {
}
if (service == null && binder != null) {
service = ILSPManagerService.Stub.asInterface(binder);
}
if (service == null) {
return;
}
int ver = -1;
try {
ver = service.getVersion();
} catch (RemoteException e) {
e.printStackTrace();
}
Log.i(App.TAG, "Got version " + ver);
List<PackageInfo> ps = null;
try {
ps = service.getInstalledPackagesFromAllUsers(0).getList();
} catch (RemoteException e) {
e.printStackTrace();
List<PackageInfo> ps = null;
try {
ps = service.getInstalledPackagesFromAllUsers(0).getList();
} catch (RemoteException e) {
e.printStackTrace();
}
Log.i(App.TAG, String.valueOf(ps));
}
Log.i(App.TAG, String.valueOf(ps));
*/
private static void ensureService() throws NullPointerException {
if (service == null) {
if (binder != null) {
service = ILSPManagerService.Stub.asInterface(binder);
} else {
throw new NullPointerException("binder is null");
}
}
}
public static int getXposedApiVersion() throws RemoteException, NullPointerException {
ensureService();
return service.getXposedApiVersion();
}
public static String getXposedVersionName() throws RemoteException, NullPointerException {
ensureService();
return service.getXposedVersionName();
}
public static int getXposedVersionCode() throws RemoteException, NullPointerException {
ensureService();
return service.getXposedVersionCode();
}
public static List<PackageInfo> getInstalledPackagesFromAllUsers(int flags) throws RemoteException, NullPointerException {
ensureService();
ParceledListSlice<PackageInfo> parceledListSlice = service.getInstalledPackagesFromAllUsers(flags);
//
return parceledListSlice.getList();
}
public static String[] enabledModules() throws RemoteException, NullPointerException {
ensureService();
return service.enabledModules();
}
public static boolean enableModule(String packageName) throws RemoteException, NullPointerException {
ensureService();
return service.enableModule(packageName);
}
public static boolean disableModule(String packageName) throws RemoteException, NullPointerException {
ensureService();
return service.disableModule(packageName);
}
public static boolean setModuleScope(String packageName, int[] uid) throws RemoteException, NullPointerException {
ensureService();
return service.setModuleScope(packageName, uid);
}
public static int[] getModuleScope(String packageName) throws RemoteException, NullPointerException {
ensureService();
return service.getModuleScope(packageName);
}
public static boolean isResourceHook() throws RemoteException, NullPointerException {
ensureService();
return service.isResourceHook();
}
public static void setResourceHook(boolean enabled) throws RemoteException, NullPointerException {
ensureService();
service.setResourceHook(enabled);
}
public static boolean isVerboseLog() throws RemoteException, NullPointerException {
ensureService();
return service.isVerboseLog();
}
public static void setVerboseLog(boolean enabled) throws RemoteException, NullPointerException {
ensureService();
service.setVerboseLog(enabled);
}
public static int getVariant() throws RemoteException, NullPointerException {
ensureService();
return service.getVariant();
}
public static void setVariant(int variant) throws RemoteException, NullPointerException {
ensureService();
service.setVariant(variant);
}
public static boolean isPermissive() throws RemoteException, NullPointerException {
ensureService();
return service.isPermissive();
}
public static ParcelFileDescriptor getVerboseLog() throws RemoteException, NullPointerException {
ensureService();
return service.getVerboseLog();
}
public static ParcelFileDescriptor getModulesLog() throws RemoteException, NullPointerException {
ensureService();
return service.getModulesLog();
}
}

View File

@ -56,6 +56,7 @@ import java.util.Calendar;
import java.util.List;
import io.github.lsposed.manager.BuildConfig;
import io.github.lsposed.manager.ConfigManager;
import io.github.lsposed.manager.Constants;
import io.github.lsposed.manager.R;
import io.github.lsposed.manager.databinding.ActivityLogsBinding;
@ -115,14 +116,10 @@ public class LogsActivity extends BaseActivity {
binding.recyclerView.setAdapter(adapter);
layoutManager = new LinearLayoutManagerFix(this);
binding.recyclerView.setLayoutManager(layoutManager);
try {
if (Files.readAllBytes(Paths.get(Constants.getMiscDir(), "disable_verbose_log"))[0] == 49) {
binding.slidingTabs.setVisibility(View.GONE);
} else {
RecyclerViewKt.addVerticalPadding(binding.recyclerView, 48, 0);
}
} catch (Exception e) {
if (!ConfigManager.isVerboseLogEnabled()) {
binding.slidingTabs.setVisibility(View.GONE);
} else {
RecyclerViewKt.addVerticalPadding(binding.recyclerView, 48, 0);
}
binding.slidingTabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override

View File

@ -35,7 +35,7 @@ import com.google.android.material.snackbar.Snackbar;
import java.util.Locale;
import io.github.lsposed.manager.Constants;
import io.github.lsposed.manager.ConfigManager;
import io.github.lsposed.manager.R;
import io.github.lsposed.manager.databinding.ActivityMainBinding;
import io.github.lsposed.manager.databinding.DialogAboutBinding;
@ -59,7 +59,7 @@ public class MainActivity extends BaseActivity {
setContentView(binding.getRoot());
HolidayHelper.setup(this);
binding.status.setOnClickListener(v -> {
if (Constants.getXposedVersionCode() != -1) {
if (ConfigManager.getXposedApiVersion() != -1) {
new StatusDialogBuilder(this)
.setTitle(R.string.info)
.setPositiveButton(android.R.string.ok, null)
@ -87,18 +87,18 @@ public class MainActivity extends BaseActivity {
Glide.with(binding.appIcon)
.load(GlideHelper.wrapApplicationInfoForIconLoader(getApplicationInfo()))
.into(binding.appIcon);
String installedXposedVersion = Constants.getXposedVersion();
String installedXposedVersion = ConfigManager.getXposedVersionName();
int cardBackgroundColor;
if (installedXposedVersion != null) {
binding.statusTitle.setText(String.format(Locale.US, "%s %s", getString(R.string.Activated), Constants.getXposedVariant()));
if (!Constants.isPermissive()) {
binding.statusTitle.setText(String.format(Locale.US, "%s %s", getString(R.string.Activated), ConfigManager.getVariantString()));
if (!ConfigManager.isPermissive()) {
if (Helpers.currentHoliday == Helpers.Holidays.LUNARNEWYEAR) {
cardBackgroundColor = 0xfff05654;
} else {
cardBackgroundColor = ResourcesKt.resolveColor(getTheme(), R.attr.colorNormal);
}
binding.statusIcon.setImageResource(R.drawable.ic_check_circle);
binding.statusSummary.setText(String.format(Locale.US, "%s (%d)", installedXposedVersion, Constants.getXposedVersionCode()));
binding.statusSummary.setText(String.format(Locale.US, "%s (%d)", installedXposedVersion, ConfigManager.getXposedVersionCode()));
} else {
cardBackgroundColor = ResourcesKt.resolveColor(getTheme(), R.attr.colorError);
binding.statusIcon.setImageResource(R.drawable.ic_warning);
@ -129,7 +129,7 @@ public class MainActivity extends BaseActivity {
@Override
public void onClick(View v) {
if (requireInstalled && Constants.getXposedVersion() == null) {
if (requireInstalled && ConfigManager.getXposedVersionName() == null) {
Snackbar.make(binding.snackbar, R.string.lsposed_not_active, Snackbar.LENGTH_LONG).show();
} else {
Intent intent = new Intent();

View File

@ -57,7 +57,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import io.github.lsposed.manager.Constants;
import io.github.lsposed.manager.ConfigManager;
import io.github.lsposed.manager.R;
import io.github.lsposed.manager.adapters.AppHelper;
import io.github.lsposed.manager.ui.activity.base.ListActivity;
@ -188,7 +188,7 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
sb.append(getString(R.string.module_empty_description));
}
int installedXposedVersion = Constants.getXposedApiVersion();
int installedXposedVersion = ConfigManager.getXposedApiVersion();
String warningText = null;
if (item.minVersion == 0) {
warningText = getString(R.string.no_min_version_specified);

View File

@ -29,7 +29,6 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
@ -45,15 +44,11 @@ import com.google.android.material.snackbar.Snackbar;
import com.takisoft.preferencex.PreferenceFragmentCompat;
import com.takisoft.preferencex.SimpleMenuPreference;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Calendar;
import java.util.Locale;
import io.github.lsposed.manager.BuildConfig;
import io.github.lsposed.manager.Constants;
import io.github.lsposed.manager.ConfigManager;
import io.github.lsposed.manager.R;
import io.github.lsposed.manager.databinding.ActivitySettingsBinding;
import io.github.lsposed.manager.ui.activity.base.BaseActivity;
@ -101,7 +96,7 @@ public class SettingsActivity extends BaseActivity {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new SettingsFragment()).commit();
}
if (Constants.getXposedVersion() == null) {
if (ConfigManager.getXposedVersionName() == null) {
Snackbar.make(binding.snackbar, R.string.lsposed_not_active, Snackbar.LENGTH_LONG).show();
}
}
@ -142,9 +137,6 @@ public class SettingsActivity extends BaseActivity {
}
public static class SettingsFragment extends PreferenceFragmentCompat {
private static final Path enableResourcesFlag = Paths.get(Constants.getConfDir(), "enable_resources");
private static final Path disableVerboseLogsFlag = Paths.get(Constants.getMiscDir(), "disable_verbose_log");
private static final Path variantFlag = Paths.get(Constants.getMiscDir(), "variant");
ActivityResultLauncher<String> backupLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument(),
uri -> {
if (uri != null) {
@ -204,36 +196,23 @@ public class SettingsActivity extends BaseActivity {
public void onCreatePreferencesFix(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.prefs);
boolean installed = Constants.getXposedVersion() != null;
boolean installed = ConfigManager.getXposedVersionName() != null;
SwitchPreference prefVerboseLogs = findPreference("disable_verbose_log");
if (prefVerboseLogs != null) {
if (requireActivity().getApplicationInfo().uid / 100000 != 0) {
prefVerboseLogs.setVisible(false);
} else {
prefVerboseLogs.setEnabled(installed);
try {
prefVerboseLogs.setChecked(Files.readAllBytes(disableVerboseLogsFlag)[0] == 49);
} catch (Exception e) {
e.printStackTrace();
}
prefVerboseLogs.setOnPreferenceChangeListener((preference, newValue) -> {
try {
Files.write(disableVerboseLogsFlag, ((boolean) newValue) ? new byte[]{49, 0} : new byte[]{48, 0});
return true;
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show();
return false;
}
});
prefVerboseLogs.setChecked(!ConfigManager.isVerboseLogEnabled());
prefVerboseLogs.setOnPreferenceChangeListener((preference, newValue) -> ConfigManager.setVerboseLogEnabled(!(boolean) newValue));
}
}
SwitchPreference prefEnableResources = findPreference("enable_resources");
if (prefEnableResources != null) {
prefEnableResources.setEnabled(installed);
prefEnableResources.setChecked(Files.exists(enableResourcesFlag));
prefEnableResources.setOnPreferenceChangeListener(new OnFlagChangeListener(enableResourcesFlag));
prefEnableResources.setChecked(ConfigManager.isResourceHookEnabled());
prefEnableResources.setOnPreferenceChangeListener((preference, newValue) -> ConfigManager.setResourceHookEnabled((boolean) newValue));
}
SimpleMenuPreference prefVariant = findPreference("variant");
@ -242,21 +221,8 @@ public class SettingsActivity extends BaseActivity {
prefVariant.setVisible(false);
} else {
prefVariant.setEnabled(installed);
try {
prefVariant.setValue(new String(Files.readAllBytes(variantFlag)).trim());
} catch (Exception e) {
e.printStackTrace();
}
prefVariant.setOnPreferenceChangeListener((preference, newValue) -> {
try {
Files.write(variantFlag, ((String) newValue).getBytes());
return true;
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show();
return false;
}
});
prefVariant.setValue(String.valueOf(ConfigManager.getVariant()));
prefVariant.setOnPreferenceChangeListener((preference, newValue) -> ConfigManager.setVariant(Integer.parseInt((String) newValue)));
}
}
@ -320,30 +286,6 @@ public class SettingsActivity extends BaseActivity {
}
}
private class OnFlagChangeListener implements Preference.OnPreferenceChangeListener {
private final Path flag;
OnFlagChangeListener(Path flag) {
this.flag = flag;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean enabled = (Boolean) newValue;
try {
if (enabled) {
Files.createFile(flag);
} else {
Files.delete(flag);
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
return (enabled == Files.exists(flag));
}
}
@Override
public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
BorderRecyclerView recyclerView = (BorderRecyclerView) super.onCreateRecyclerView(inflater, parent, savedInstanceState);

View File

@ -33,7 +33,7 @@ import androidx.appcompat.app.AlertDialog;
import io.github.lsposed.manager.App;
import io.github.lsposed.manager.BuildConfig;
import io.github.lsposed.manager.Constants;
import io.github.lsposed.manager.ConfigManager;
import io.github.lsposed.manager.R;
import io.github.lsposed.manager.util.NavUtil;
import io.github.lsposed.manager.util.theme.ThemeUtil;
@ -53,7 +53,7 @@ public class BaseActivity extends MaterialActivity {
super.onCreate(savedInstanceState);
// make sure the versions are consistent
String coreVersionStr = Constants.getXposedVersion();
String coreVersionStr = ConfigManager.getXposedVersionName();
if (coreVersionStr != null) {
if (!BuildConfig.VERSION_NAME.equals(coreVersionStr)) {
new AlertDialog.Builder(this)

View File

@ -38,7 +38,7 @@ import java.util.Locale;
import dalvik.system.VMRuntime;
import io.github.lsposed.manager.BuildConfig;
import io.github.lsposed.manager.Constants;
import io.github.lsposed.manager.ConfigManager;
import io.github.lsposed.manager.R;
import io.github.lsposed.manager.databinding.StatusInstallerBinding;
@ -66,20 +66,20 @@ public class StatusDialogBuilder extends AlertDialog.Builder {
super(context);
StatusInstallerBinding binding = StatusInstallerBinding.inflate(LayoutInflater.from(context), null, false);
String installedXposedVersion = Constants.getXposedVersion();
String installedXposedVersion = ConfigManager.getXposedVersionName();
String mAppVer = String.format("%s (%s)", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE);
binding.manager.setText(mAppVer);
if (installedXposedVersion != null) {
binding.api.setText(String.format(Locale.US, "%s.0", Constants.getXposedApiVersion()));
binding.framework.setText(String.format(Locale.US, "%s (%s)", installedXposedVersion, Constants.getXposedVersionCode()));
binding.api.setText(String.format(Locale.US, "%s.0", ConfigManager.getXposedApiVersion()));
binding.framework.setText(String.format(Locale.US, "%s (%s)", installedXposedVersion, ConfigManager.getXposedVersionCode()));
}
binding.androidVersion.setText(context.getString(R.string.android_sdk, getAndroidVersion(), Build.VERSION.RELEASE, Build.VERSION.SDK_INT));
binding.manufacturer.setText(getUIFramework());
binding.cpu.setText(getCompleteArch());
if (Constants.isPermissive()) {
if (ConfigManager.isPermissive()) {
binding.selinux.setVisibility(View.VISIBLE);
binding.selinux.setText(HtmlCompat.fromHtml(context.getString(R.string.selinux_permissive), HtmlCompat.FROM_HTML_MODE_LEGACY));
}

View File

@ -34,8 +34,6 @@ import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import io.github.lsposed.manager.adapters.AppHelper;
public class BackupUtils {
private static final int VERSION = 1;
@ -56,11 +54,11 @@ public class BackupUtils {
JSONObject moduleObject = new JSONObject();
moduleObject.put("enable", ModuleUtil.getInstance().isModuleEnabled(module.packageName));
moduleObject.put("package", module.packageName);
List<String> scope = AppHelper.getScopeList(module.packageName);
//List<String> scope = AppHelper.getScopeList(module.packageName);
JSONArray scopeArray = new JSONArray();
for (String s : scope) {
scopeArray.put(s);
}
//for (String s : scope) {
// scopeArray.put(s);
//}
moduleObject.put("scope", scopeArray);
modulesArray.put(moduleObject);
}
@ -110,7 +108,7 @@ public class BackupUtils {
for (int j = 0; j < scopeArray.length(); j++) {
scope.add(scopeArray.getString(j));
}
AppHelper.saveScopeList(name, scope);
//AppHelper.saveScopeList(name, scope);
}
}
}

View File

@ -25,12 +25,10 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.util.Log;
import androidx.annotation.NonNull;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
@ -40,8 +38,7 @@ import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import io.github.lsposed.manager.App;
import io.github.lsposed.manager.Constants;
import io.github.lsposed.manager.adapters.AppHelper;
import io.github.lsposed.manager.ConfigManager;
import io.github.lsposed.manager.repo.RepoLoader;
import io.github.lsposed.manager.repo.model.OnlineModule;
@ -57,7 +54,7 @@ public final class ModuleUtil {
private ModuleUtil() {
pm = App.getInstance().getPackageManager();
enabledModules = AppHelper.getEnabledModuleList();
enabledModules = new ArrayList<>(Arrays.asList(ConfigManager.getEnabledModules()));
}
public static synchronized ModuleUtil getInstance() {
@ -148,16 +145,18 @@ public final class ModuleUtil {
return installedModules;
}
public void setModuleEnabled(String packageName, boolean enabled) {
public boolean setModuleEnabled(String packageName, boolean enabled) {
if (!ConfigManager.setModuleEnabled(packageName, enabled)) {
return false;
}
if (enabled) {
if (!enabledModules.contains(packageName)) {
enabledModules.add(packageName);
updateModulesList();
}
} else {
enabledModules.remove(packageName);
updateModulesList();
}
return true;
}
public boolean isModuleEnabled(String packageName) {
@ -179,7 +178,7 @@ public final class ModuleUtil {
}
public synchronized void updateModulesList() {
try {
/*try {
Log.i(App.TAG, "ModuleUtil -> updating modules.list");
PrintWriter modulesList = new PrintWriter(Constants.getModulesListFile());
PrintWriter enabledModulesList = new PrintWriter(Constants.getEnabledModulesListFile());
@ -192,7 +191,7 @@ public final class ModuleUtil {
enabledModulesList.close();
} catch (IOException e) {
Log.e(App.TAG, "ModuleUtil -> cannot write " + Constants.getModulesListFile(), e);
}
}*/
}
public void addListener(ModuleListener listener) {

View File

@ -28,12 +28,10 @@ import android.os.Parcelable;
import android.util.AttributeSet;
import android.widget.ImageView;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.TypedArrayUtils;
import androidx.preference.DialogPreference;
import androidx.preference.PreferenceViewHolder;
import com.takisoft.colorpicker.ColorStateDrawable;
import com.takisoft.preferencex.PreferenceFragmentCompat;
import io.github.lsposed.manager.R;