From abc359888126075bcc6aa86fc41f3238032039ce Mon Sep 17 00:00:00 2001 From: NekoInverter <7741672-NekoInverter@users.noreply.gitlab.com> Date: Fri, 11 Dec 2020 00:01:50 +0800 Subject: [PATCH] Adapt to new EdXposed --- app/proguard-rules.pro | 5 +- app/src/main/AndroidManifest.xml | 12 - app/src/main/assets/xposed_init | 1 - .../android/xposed/installer/XposedApp.java | 56 --- .../xposed/installer/util/InstallZipUtil.java | 51 --- .../org/meowcat/edxposed/manager/App.java | 23 +- .../meowcat/edxposed/manager/Constants.java | 37 ++ .../edxposed/manager/adapters/AppHelper.java | 8 +- .../manager/ui/activity/LogsActivity.java | 9 +- .../manager/ui/activity/MainActivity.java | 18 +- .../manager/ui/activity/ModulesActivity.java | 5 +- .../manager/ui/activity/SettingsActivity.java | 121 +----- .../ui/fragment/StatusInstallerFragment.java | 22 +- .../edxposed/manager/util/ModuleUtil.java | 20 +- .../edxposed/manager/xposed/Enhancement.java | 354 ------------------ app/src/main/res/xml/prefs.xml | 35 -- 16 files changed, 86 insertions(+), 691 deletions(-) delete mode 100644 app/src/main/assets/xposed_init delete mode 100644 app/src/main/java/de/robv/android/xposed/installer/XposedApp.java delete mode 100644 app/src/main/java/de/robv/android/xposed/installer/util/InstallZipUtil.java create mode 100644 app/src/main/java/org/meowcat/edxposed/manager/Constants.java delete mode 100644 app/src/main/java/org/meowcat/edxposed/manager/xposed/Enhancement.java diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 69f8fdd6..5f3c6e51 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -19,6 +19,5 @@ # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile --keep class org.meowcat.edxposed.manager.util.json.**{public *; } --keep class org.meowcat.edxposed.manager.xposed.**{ *; } --keep class de.robv.android.xposed.installer.**{public *; } \ No newline at end of file +-keep class org.meowcat.edxposed.manager.util.json.** {public *; } +-keep class org.meowcat.edxposed.manager.Constants { *; } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7161aaf7..cf4260c2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,18 +97,6 @@ android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> - - - - - - \ No newline at end of file diff --git a/app/src/main/assets/xposed_init b/app/src/main/assets/xposed_init deleted file mode 100644 index dbac97d2..00000000 --- a/app/src/main/assets/xposed_init +++ /dev/null @@ -1 +0,0 @@ -org.meowcat.edxposed.manager.xposed.Enhancement \ No newline at end of file diff --git a/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java b/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java deleted file mode 100644 index d5631613..00000000 --- a/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java +++ /dev/null @@ -1,56 +0,0 @@ -package de.robv.android.xposed.installer; - -import android.annotation.SuppressLint; -import android.app.Application; -import android.util.Log; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; - -import de.robv.android.xposed.installer.util.InstallZipUtil; - -import static de.robv.android.xposed.installer.util.InstallZipUtil.parseXposedProp; - -@SuppressLint("Registered") -public class XposedApp extends Application { - public static final String TAG = "EdXposedManager"; - private static final File EDXPOSED_PROP_FILE = new File("/system/framework/edconfig.jar"); - public InstallZipUtil.XposedProp mXposedProp; - - public static boolean isEnhancementEnabled() { - return false; - } - - // This method is hooked by XposedBridge to return the current version - public static Integer getActiveXposedVersion() { - Log.d(TAG, "EdXposed is not active"); - return -1; - } - - public void onCreate() { - super.onCreate(); - reloadXposedProp(); - } - - // This method is hooked by XposedBridge - public void reloadXposedProp() { - InstallZipUtil.XposedProp prop = null; - File file = null; - - if (EDXPOSED_PROP_FILE.canRead()) { - file = EDXPOSED_PROP_FILE; - } - - if (file != null) { - try (FileInputStream is = new FileInputStream(file)) { - prop = parseXposedProp(is); - } catch (IOException e) { - Log.e(TAG, "Could not read " + file.getPath(), e); - } - } - synchronized (this) { - mXposedProp = prop; - } - } -} diff --git a/app/src/main/java/de/robv/android/xposed/installer/util/InstallZipUtil.java b/app/src/main/java/de/robv/android/xposed/installer/util/InstallZipUtil.java deleted file mode 100644 index d402d2e2..00000000 --- a/app/src/main/java/de/robv/android/xposed/installer/util/InstallZipUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -package de.robv.android.xposed.installer.util; - -import org.meowcat.edxposed.manager.util.ModuleUtil; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; - -public final class InstallZipUtil { - - public static XposedProp parseXposedProp(InputStream is) throws IOException { - XposedProp prop = new XposedProp(); - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - String line; - while ((line = reader.readLine()) != null) { - String[] parts = line.split("=", 2); - if (parts.length != 2) { - continue; - } - - String key = parts[0].trim(); - if (key.charAt(0) == '#') { - continue; - } - - String value = parts[1].trim(); - - if ("version".equals(key)) { - prop.mVersion = value; - prop.mVersionInt = ModuleUtil.extractIntPart(value); - } - } - reader.close(); - return prop.isComplete() ? prop : null; - } - - public static class XposedProp { - private String mVersion = null; - private int mVersionInt = 0; - - private boolean isComplete() { - return mVersion != null - && mVersionInt > 0; - } - - public String getVersion() { - return mVersion; - } - } -} diff --git a/app/src/main/java/org/meowcat/edxposed/manager/App.java b/app/src/main/java/org/meowcat/edxposed/manager/App.java index 6f1ce312..46b725ff 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/App.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/App.java @@ -35,12 +35,8 @@ import java.util.Collection; import java.util.Date; import java.util.Objects; -import de.robv.android.xposed.installer.XposedApp; -import de.robv.android.xposed.installer.util.InstallZipUtil; - -public class App extends XposedApp implements Application.ActivityLifecycleCallbacks { - public static String BASE_DIR = null; - public static String ENABLED_MODULES_LIST_FILE = null; +public class App extends Application implements Application.ActivityLifecycleCallbacks { + public static final String TAG = "EdXposedManager"; @SuppressLint("StaticFieldLeak") private static App instance = null; private static Thread uiThread; @@ -53,10 +49,6 @@ public class App extends XposedApp implements Application.ActivityLifecycleCallb return instance; } - public static InstallZipUtil.XposedProp getXposedProp() { - return getInstance().mXposedProp; - } - public static void runOnUiThread(Runnable action) { if (Thread.currentThread() != uiThread) { mainHandler.post(action); @@ -70,14 +62,14 @@ public class App extends XposedApp implements Application.ActivityLifecycleCallb } public static void mkdirAndChmod(String dir, int permissions) { - dir = BASE_DIR + dir; + dir = Constants.getBaseDir() + dir; //noinspection ResultOfMethodCallIgnored new File(dir).mkdir(); FileUtils.setPermissions(dir, permissions); } public static boolean supportScope() { - return App.getActiveXposedVersion() >= 92; + return Constants.getXposedApiVersion() >= 92; } public void onCreate() { @@ -111,11 +103,6 @@ public class App extends XposedApp implements Application.ActivityLifecycleCallb } } - final ApplicationInfo appInfo = getApplicationInfo(); - BASE_DIR = appInfo.deviceProtectedDataDir + "/"; - ENABLED_MODULES_LIST_FILE = BASE_DIR + "conf/enabled_modules.list"; - ModuleUtil.MODULES_LIST_FILE = BASE_DIR + "conf/modules.list"; - instance = this; uiThread = Thread.currentThread(); mainHandler = new Handler(); @@ -158,7 +145,7 @@ public class App extends XposedApp implements Application.ActivityLifecycleCallb @SuppressWarnings({"OctalInteger"}) @SuppressLint({"PrivateApi", "NewApi"}) private void createDirectories() { - FileUtils.setPermissions(BASE_DIR, 00777); + FileUtils.setPermissions(Constants.getBaseDir(), 00777); mkdirAndChmod("conf", 00777); mkdirAndChmod("log", 00777); } diff --git a/app/src/main/java/org/meowcat/edxposed/manager/Constants.java b/app/src/main/java/org/meowcat/edxposed/manager/Constants.java new file mode 100644 index 00000000..7cc13a8b --- /dev/null +++ b/app/src/main/java/org/meowcat/edxposed/manager/Constants.java @@ -0,0 +1,37 @@ +package org.meowcat.edxposed.manager; + +import android.util.Log; + +public class Constants { + public static int getXposedApiVersion() { + Log.e(App.TAG, "getXposedApiVersion: Xposed is not active"); + return -1; + } + + public static String getXposedVersion() { + Log.e(App.TAG, "getXposedVersion: Xposed is not active"); + return null; + } + + public static int getXposedVersionCode() { + Log.e(App.TAG, "getXposedVersionCode: Xposed is not active"); + return -1; + } + + public static String getXposedVariant() { + Log.e(App.TAG, "getXposedVariant: Xposed is not active"); + return null; + } + + public static String getEnabledModulesListFile() { + return getBaseDir() + "conf/enabled_modules.list"; + } + + public static String getModulesListFile() { + return getBaseDir() + "conf/modules.list"; + } + + public static String getBaseDir() { + return App.getInstance().getApplicationInfo().deviceProtectedDataDir + "/"; + } +} diff --git a/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppHelper.java b/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppHelper.java index 4418f8a4..9e804043 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppHelper.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppHelper.java @@ -17,6 +17,7 @@ import androidx.fragment.app.FragmentManager; import org.meowcat.edxposed.manager.App; import org.meowcat.edxposed.manager.BuildConfig; +import org.meowcat.edxposed.manager.Constants; import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.util.CompileUtil; import org.meowcat.edxposed.manager.util.FileUtils; @@ -30,7 +31,6 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -41,9 +41,7 @@ import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS; @SuppressWarnings("deprecation") public class AppHelper { - public static final String TAG = App.TAG; - - private static final String BASE_PATH = App.BASE_DIR; + private static final String BASE_PATH = Constants.getBaseDir(); private static final String WHITE_LIST_PATH = "conf/whitelist/"; private static final String BLACK_LIST_PATH = "conf/blacklist/"; private static final String COMPAT_LIST_PATH = "conf/compatlist/"; @@ -51,7 +49,7 @@ public class AppHelper { private static final String WHITE_LIST_MODE = "conf/usewhitelist"; private static final String BLACK_LIST_MODE = "conf/blackwhitelist"; - private static final List FORCE_WHITE_LIST = new ArrayList<>(App.isEnhancementEnabled() ? Arrays.asList(BuildConfig.APPLICATION_ID, "android") : Collections.singletonList(BuildConfig.APPLICATION_ID)); + private static final List FORCE_WHITE_LIST = new ArrayList<>(Collections.singletonList(BuildConfig.APPLICATION_ID)); public static List FORCE_WHITE_LIST_MODULE = new ArrayList<>(FORCE_WHITE_LIST); private static final HashMap> scopeList = new HashMap<>(); diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/LogsActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/LogsActivity.java index 8ff38a75..04f220e8 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/LogsActivity.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/LogsActivity.java @@ -26,6 +26,7 @@ import com.google.android.material.tabs.TabLayout; import org.meowcat.edxposed.manager.App; import org.meowcat.edxposed.manager.BuildConfig; +import org.meowcat.edxposed.manager.Constants; import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.databinding.ActivityLogsBinding; import org.meowcat.edxposed.manager.databinding.DialogInstallWarningBinding; @@ -44,11 +45,11 @@ import java.util.Scanner; public class LogsActivity extends BaseActivity { private boolean allLog = false; - private final File fileErrorLog = new File(App.BASE_DIR + "log/error.log"); + private final File fileErrorLog = new File(Constants.getBaseDir() + "log/error.log"); private final File fileErrorLogOld = new File( - App.BASE_DIR + "log/error.log.old"); - private final File fileAllLog = new File(App.BASE_DIR + "log/all.log"); - private final File fileAllLogOld = new File(App.BASE_DIR + "log/all.log.old"); + Constants.getBaseDir() + "log/error.log.old"); + private final File fileAllLog = new File(Constants.getBaseDir() + "log/all.log"); + private final File fileAllLogOld = new File(Constants.getBaseDir() + "log/all.log.old"); private LogsAdapter adapter; private final Handler handler = new Handler(); private ActivityLogsBinding binding; diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/MainActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/MainActivity.java index 264533e1..65bed4df 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/MainActivity.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/MainActivity.java @@ -11,6 +11,7 @@ import androidx.core.content.ContextCompat; import com.bumptech.glide.Glide; import org.meowcat.edxposed.manager.App; +import org.meowcat.edxposed.manager.Constants; import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.adapters.AppHelper; import org.meowcat.edxposed.manager.adapters.BlackListAdapter; @@ -86,18 +87,11 @@ public class MainActivity extends BaseActivity implements RepoLoader.RepoListene Glide.with(binding.appIcon) .load(GlideHelper.wrapApplicationInfoForIconLoader(getApplicationInfo())) .into(binding.appIcon); - String installedXposedVersion; - try { - installedXposedVersion = App.getXposedProp().getVersion(); - } catch (NullPointerException e) { - installedXposedVersion = null; - } + String installedXposedVersion = Constants.getXposedVersion(); if (installedXposedVersion != null) { - int installedXposedVersionInt = extractIntPart(installedXposedVersion); - if (App.getActiveXposedVersion() != -1) { - String installedXposedVersionStr = installedXposedVersionInt + ".0"; + if (Constants.getXposedApiVersion() != -1) { binding.statusTitle.setText(R.string.Activated); - binding.statusSummary.setText(installedXposedVersion.replace(installedXposedVersionStr + "-", "")); + binding.statusSummary.setText(installedXposedVersion + " (" + Constants.getXposedVariant() + ")"); binding.status.setCardBackgroundColor(ContextCompat.getColor(this, R.color.download_status_update_available)); binding.statusIcon.setImageResource(R.drawable.ic_check_circle); } else { @@ -106,9 +100,9 @@ public class MainActivity extends BaseActivity implements RepoLoader.RepoListene binding.status.setCardBackgroundColor(ContextCompat.getColor(this, R.color.amber_500)); binding.statusIcon.setImageResource(R.drawable.ic_warning); } - } else if (App.getActiveXposedVersion() > 0) { + } else if (Constants.getXposedApiVersion() > 0) { binding.statusTitle.setText(R.string.Activated); - binding.statusSummary.setText(getString(R.string.version_x, App.getActiveXposedVersion())); + binding.statusSummary.setText(getString(R.string.version_x, Constants.getXposedApiVersion())); binding.status.setCardBackgroundColor(ContextCompat.getColor(this, R.color.download_status_update_available)); binding.statusIcon.setImageResource(R.drawable.ic_check_circle); } else { diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/ModulesActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/ModulesActivity.java index 3167d7d3..87688427 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/ModulesActivity.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/ModulesActivity.java @@ -29,6 +29,7 @@ import com.google.android.material.snackbar.Snackbar; import org.meowcat.edxposed.manager.App; import org.meowcat.edxposed.manager.BuildConfig; +import org.meowcat.edxposed.manager.Constants; import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.databinding.ActivityModulesBinding; import org.meowcat.edxposed.manager.repo.Module; @@ -191,7 +192,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi pm = getPackageManager(); displayNameComparator = new ApplicationInfo.DisplayNameComparator(pm); cmp = displayNameComparator; - installedXposedVersion = App.getActiveXposedVersion(); + installedXposedVersion = Constants.getXposedApiVersion(); if (installedXposedVersion <= 0) { Snackbar.make(binding.snackbar, R.string.xposed_not_active, Snackbar.LENGTH_LONG).setAction(R.string.Settings, v -> { Intent intent = new Intent(); @@ -246,7 +247,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi return; } if (requestCode == 42) { - File listModules = new File(App.ENABLED_MODULES_LIST_FILE); + File listModules = new File(Constants.getEnabledModulesListFile()); if (data != null) { Uri uri = data.getData(); if (uri != null) { diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/SettingsActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/SettingsActivity.java index b0ee8815..7ea6705d 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/SettingsActivity.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/SettingsActivity.java @@ -25,6 +25,7 @@ import com.takisoft.preferencex.PreferenceFragmentCompat; import com.topjohnwu.superuser.Shell; import org.meowcat.edxposed.manager.App; +import org.meowcat.edxposed.manager.Constants; import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.adapters.AppHelper; import org.meowcat.edxposed.manager.adapters.BlackListAdapter; @@ -114,18 +115,15 @@ public class SettingsActivity extends BaseActivity { @SuppressWarnings({"ResultOfMethodCallIgnored", "deprecation"}) public static class SettingsFragment extends PreferenceFragmentCompat { - private static final File pretendXposedInstallerFlag = new File(App.BASE_DIR + "conf/pretend_xposed_installer"); - private static final File hideEdXposedManagerFlag = new File(App.BASE_DIR + "conf/hide_edxposed_manager"); - private static final File disableHiddenAPIBypassFlag = new File(App.BASE_DIR + "conf/disable_hidden_api_bypass"); - private static final File disableResourcesFlag = new File(App.BASE_DIR + "conf/disable_resources"); - private static final File dynamicModulesFlag = new File(App.BASE_DIR + "conf/dynamicmodules"); - private static final File deoptBootFlag = new File(App.BASE_DIR + "conf/deoptbootimage"); - private static final File whiteListModeFlag = new File(App.BASE_DIR + "conf/usewhitelist"); - private static final File blackWhiteListModeFlag = new File(App.BASE_DIR + "conf/blackwhitelist"); - private static final File disableVerboseLogsFlag = new File(App.BASE_DIR + "conf/disable_verbose_log"); - private static final File disableModulesLogsFlag = new File(App.BASE_DIR + "conf/disable_modules_log"); - private static final File verboseLogProcessID = new File(App.BASE_DIR + "log/all.pid"); - private static final File modulesLogProcessID = new File(App.BASE_DIR + "log/error.pid"); + private static final File disableResourcesFlag = new File(Constants.getBaseDir() + "conf/disable_resources"); + private static final File dynamicModulesFlag = new File(Constants.getBaseDir() + "conf/dynamicmodules"); + private static final File deoptBootFlag = new File(Constants.getBaseDir() + "conf/deoptbootimage"); + private static final File whiteListModeFlag = new File(Constants.getBaseDir() + "conf/usewhitelist"); + private static final File blackWhiteListModeFlag = new File(Constants.getBaseDir() + "conf/blackwhitelist"); + private static final File disableVerboseLogsFlag = new File(Constants.getBaseDir() + "conf/disable_verbose_log"); + private static final File disableModulesLogsFlag = new File(Constants.getBaseDir() + "conf/disable_modules_log"); + private static final File verboseLogProcessID = new File(Constants.getBaseDir() + "log/all.pid"); + private static final File modulesLogProcessID = new File(Constants.getBaseDir() + "log/error.pid"); @SuppressLint({"WorldReadableFiles", "WorldWriteableFiles"}) static void setFilePermissionsFromMode(String name) { @@ -492,105 +490,6 @@ public class SettingsActivity extends BaseActivity { return true; }); updatePreference(!md2.isChecked()); - - Preference enhancement_status = findPreference("enhancement_status"); - Objects.requireNonNull(enhancement_status).setSummary(App.isEnhancementEnabled() ? R.string.settings_summary_enhancement_enabled : R.string.settings_summary_enhancement); - SwitchPreferenceCompat prefPretendXposedInstaller = findPreference("pretend_xposed_installer"); - - Objects.requireNonNull(prefPretendXposedInstaller).setChecked(pretendXposedInstallerFlag.exists()); - prefPretendXposedInstaller.setOnPreferenceChangeListener((preference, newValue) -> { - boolean enabled = (Boolean) newValue; - if (enabled) { - new BlackListAdapter(getContext(), AppHelper.isWhiteListMode()).generateCheckedList(); - FileOutputStream fos = null; - try { - fos = new FileOutputStream(pretendXposedInstallerFlag.getPath()); - setFilePermissionsFromMode(pretendXposedInstallerFlag.getPath()); - } catch (FileNotFoundException e) { - Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show(); - } finally { - if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show(); - try { - pretendXposedInstallerFlag.createNewFile(); - } catch (IOException e1) { - Toast.makeText(getActivity(), e1.getMessage(), Toast.LENGTH_SHORT).show(); - } - } - } - } - } else { - pretendXposedInstallerFlag.delete(); - } - return (enabled == pretendXposedInstallerFlag.exists()); - }); - - SwitchPreferenceCompat prefHideEdXposedManager = findPreference("hide_edxposed_manager"); - Objects.requireNonNull(prefHideEdXposedManager).setChecked(hideEdXposedManagerFlag.exists()); - prefHideEdXposedManager.setOnPreferenceChangeListener((preference, newValue) -> { - boolean enabled = (Boolean) newValue; - if (enabled) { - new BlackListAdapter(getContext(), AppHelper.isWhiteListMode()).generateCheckedList(); - FileOutputStream fos = null; - try { - fos = new FileOutputStream(hideEdXposedManagerFlag.getPath()); - setFilePermissionsFromMode(hideEdXposedManagerFlag.getPath()); - } catch (FileNotFoundException e) { - Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show(); - } finally { - if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show(); - try { - hideEdXposedManagerFlag.createNewFile(); - } catch (IOException e1) { - Toast.makeText(getActivity(), e1.getMessage(), Toast.LENGTH_SHORT).show(); - } - } - } - } - } else { - hideEdXposedManagerFlag.delete(); - } - return (enabled == hideEdXposedManagerFlag.exists()); - }); - - SwitchPreferenceCompat prefDisableHiddenAPIBypass = findPreference("disable_hidden_api_bypass"); - Objects.requireNonNull(prefDisableHiddenAPIBypass).setChecked(disableHiddenAPIBypassFlag.exists()); - prefDisableHiddenAPIBypass.setOnPreferenceChangeListener((preference, newValue) -> { - boolean enabled = (Boolean) newValue; - if (enabled) { - FileOutputStream fos = null; - try { - fos = new FileOutputStream(disableHiddenAPIBypassFlag.getPath()); - setFilePermissionsFromMode(disableHiddenAPIBypassFlag.getPath()); - } catch (FileNotFoundException e) { - Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show(); - } finally { - if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show(); - try { - disableHiddenAPIBypassFlag.createNewFile(); - } catch (IOException e1) { - Toast.makeText(getActivity(), e1.getMessage(), Toast.LENGTH_SHORT).show(); - } - } - } - } - } else { - disableHiddenAPIBypassFlag.delete(); - } - return (enabled == disableHiddenAPIBypassFlag.exists()); - }); - } } diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/StatusInstallerFragment.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/StatusInstallerFragment.java index f49b57ae..d68c4c3b 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/StatusInstallerFragment.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/StatusInstallerFragment.java @@ -21,6 +21,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.meowcat.edxposed.manager.App; import org.meowcat.edxposed.manager.BuildConfig; +import org.meowcat.edxposed.manager.Constants; import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.databinding.StatusInstallerBinding; @@ -99,25 +100,12 @@ public class StatusInstallerFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { binding = StatusInstallerBinding.inflate(inflater, container, false); - String installedXposedVersion; - try { - installedXposedVersion = App.getXposedProp().getVersion(); - } catch (NullPointerException e) { - installedXposedVersion = null; - } - - String mAppVer; - if (App.isEnhancementEnabled()) { - mAppVer = String.format("v%s (%s) (%s)", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, getString(R.string.status_enhancement)); - } else { - mAppVer = String.format("v%s (%s)", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE); - } + String installedXposedVersion = Constants.getXposedVersion(); + String mAppVer = String.format("v%s (%s)", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE); binding.manager.setText(mAppVer); if (installedXposedVersion != null) { - int installedXposedVersionInt = extractIntPart(installedXposedVersion); - String installedXposedVersionStr = installedXposedVersionInt + ".0"; - binding.api.setText(installedXposedVersionStr); - binding.framework.setText(installedXposedVersion.replace(installedXposedVersionStr + "-", "")); + binding.api.setText(Constants.getXposedApiVersion() + ".0"); + binding.framework.setText(installedXposedVersion + " (" + Constants.getXposedVariant() + ")"); } binding.androidVersion.setText(getString(R.string.android_sdk, getAndroidVersion(), Build.VERSION.RELEASE, Build.VERSION.SDK_INT)); diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/ModuleUtil.java b/app/src/main/java/org/meowcat/edxposed/manager/util/ModuleUtil.java index 31f44afd..96b85669 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/util/ModuleUtil.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/util/ModuleUtil.java @@ -15,6 +15,7 @@ import androidx.annotation.NonNull; import com.google.android.material.snackbar.Snackbar; import org.meowcat.edxposed.manager.App; +import org.meowcat.edxposed.manager.Constants; import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.databinding.ActivityModulesBinding; import org.meowcat.edxposed.manager.repo.ModuleVersion; @@ -32,7 +33,6 @@ import java.util.concurrent.CopyOnWriteArrayList; public final class ModuleUtil { private static final String PLAY_STORE_PACKAGE = "com.android.vending"; // xposedminversion below this - public static String MODULES_LIST_FILE = App.BASE_DIR + "conf/modules.list"; public static int MIN_MODULE_VERSION = 2; // reject modules with private static ModuleUtil instance = null; private final PackageManager pm; @@ -212,7 +212,7 @@ public final class ModuleUtil { public synchronized void updateModulesList(boolean showToast, ActivityModulesBinding binding) { try { Log.i(App.TAG, "ModuleUtil -> updating modules.list"); - int installedXposedVersion = App.getActiveXposedVersion(); + int installedXposedVersion = Constants.getXposedApiVersion(); if (!App.getPreferences().getBoolean("skip_xposedminversion_check", false) && installedXposedVersion <= 0 && showToast) { if (binding != null) { Snackbar.make(binding.snackbar, R.string.notinstalled, Snackbar.LENGTH_SHORT).show(); @@ -222,8 +222,8 @@ public final class ModuleUtil { return; } - PrintWriter modulesList = new PrintWriter(MODULES_LIST_FILE); - PrintWriter enabledModulesList = new PrintWriter(App.ENABLED_MODULES_LIST_FILE); + PrintWriter modulesList = new PrintWriter(Constants.getModulesListFile()); + PrintWriter enabledModulesList = new PrintWriter(Constants.getEnabledModulesListFile()); List enabledModules = getEnabledModules(); for (InstalledModule module : enabledModules) { @@ -248,8 +248,8 @@ public final class ModuleUtil { modulesList.close(); enabledModulesList.close(); - FileUtils.setPermissions(MODULES_LIST_FILE, 00664); - FileUtils.setPermissions(App.ENABLED_MODULES_LIST_FILE, 00664); + FileUtils.setPermissions(Constants.getEnabledModulesListFile(), 00664); + FileUtils.setPermissions(Constants.getEnabledModulesListFile(), 00664); if (showToast) { if (binding != null) { @@ -259,11 +259,11 @@ public final class ModuleUtil { } } } catch (IOException e) { - Log.e(App.TAG, "ModuleUtil -> cannot write " + MODULES_LIST_FILE, e); + Log.e(App.TAG, "ModuleUtil -> cannot write " + Constants.getModulesListFile(), e); if (binding != null) { - Snackbar.make(binding.snackbar, "cannot write " + MODULES_LIST_FILE + e, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(binding.snackbar, "cannot write " + Constants.getModulesListFile() + e, Snackbar.LENGTH_SHORT).show(); } else { - Toast.makeText(App.getInstance(), "cannot write " + MODULES_LIST_FILE + e, Toast.LENGTH_SHORT).show(); + Toast.makeText(App.getInstance(), "cannot write " + Constants.getModulesListFile() + e, Toast.LENGTH_SHORT).show(); } } } @@ -332,7 +332,7 @@ public final class ModuleUtil { this.minVersion = 0; this.description = ""; } else { - int version = App.getActiveXposedVersion(); + int version = Constants.getXposedApiVersion(); if (version > 0 && App.getPreferences().getBoolean("skip_xposedminversion_check", false)) { this.minVersion = version; } else { diff --git a/app/src/main/java/org/meowcat/edxposed/manager/xposed/Enhancement.java b/app/src/main/java/org/meowcat/edxposed/manager/xposed/Enhancement.java deleted file mode 100644 index 6606ce5b..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/xposed/Enhancement.java +++ /dev/null @@ -1,354 +0,0 @@ -package org.meowcat.edxposed.manager.xposed; - -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.os.Binder; -import android.os.Build; -import android.os.FileObserver; -import android.os.StrictMode; -import android.os.UserHandle; -import android.util.SparseArray; - -import androidx.annotation.Keep; -import androidx.annotation.Nullable; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import de.robv.android.xposed.IXposedHookLoadPackage; -import de.robv.android.xposed.XC_MethodHook; -import de.robv.android.xposed.XC_MethodReplacement; -import de.robv.android.xposed.XposedBridge; -import de.robv.android.xposed.XposedHelpers; -import de.robv.android.xposed.callbacks.XC_LoadPackage; -import de.robv.android.xposed.installer.XposedApp; - -import static de.robv.android.xposed.XposedHelpers.callMethod; -import static de.robv.android.xposed.XposedHelpers.callStaticMethod; -import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; -import static java.util.Collections.binarySearch; -import static org.meowcat.edxposed.manager.BuildConfig.APPLICATION_ID; - -@Keep -public class Enhancement implements IXposedHookLoadPackage { - - private static final String mPretendXposedInstallerFlag = "pretend_xposed_installer"; - private static final String mHideEdXposedManagerFlag = "hide_edxposed_manager"; - - private static final String LEGACY_INSTALLER = "de.robv.android.xposed.installer"; - - private static final List HIDE_WHITE_LIST = Arrays.asList( // TODO: more whitelist packages - APPLICATION_ID, // Whitelist or crash - LEGACY_INSTALLER, // for safety - "com.android.providers.downloads", // For download modules - "com.android.providers.downloads.ui", - "com.android.packageinstaller", // For uninstall EdXposed Manager - "com.google.android.packageinstaller", - "com.android.systemui", // For notifications - "com.android.permissioncontroller", // For permissions grant - "com.topjohnwu.magisk", // For superuser root grant - "eu.chainfire.supersu" - ); // UserHandle.isCore(uid) will auto pass - - private static final SparseArray> modulesList = new SparseArray<>(); - private static final SparseArray modulesListObservers = new SparseArray<>(); - - static { - Collections.sort(HIDE_WHITE_LIST); - } - - private static boolean getFlagState(int user, String flag) { - final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); - try { - return new File(String.format("/data/user_de/%s/%s/conf/%s", user, APPLICATION_ID, flag)).exists(); - } finally { - StrictMode.setThreadPolicy(oldPolicy); - } - } - - private static List getModulesList(final int user) { - final int index = modulesList.indexOfKey(user); - if (index >= 0) { - return modulesList.valueAt(index); - } - - final String filename = String.format("/data/user_de/%s/%s/conf/enabled_modules.list", user, APPLICATION_ID); - final FileObserver observer = new FileObserver(filename) { - @Override - public void onEvent(int event, @Nullable String path) { - switch (event) { - case FileObserver.MODIFY: - modulesList.put(user, readModulesList(filename)); - break; - case FileObserver.MOVED_FROM: - case FileObserver.MOVED_TO: - case FileObserver.MOVE_SELF: - case FileObserver.DELETE: - case FileObserver.DELETE_SELF: - modulesList.remove(user); - modulesListObservers.remove(user); - break; - } - } - }; - modulesListObservers.put(user, observer); - final List list = readModulesList(filename); - modulesList.put(user, list); - observer.startWatching(); - return list; - } - - private static List readModulesList(final String filename) { - XposedBridge.log("EdXposedManager: Reading modules list " + filename + "..."); - final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); - try { - final File listFile = new File(filename); - final List list = new ArrayList<>(); - try { - final FileReader fileReader = new FileReader(listFile); - final BufferedReader bufferedReader = new BufferedReader(fileReader); - String str; - while ((str = bufferedReader.readLine()) != null) { - list.add(str); - } - bufferedReader.close(); - fileReader.close(); - } catch (IOException e) { - XposedBridge.log(e); - } - Collections.sort(list); - return list; - } finally { - StrictMode.setThreadPolicy(oldPolicy); - } - } - - private static void hookAllMethods(String className, ClassLoader classLoader, String methodName, XC_MethodHook callback) { - try { - final Class hookClass = XposedHelpers.findClassIfExists(className, classLoader); - if (hookClass == null || XposedBridge.hookAllMethods(hookClass, methodName, callback).size() == 0) - XposedBridge.log("Failed to hook " + methodName + " method in " + className); - } catch (Throwable t) { - XposedBridge.log(t); - } - } - - @Override - public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) { - if (lpparam.packageName.equals("android")) { - // com.android.server.pm.PackageManagerService.getInstalledApplications(int flag, int userId) - findAndHookMethod("com.android.server.pm.PackageManagerService", lpparam.classLoader, "getInstalledApplications", int.class, int.class, new XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) { - if (param.args != null && param.args[0] != null) { - final int packageUid = Binder.getCallingUid(); - if ((boolean) callStaticMethod(UserHandle.class, "isCore", packageUid)) { - return; - } - - final int userId = (int) param.args[1]; - boolean isXposedModule = false; - final String[] packages = (String[]) callMethod(param.thisObject, "getPackagesForUid", packageUid); - if (packages == null || packages.length == 0) { - return; - } - for (String packageName : packages) { - if (binarySearch(HIDE_WHITE_LIST, packageName) >= 0) { - return; - } - if (binarySearch(getModulesList(userId), packageName) >= 0) { - isXposedModule = true; - break; - } - } - - @SuppressWarnings("unchecked") final List applicationInfoList = (List) callMethod(param.getResult(), "getList"); - if (isXposedModule) { - if (getFlagState(userId, mPretendXposedInstallerFlag)) { - for (ApplicationInfo applicationInfo : applicationInfoList) { - if (applicationInfo.packageName.equals(APPLICATION_ID)) { - applicationInfo.packageName = LEGACY_INSTALLER; - applicationInfoList.add(applicationInfo); - break; - } - } - } - } else { - if (getFlagState(userId, mHideEdXposedManagerFlag)) { - for (ApplicationInfo applicationInfo : applicationInfoList) { - if (applicationInfo.packageName.equals(APPLICATION_ID) || applicationInfo.packageName.equals(LEGACY_INSTALLER)) { - applicationInfoList.remove(applicationInfo); - break; - } - } - } - } - param.setResult(param.getResult()); // "reset" the result to indicate that we handled it - } - } - }); - // com.android.server.pm.PackageManagerService.getInstalledPackages(int flag, int userId) - findAndHookMethod("com.android.server.pm.PackageManagerService", lpparam.classLoader, "getInstalledPackages", int.class, int.class, new XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) { - if (param.args != null && param.args[0] != null) { - final int packageUid = Binder.getCallingUid(); - if ((boolean) callStaticMethod(UserHandle.class, "isCore", packageUid)) { - return; - } - - final int userId = (int) param.args[1]; - boolean isXposedModule = false; - final String[] packages = (String[]) callMethod(param.thisObject, "getPackagesForUid", packageUid); - if (packages == null || packages.length == 0) { - return; - } - for (String packageName : packages) { - if (binarySearch(HIDE_WHITE_LIST, packageName) >= 0) { - return; - } - if (binarySearch(getModulesList(userId), packageName) >= 0) { - isXposedModule = true; - break; - } - } - - @SuppressWarnings("unchecked") final List packageInfoList = (List) callMethod(param.getResult(), "getList"); - if (isXposedModule) { - if (getFlagState(userId, mPretendXposedInstallerFlag)) { - for (PackageInfo packageInfo : packageInfoList) { - if (packageInfo.packageName.equals(APPLICATION_ID)) { - packageInfo.packageName = LEGACY_INSTALLER; - packageInfoList.add(packageInfo); - break; - } - } - } - } else { - if (getFlagState(userId, mHideEdXposedManagerFlag)) { - for (PackageInfo packageInfo : packageInfoList) { - if (packageInfo.packageName.equals(APPLICATION_ID) || packageInfo.packageName.equals(LEGACY_INSTALLER)) { - packageInfoList.remove(packageInfo); - break; - } - } - } - } - param.setResult(param.getResult()); // "reset" the result to indicate that we handled it - } - } - }); - // com.android.server.pm.PackageManagerService.getApplicationInfo(String packageName, int flag, int userId) - hookAllMethods("com.android.server.pm.PackageManagerService", lpparam.classLoader, "getApplicationInfo", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) { - if (param.args != null && param.args[0] != null) { - final int packageUid = Binder.getCallingUid(); - if ((boolean) callStaticMethod(UserHandle.class, "isCore", packageUid)) { - return; - } - - final int userId = (int) param.args[2]; - boolean isXposedModule = false; - final String[] packages = (String[]) callMethod(param.thisObject, "getPackagesForUid", packageUid); - if (packages == null || packages.length == 0) { - return; - } - for (String packageName : packages) { - if (binarySearch(HIDE_WHITE_LIST, packageName) >= 0) { - return; - } - if (binarySearch(getModulesList(userId), packageName) >= 0) { - isXposedModule = true; - break; - } - } - - if (isXposedModule) { - if (getFlagState(userId, mPretendXposedInstallerFlag)) { - if (param.args[0].equals(LEGACY_INSTALLER)) { - param.args[0] = APPLICATION_ID; - } - } - } else { - if (getFlagState(userId, mHideEdXposedManagerFlag)) { - if (param.args[0].equals(APPLICATION_ID) || param.args[0].equals(LEGACY_INSTALLER)) { - param.setResult(null); - } - } - } - } - } - }); - // com.android.server.pm.PackageManagerService.getPackageInfo(String packageName, int flag, int userId) - hookAllMethods("com.android.server.pm.PackageManagerService", lpparam.classLoader, "getPackageInfo", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) { - if (param.args != null && param.args[0] != null) { - final int packageUid = Binder.getCallingUid(); - if ((boolean) callStaticMethod(UserHandle.class, "isCore", packageUid)) { - return; - } - - final int userId = (int) param.args[2]; - boolean isXposedModule = false; - final String[] packages = (String[]) callMethod(param.thisObject, "getPackagesForUid", packageUid); - if (packages == null || packages.length == 0) { - return; - } - for (String packageName : packages) { - if (binarySearch(HIDE_WHITE_LIST, packageName) >= 0) { - return; - } - if (binarySearch(getModulesList(userId), packageName) >= 0) { - isXposedModule = true; - break; - } - } - - if (isXposedModule) { - if (getFlagState(userId, mPretendXposedInstallerFlag)) { - if (param.args[0].equals(LEGACY_INSTALLER)) { - param.args[0] = APPLICATION_ID; - } - } - } else { - if (getFlagState(userId, mHideEdXposedManagerFlag)) { - if (param.args[0].equals(APPLICATION_ID) || param.args[0].equals(LEGACY_INSTALLER)) { - param.setResult(null); - } - } - } - } - } - }); - // Hook AM to remove restrict of EdXposed Manager - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - final XC_MethodHook hook = new XC_MethodHook() { - @Override - protected void afterHookedMethod(MethodHookParam param) { - if (param.args != null && param.args[1] != null) { - if (param.args[1].equals(APPLICATION_ID)) { - param.setResult(0); - } - } - } - }; - hookAllMethods("com.android.server.am.ActivityManagerService", lpparam.classLoader, "appRestrictedInBackgroundLocked", hook); - hookAllMethods("com.android.server.am.ActivityManagerService", lpparam.classLoader, "appServicesRestrictedInBackgroundLocked", hook); - hookAllMethods("com.android.server.am.ActivityManagerService", lpparam.classLoader, "getAppStartModeLocked", hook); - } - } else if (lpparam.packageName.equals(APPLICATION_ID)) { - // Make sure Xposed work - XposedHelpers.findAndHookMethod(XposedApp.class.getName(), lpparam.classLoader, "isEnhancementEnabled", XC_MethodReplacement.returnConstant(true)); - // XposedHelpers.findAndHookMethod(StatusInstallerFragment.class.getName(), lpparam.classLoader, "isSELinuxEnforced", XC_MethodReplacement.returnConstant(SELinuxHelper.isSELinuxEnforced())); - } - } - -} \ No newline at end of file diff --git a/app/src/main/res/xml/prefs.xml b/app/src/main/res/xml/prefs.xml index d6acd147..5a0b53b8 100644 --- a/app/src/main/res/xml/prefs.xml +++ b/app/src/main/res/xml/prefs.xml @@ -154,13 +154,6 @@ android:title="@string/pref_title_enable_boot_image_deopt" app:iconSpaceReserved="false" /> - - - - - - - - - - - - - \ No newline at end of file