Enhance enhance!
This commit is contained in:
parent
c460571a3e
commit
b235892098
|
|
@ -0,0 +1 @@
|
|||
org.meowcat.edxposed.manager.xposed.Enhancement
|
||||
|
|
@ -26,6 +26,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
|||
import com.takisoft.preferencex.PreferenceFragmentCompat;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
import org.meowcat.edxposed.manager.adapters.AppHelper;
|
||||
import org.meowcat.edxposed.manager.adapters.BlackListAdapter;
|
||||
import org.meowcat.edxposed.manager.databinding.ActivitySettingsBinding;
|
||||
import org.meowcat.edxposed.manager.util.RepoLoader;
|
||||
import org.meowcat.edxposed.manager.widget.IntegerListPreference;
|
||||
|
|
@ -34,6 +36,7 @@ import java.io.File;
|
|||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SettingsActivity extends BaseActivity {
|
||||
private static final String KEY_PREFIX = SettingsActivity.class.getName() + '.';
|
||||
|
|
@ -111,6 +114,8 @@ public class SettingsActivity extends BaseActivity {
|
|||
|
||||
@SuppressWarnings({"ResultOfMethodCallIgnored", "deprecation"})
|
||||
public static class SettingsFragment extends PreferenceFragmentCompat {
|
||||
private static final File pretendXposedInstallerFlag = new File(XposedApp.BASE_DIR + "conf/pretend_xposed_installer");
|
||||
private static final File hideEdXposedManagerFlag = new File(XposedApp.BASE_DIR + "conf/hide_edxposed_manager");
|
||||
static final File disableResourcesFlag = new File(XposedApp.BASE_DIR + "conf/disable_resources");
|
||||
static final File dynamicModulesFlag = new File(XposedApp.BASE_DIR + "conf/dynamicmodules");
|
||||
static final File deoptBootFlag = new File(XposedApp.BASE_DIR + "conf/deoptbootimage");
|
||||
|
|
@ -486,6 +491,74 @@ public class SettingsActivity extends BaseActivity {
|
|||
return true;
|
||||
});
|
||||
updatePreference(!md2.isChecked());
|
||||
|
||||
Preference enhancement_status = findPreference("enhancement_status");
|
||||
Objects.requireNonNull(enhancement_status).setSummary(StatusInstallerFragment.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(), null).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(), null).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());
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ public class PackageChangeReceiver extends BroadcastReceiver {
|
|||
|
||||
moduleUtil = getModuleUtilInstance();
|
||||
|
||||
moduleUtil.updateModulesList(false);
|
||||
InstalledModule module = ModuleUtil.getInstance().reloadSingleModule(packageName);
|
||||
if (module == null
|
||||
|| intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
|
||||
|
|
@ -58,13 +59,11 @@ public class PackageChangeReceiver extends BroadcastReceiver {
|
|||
// Xposed mod
|
||||
if (moduleUtil.isModuleEnabled(packageName)) {
|
||||
moduleUtil.setModuleEnabled(packageName, false);
|
||||
moduleUtil.updateModulesList(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (moduleUtil.isModuleEnabled(packageName)) {
|
||||
moduleUtil.updateModulesList(false);
|
||||
NotificationUtil.showModulesUpdatedNotification();
|
||||
} else {
|
||||
NotificationUtil.showNotActivatedNotification(packageName, module.getAppName());
|
||||
|
|
|
|||
|
|
@ -1,6 +1,19 @@
|
|||
package org.meowcat.edxposed.manager.xposed;
|
||||
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 androidx.annotation.Keep;
|
||||
|
||||
import org.meowcat.edxposed.manager.StatusInstallerFragment;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.robv.android.xposed.IXposedHookLoadPackage;
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
import de.robv.android.xposed.XC_MethodReplacement;
|
||||
|
|
@ -8,12 +21,45 @@ import de.robv.android.xposed.XposedBridge;
|
|||
import de.robv.android.xposed.XposedHelpers;
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||
|
||||
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
|
||||
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 List modulesList = null;
|
||||
|
||||
private static boolean getFlagState(int user, String flag) {
|
||||
return new File(String.format("/data/user_de/%s/%s/conf/%s", user, APPLICATION_ID, flag)).exists();
|
||||
}
|
||||
|
||||
private static List getModulesList(int user) {
|
||||
if (modulesList != null) {
|
||||
return modulesList;
|
||||
}
|
||||
final File listFile = new File(String.format("/data/user_de/%s/%s/conf/enabled_modules.list", user, APPLICATION_ID));
|
||||
List<String> list = new ArrayList<>();
|
||||
try {
|
||||
FileReader fileReader = new FileReader(listFile);
|
||||
BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
String str;
|
||||
while ((str = bufferedReader.readLine()) != null) {
|
||||
list.add(str);
|
||||
}
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
modulesList = list;
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void hookAllMethods(String className, ClassLoader classLoader, String methodName, XC_MethodHook callback) {
|
||||
try {
|
||||
Class<?> hookClass = XposedHelpers.findClassIfExists(className, classLoader);
|
||||
|
|
@ -27,24 +73,165 @@ public class Enhancement implements IXposedHookLoadPackage {
|
|||
@Override
|
||||
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
if (lpparam.packageName.equals("android")) {
|
||||
// Hook PM to pretend to have legacy Xposed Installer installed
|
||||
// android.app.ApplicationPackageManager.getInstalledApplicationsAsUser(int flag, int userId)
|
||||
findAndHookMethod("android.app.ApplicationPackageManager", lpparam.classLoader, "getInstalledApplicationsAsUser", int.class, int.class, new XC_MethodHook() {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
if (param.args != null && param.args[0] != null) {
|
||||
final int userId = (int) param.args[1];
|
||||
|
||||
boolean isXposedModule = false;
|
||||
final String[] packages =
|
||||
(String[]) XposedHelpers.callMethod(param.thisObject, "getPackagesForUid", Binder.getCallingUid());
|
||||
for (String packageName : packages) {
|
||||
if (packageName.equals(APPLICATION_ID)) {
|
||||
return;
|
||||
}
|
||||
if (getModulesList(userId).contains(packageName)) {
|
||||
isXposedModule = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") List<ApplicationInfo> applicationInfoList = (List<ApplicationInfo>) param.getResult();
|
||||
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)) {
|
||||
applicationInfoList.remove(applicationInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
param.setResult(applicationInfoList);
|
||||
}
|
||||
}
|
||||
});
|
||||
// android.app.ApplicationPackageManager.getInstalledPackagesAsUser(int flag, int userId)
|
||||
findAndHookMethod("android.app.ApplicationPackageManager", lpparam.classLoader, "getInstalledPackagesAsUser", int.class, int.class, new XC_MethodHook() {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
if (param.args != null && param.args[0] != null) {
|
||||
final int userId = (int) param.args[1];
|
||||
|
||||
boolean isXposedModule = false;
|
||||
final String[] packages =
|
||||
(String[]) XposedHelpers.callMethod(param.thisObject, "getPackagesForUid", Binder.getCallingUid());
|
||||
for (String packageName : packages) {
|
||||
if (packageName.equals(APPLICATION_ID)) {
|
||||
return;
|
||||
}
|
||||
if (getModulesList(userId).contains(packageName)) {
|
||||
isXposedModule = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") List<PackageInfo> packageInfoList = (List<PackageInfo>) param.getResult();
|
||||
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)) {
|
||||
packageInfoList.remove(packageInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
param.setResult(packageInfoList);
|
||||
}
|
||||
}
|
||||
});
|
||||
// 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) {
|
||||
if (param.args[0].equals(LEGACY_INSTALLER)) {
|
||||
param.args[0] = APPLICATION_ID;
|
||||
final int userId = (int) param.args[2];
|
||||
|
||||
boolean isXposedModule = false;
|
||||
final String[] packages =
|
||||
(String[]) XposedHelpers.callMethod(param.thisObject, "getPackagesForUid", Binder.getCallingUid());
|
||||
for (String packageName : packages) {
|
||||
if (packageName.equals(APPLICATION_ID)) {
|
||||
return;
|
||||
}
|
||||
if (getModulesList(userId).contains(packageName)) {
|
||||
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.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) {
|
||||
if (param.args[0].equals(LEGACY_INSTALLER)) {
|
||||
param.args[0] = APPLICATION_ID;
|
||||
final int userId = (int) param.args[2];
|
||||
|
||||
boolean isXposedModule = false;
|
||||
final String[] packages =
|
||||
(String[]) XposedHelpers.callMethod(param.thisObject, "getPackagesForUid", Binder.getCallingUid());
|
||||
for (String packageName : packages) {
|
||||
if (packageName.equals(APPLICATION_ID)) {
|
||||
return;
|
||||
}
|
||||
if (getModulesList(userId).contains(packageName)) {
|
||||
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.setResult(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -84,7 +271,8 @@ public class Enhancement implements IXposedHookLoadPackage {
|
|||
}
|
||||
} else if (lpparam.packageName.equals(APPLICATION_ID)) {
|
||||
// Make sure Xposed work
|
||||
XposedHelpers.findAndHookMethod("org.meowcat.edxposed.manager.StatusInstallerFragment", lpparam.classLoader, "isEnhancementEnabled", XC_MethodReplacement.returnConstant(true));
|
||||
XposedHelpers.findAndHookMethod(StatusInstallerFragment.class.getName(), lpparam.classLoader, "isEnhancementEnabled", XC_MethodReplacement.returnConstant(true));
|
||||
// XposedHelpers.findAndHookMethod(StatusInstallerFragment.class.getName(), lpparam.classLoader, "isSELinuxEnforced", XC_MethodReplacement.returnConstant(SELinuxHelper.isSELinuxEnforced()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -302,6 +302,14 @@
|
|||
<string name="colorized_action_bar">着色应用栏</string>
|
||||
<string name="settings_group_theme">主题</string>
|
||||
<string name="material_design_2">惨白设计</string>
|
||||
<string name="xposed_description">启用 EdXposed 的增强功能:\n判断 Xposed 是否正常工作\n移除针对 EdXposed 的后台限制\n假装安装了 Xposed Installer</string>
|
||||
<string name="xposed_description">启用 EdXposed 的增强功能:\n - 判断 Xposed 是否正常工作\n - 移除针对 EdXposed 的后台限制\n - 假装安装了 Xposed Installer\n - 隐藏 EdXposed Manager</string>
|
||||
<string name="status_enhancement">增强模式已激活</string>
|
||||
<string name="settings_group_enhancement">增强模式</string>
|
||||
<string name="settings_title_enhancement">增强模式状态</string>
|
||||
<string name="settings_summary_enhancement">未激活\n你可以在「模块」中启用增强模块</string>
|
||||
<string name="settings_summary_enhancement_enabled">已激活</string>
|
||||
<string name="settings_title_pretend_xposed_installer">Xposed Installer 伪装</string>
|
||||
<string name="settings_summary_pretend_xposed_installer">假装已安装 Xposed Installer 来使一些过时但有用的模块正常工作\n注:开启此功能可能会被某些软件(如 RootBeer)检测到 EdXposed</string>
|
||||
<string name="settings_title_hide_edxposed_manager">隐藏 EdXposed Manager</string>
|
||||
<string name="settings_summary_hide_edxposed_manager">防止软件检测到 EdXposed Manager\n注:模块可能无法正常打开 Manager 界面</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -333,7 +333,15 @@
|
|||
<string name="colorized_action_bar">Colorized action bar</string>
|
||||
<string name="settings_group_theme">Theme</string>
|
||||
<string name="material_design_2">Material Design 2</string>
|
||||
<string name="xposed_description">Enable EdXposed enhancements:\nRemove background restrictions on EdXposed\nDetermine if Xposed is working properly\nPretend to have Xposed Installer installed</string>
|
||||
<string name="xposed_description">Enable EdXposed enhancements:\nRemove background restrictions on EdXposed\nDetermine if Xposed is working properly\nPretend to have Xposed Installer installed\nHide EdXposed Manager</string>
|
||||
<string name="status_enhancement">Enhancement mode</string>
|
||||
<string name="settings_group_enhancement">Enhancement mode</string>
|
||||
<string name="settings_title_enhancement">Enhancement mode status</string>
|
||||
<string name="settings_summary_enhancement">Disabled\nYou can enable enhancement mode in the module</string>
|
||||
<string name="settings_summary_enhancement_enabled">Enabled</string>
|
||||
<string name="settings_title_pretend_xposed_installer">Pretend to have Xposed Installer installed</string>
|
||||
<string name="settings_summary_pretend_xposed_installer">Pretend that Xposed Installer is installed to make some outdated but useful modules work\nWARNING: Some software (eg. RootBeer) may detect that EdXposed when this function is turned on</string>
|
||||
<string name="settings_title_hide_edxposed_manager">Hide EdXposed Manager</string>
|
||||
<string name="settings_summary_hide_edxposed_manager">Prevent the software from detecting EdXposed Manager\nWARNING: Modules may not be able to start the Manager UI properly</string>
|
||||
<string name="version_x">Version %d</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -189,4 +189,27 @@
|
|||
app:iconSpaceReserved="false" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="group_enhancement"
|
||||
android:title="@string/settings_group_enhancement">
|
||||
|
||||
<Preference
|
||||
android:key="enhancement_status"
|
||||
android:title="@string/settings_title_enhancement"
|
||||
android:summary="@string/settings_summary_enhancement" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="pretend_xposed_installer"
|
||||
android:summary="@string/settings_summary_pretend_xposed_installer"
|
||||
android:title="@string/settings_title_pretend_xposed_installer" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="hide_edxposed_manager"
|
||||
android:summary="@string/settings_summary_hide_edxposed_manager"
|
||||
android:title="@string/settings_title_hide_edxposed_manager" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
Loading…
Reference in New Issue