├── framework-compile ├── .gitignore ├── consumer-rules.pro ├── src │ └── main │ │ ├── java │ │ └── android │ │ │ ├── app │ │ │ ├── LoadedApk.java │ │ │ └── ActivityThread.java │ │ │ └── content │ │ │ └── res │ │ │ └── CompatibilityInfo.java │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── app ├── .gitignore ├── src │ ├── main │ │ ├── assets │ │ │ └── xposed_init │ │ ├── cpp │ │ │ ├── hook │ │ │ │ ├── hook_time.h │ │ │ │ ├── hook_dlfcn.h │ │ │ │ ├── hook_env.h │ │ │ │ ├── hook_io.h │ │ │ │ ├── hook_string.h │ │ │ │ ├── hook_vfs.h │ │ │ │ ├── hook_properties.h │ │ │ │ ├── hook_syscall.h │ │ │ │ ├── canonicalize.h │ │ │ │ ├── hook_unistd.h │ │ │ │ ├── hook_exec.h │ │ │ │ ├── hook_stat.h │ │ │ │ ├── hook_java_native.h │ │ │ │ ├── hook_common.cpp │ │ │ │ ├── hook_env.cpp │ │ │ │ ├── hook_string.cpp │ │ │ │ ├── hook_time.cpp │ │ │ │ ├── hook_jni_native_interface.h │ │ │ │ ├── hook.map.txt │ │ │ │ ├── hook_vfs.cpp │ │ │ │ ├── hook_properties.cpp │ │ │ │ └── hook_stat.cpp │ │ │ ├── common │ │ │ │ ├── module_config.h │ │ │ │ ├── gtype.h │ │ │ │ ├── alog.h │ │ │ │ ├── maps_util.h │ │ │ │ ├── scoped_local_ref.h │ │ │ │ └── scoped_utf_chars.h │ │ │ ├── module_config.h.in │ │ │ └── interface │ │ │ │ └── variable_length_object.h │ │ ├── ic_launcher-playstore.png │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_round.png │ │ │ │ └── ic_launcher_foreground.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── menu │ │ │ │ ├── menu_setting.xml │ │ │ │ ├── navigation.xml │ │ │ │ └── menu_edit.xml │ │ │ ├── values │ │ │ │ ├── attrs.xml │ │ │ │ ├── arrays.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── shape.xml │ │ │ │ ├── colors.xml │ │ │ │ └── type.xml │ │ │ ├── drawable │ │ │ │ ├── ic_arrow_24dp.xml │ │ │ │ ├── ic_add_black_24dp.xml │ │ │ │ ├── ic_state_warning_24dp.xml │ │ │ │ ├── ic_modify_24dp.xml │ │ │ │ ├── ic_state_normal_24dp.xml │ │ │ │ ├── ic_descriptor_24dp.xml │ │ │ │ ├── ic_sync_24dp.xml │ │ │ │ ├── ic_wechat_public_24dp.xml │ │ │ │ ├── ic_delete_24dp.xml │ │ │ │ ├── ic_shared_24dp.xml │ │ │ │ ├── ic_github_24dp.xml │ │ │ │ ├── ic_open_file_24dp.xml │ │ │ │ ├── ic_donate_24dp.xml │ │ │ │ ├── ic_wechat_24dp.xml │ │ │ │ └── ic_setting_24dp.xml │ │ │ ├── layout │ │ │ │ ├── fragment_recycler_view.xml │ │ │ │ ├── item_switch_layout.xml │ │ │ │ ├── select_add_view.xml │ │ │ │ ├── recycle_progress_layout.xml │ │ │ │ ├── appcompat_app_bar.xml │ │ │ │ ├── settings_activity.xml │ │ │ │ ├── main_fragment_item.xml │ │ │ │ ├── recycle_add_item_layout.xml │ │ │ │ ├── edit_item_dialog_fragment.xml │ │ │ │ ├── fragment_string_item.xml │ │ │ │ ├── edit_string_view.xml │ │ │ │ ├── item_card_view.xml │ │ │ │ ├── package_add_item_layout.xml │ │ │ │ ├── key_value_add_view_layout.xml │ │ │ │ └── item_fragment.xml │ │ │ └── xml │ │ │ │ └── setting_preferences.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── sanfengandroid │ │ │ │ ├── xp │ │ │ │ ├── hooks │ │ │ │ │ ├── IHook.java │ │ │ │ │ ├── XposedFilter.java │ │ │ │ │ ├── HookSettingContentProvider.java │ │ │ │ │ ├── HookDebugCheck.java │ │ │ │ │ └── HookNativeMethodChecked.java │ │ │ │ ├── ProcessMode.java │ │ │ │ ├── XpDataMode.java │ │ │ │ ├── ObservableMap.java │ │ │ │ └── RemoteCall.java │ │ │ │ ├── common │ │ │ │ ├── model │ │ │ │ │ ├── StackElementModel.java │ │ │ │ │ ├── base │ │ │ │ │ │ ├── DataModelFilterable.java │ │ │ │ │ │ ├── ShowDataModel.java │ │ │ │ │ │ ├── EditDataModel.java │ │ │ │ │ │ ├── BaseShowDataModel.java │ │ │ │ │ │ ├── BaseKeyValueEditDataModel.java │ │ │ │ │ │ └── BaseKeyValueModel.java │ │ │ │ │ ├── SymbolBlacklistModel.java │ │ │ │ │ ├── ComponentKeywordModel.java │ │ │ │ │ ├── FileBlacklistModel.java │ │ │ │ │ ├── SystemPropertyModel.java │ │ │ │ │ └── LoadClassModel.java │ │ │ │ ├── Const.java │ │ │ │ ├── proxy │ │ │ │ │ ├── ProxyInputStream.java │ │ │ │ │ └── ProxyOutStream.java │ │ │ │ ├── util │ │ │ │ │ └── NetUtil.java │ │ │ │ └── bean │ │ │ │ │ └── EnvBean.java │ │ │ │ ├── fakeinterface │ │ │ │ ├── NativeHookStatus.java │ │ │ │ ├── MapsMode.java │ │ │ │ ├── FileAccessMask.java │ │ │ │ ├── NativeCall.java │ │ │ │ ├── NativeOption.java │ │ │ │ ├── NativeConfig.java │ │ │ │ └── Installer.java │ │ │ │ └── datafilter │ │ │ │ ├── listener │ │ │ │ ├── ICallExternal.java │ │ │ │ ├── DataModelItemClickListener.java │ │ │ │ ├── OnItemClickListener.java │ │ │ │ └── AppFilterable.java │ │ │ │ ├── viewmodel │ │ │ │ ├── SingleLiveData.java │ │ │ │ └── AppBean.java │ │ │ │ ├── XpApplication.java │ │ │ │ ├── ui │ │ │ │ ├── FileBrowseLayout.java │ │ │ │ ├── activties │ │ │ │ │ └── EditItemDialogActivity.java │ │ │ │ └── ViewAnimation.java │ │ │ │ └── XPContentProvider.java │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── sanfengandroid │ │ │ └── datafilter │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── sanfengandroid │ │ └── datafilter │ │ └── ExampleInstrumentedTest.java └── proguard-rules.pro ├── capture ├── cn │ ├── home.png │ ├── dlsym_hidden.png │ ├── package_hidden.png │ └── package_configuration.png └── en │ ├── home.png │ ├── dlsym_hidden.png │ ├── package_hidden.png │ └── package_configuration.png ├── .gitmodules ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── local.properties.sample ├── docs ├── cn │ └── app_changes.md └── en │ └── app_changes.md ├── settings.gradle ├── gradle.properties ├── .github └── workflows │ └── android.yml └── gradlew.bat /framework-compile/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /framework-compile/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /src/main/libs -------------------------------------------------------------------------------- /app/src/main/assets/xposed_init: -------------------------------------------------------------------------------- 1 | com.sanfengandroid.xp.XposedEntry -------------------------------------------------------------------------------- /capture/cn/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/capture/cn/home.png -------------------------------------------------------------------------------- /capture/en/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/capture/en/home.png -------------------------------------------------------------------------------- /capture/cn/dlsym_hidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/capture/cn/dlsym_hidden.png -------------------------------------------------------------------------------- /capture/en/dlsym_hidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/capture/en/dlsym_hidden.png -------------------------------------------------------------------------------- /capture/cn/package_hidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/capture/cn/package_hidden.png -------------------------------------------------------------------------------- /capture/en/package_hidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/capture/en/package_hidden.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "fake-linker"] 2 | path = fake-linker 3 | url = https://github.com/sanfengAndroid/fake-linker.git 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /capture/cn/package_configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/capture/cn/package_configuration.png -------------------------------------------------------------------------------- /capture/en/package_configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/capture/en/package_configuration.png -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_time.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "hook_common.h" -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/cpp/common/module_config.h: -------------------------------------------------------------------------------- 1 | 2 | #define HOOK_LOG_LEVEL 2 3 | #define MODULE_VERSION 1500 4 | #define MODULE_VERSION_NAME "1.5" 5 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_dlfcn.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "hook_common.h" 8 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_env.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2021/2/19. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "hook_common.h" 8 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_io.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "hook_common.h" 8 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_string.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "hook_common.h" -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_vfs.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "hook_common.h" 8 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_properties.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2021/2/19. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "hook_common.h" 8 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/cpp/module_config.h.in: -------------------------------------------------------------------------------- 1 | 2 | #define HOOK_LOG_LEVEL @HOOK_LOG_LEVEL@ 3 | #define MODULE_VERSION @MODULE_VERSION@ 4 | #define MODULE_VERSION_NAME @MODULE_VERSION_NAME@ -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanfengAndroid/FakeXposed/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_syscall.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #pragma once 6 | #include "hook_common.h" 7 | 8 | HOOK_DECLARE(long, syscall, long number, ...); -------------------------------------------------------------------------------- /app/src/main/cpp/hook/canonicalize.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/27. 3 | // 4 | 5 | #pragma once 6 | 7 | 8 | extern "C" int canonicalize(const char *original, char *resolved, int len); -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_unistd.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "hook_common.h" 8 | 9 | 10 | HOOK_DECLARE(int, unlink, const char *path); -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_exec.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "hook_common.h" 8 | 9 | HOOK_DECLARE(int, execvp, const char *name, char *const *argv); -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_stat.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "hook_common.h" 8 | 9 | 10 | HOOK_DECLARE(int, stat, const char *path, struct stat *buf); -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_java_native.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2021/2/26. 3 | // 4 | 5 | #pragma once 6 | 7 | #include "hook_common.h" 8 | 9 | class JNHook{ 10 | public: 11 | static bool InitJavaNativeHook(JNIEnv *env); 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | .idea 4 | /local.properties 5 | /.idea/caches 6 | /.idea/libraries 7 | /.idea/modules.xml 8 | /.idea/workspace.xml 9 | /.idea/navEditor.xml 10 | /.idea/assetWizardSettings.xml 11 | .DS_Store 12 | /build 13 | /captures 14 | .externalNativeBuild 15 | .cxx 16 | local.properties 17 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_common.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #include "hook_common.h" 6 | #include 7 | 8 | int force_O_LARGEFILE(int flags) { 9 | #if defined(__LP64__) 10 | return flags; // No need, and aarch64's strace gets confused. 11 | #else 12 | return flags | O_LARGEFILE; 13 | #endif 14 | } -------------------------------------------------------------------------------- /app/src/main/cpp/common/gtype.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by lenovo-s on 2019/4/15. 3 | // 4 | #pragma once 5 | 6 | #include 7 | 8 | #define LINE_MAX 4096 9 | 10 | typedef void *gpointer; 11 | typedef intptr_t gssize; 12 | typedef uintptr_t gsize; 13 | typedef uint64_t gaddress; 14 | #define GSIZE_TO_POINTER(s) ((gpointer) (gsize) (s)) 15 | #define GPOINTER_TO_SIZE(p) ((gsize) (p)) 16 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_env.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2021/2/19. 3 | // 4 | 5 | #include "hook_env.h" 6 | 7 | FUN_INTERCEPT HOOK_DEF(char*, getenv, const char *name) { 8 | LOGMV("Monitor: getenv name: %s", name); 9 | char *value = get_orig_getenv()(name); 10 | if (value == nullptr) { 11 | return value; 12 | } 13 | char *result = FXHandler::EnvironmentReplace(name, value); 14 | return result == nullptr ? value : result; 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_string.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #include "hook_string.h" 6 | 7 | 8 | FUN_INTERCEPT HOOK_DEF(int, strcasecmp, const char *s1, const char *s2) { 9 | LOGMV("s1: %s, s2: %s\n", s1, s2); 10 | return get_orig_strcasecmp()(s1, s2); 11 | } 12 | 13 | FUN_INTERCEPT HOOK_DEF_CPP(const char *, strcasestr, const char *haystack, const char *needle) { 14 | LOGMV("haystack: %s, needle: %s", haystack, needle); 15 | return get_orig_strcasestr()(haystack, needle); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /local.properties.sample: -------------------------------------------------------------------------------- 1 | ## This is the build configuration file 2 | 3 | # Android sign file path 4 | storeFile=string 5 | # Android sign file password 6 | storePassword=string 7 | # Android sign configuration key alias 8 | keyAlias=string 9 | # Android sign key password 10 | keyPassword=string 11 | 12 | # Android build target SDK 13 | targetSdk=int 14 | # Specify the currently build api level, the default is the latest version 30 15 | buildApi=int 16 | # Configure the lowest level of native library to print log, the default is 2 17 | logLevel=int -------------------------------------------------------------------------------- /docs/cn/app_changes.md: -------------------------------------------------------------------------------- 1 | # FakeXposed 更新日志 2 | 3 | ### v1.1 4 | 5 | - 修复低版本创建ContextImpl错误导致后面无法继续 6 | - 修复Android7以下libcutil.so查找属性时导致循环依赖递归调用问题 7 | - 修复Android7以下Java Hook System类问题 8 | - 修复maps规则不生效 9 | - 修复环境变量不生效问题 10 | - 修复重定向路径反向读取问题 11 | - 修复遗漏的syscall open调用号 12 | - 更改新的Runtime.exec匹配规则并生效 13 | - 添加Android 25支持 14 | 15 | ### v1.3 16 | - 修改数据读取模式,调整targetSdk为23,旧版本需要卸载安装,Android9以下直接使用XsharedPreference 17 | - 更改部分Java Hook为Native Java Hook,更加通用稳定和防检测 18 | - 默认添加Edxposed包名到黑名单,解决自身无法访问时其它应用可以访问 19 | - 部分代码优化 20 | 21 | ### v1.4 22 | - 修改包名和应用介绍 23 | - 添加测试选项 24 | 25 | ### v1.5 26 | - 修复Android7以下循环依赖问题 27 | - 修复部分动态代理出错 28 | - 修复部分情况下Android11读取不到文件路径 -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_time.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #include "hook_time.h" 6 | #include 7 | 8 | #include "io_redirect.h" 9 | 10 | FUN_INTERCEPT HOOK_DEF(int, utimes, const char *path, const timeval tv[2]) { 11 | IS_BLACKLIST_FILE(path); 12 | return get_orig_utimes()(IoRedirect::GetRedirect(path), tv); 13 | } 14 | 15 | FUN_INTERCEPT HOOK_DEF(int, utime, const char *path, const void *times) { 16 | IS_BLACKLIST_FILE(path); 17 | return get_orig_utime()(IoRedirect::GetRedirect(path), times); 18 | } 19 | 20 | 21 | FUN_INTERCEPT HOOK_DEF(int, lutimes, const char *path, const struct timeval times[2]) { 22 | IS_BLACKLIST_FILE(path); 23 | return get_orig_lutimes()(IoRedirect::GetRedirect(path), times); 24 | } -------------------------------------------------------------------------------- /app/src/main/cpp/common/alog.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/11/6. 3 | // 4 | #pragma once 5 | 6 | #include 7 | 8 | #define LOG_TAG "HookLog" 9 | 10 | extern int g_log_level; 11 | 12 | #define _PRINT(v, format, ...) \ 13 | do { \ 14 | if(g_log_level <= (v)) __android_log_print(v, LOG_TAG, format, ##__VA_ARGS__); \ 15 | }while(0) 16 | 17 | #define LOGV(format, ...) _PRINT(ANDROID_LOG_VERBOSE, format, ##__VA_ARGS__) 18 | #define LOGD(format, ...) _PRINT(ANDROID_LOG_DEBUG, format, ##__VA_ARGS__) 19 | #define LOGI(format, ...) _PRINT(ANDROID_LOG_INFO, format, ##__VA_ARGS__) 20 | #define LOGW(format, ...) _PRINT(ANDROID_LOG_WARN, format, ##__VA_ARGS__) 21 | #define LOGE(format, ...) _PRINT(ANDROID_LOG_ERROR, format, ##__VA_ARGS__) -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_setting.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /framework-compile/src/main/java/android/app/LoadedApk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package android.app; 19 | 20 | public class LoadedApk { 21 | } 22 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | include ':framework-compile' 19 | include ':app' 20 | rootProject.name = "FakeXposed" 21 | include ':fake-linker' 22 | -------------------------------------------------------------------------------- /framework-compile/src/main/java/android/content/res/CompatibilityInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package android.content.res; 19 | 20 | public class CompatibilityInfo { 21 | } 22 | -------------------------------------------------------------------------------- /framework-compile/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /framework-compile/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/xp/hooks/IHook.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.xp.hooks; 19 | 20 | public interface IHook { 21 | void hook(ClassLoader loader) throws Throwable; 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/xp/ProcessMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.xp; 19 | 20 | public enum ProcessMode { 21 | /** 22 | * 运行在自身进程 23 | */ 24 | SELF, 25 | /* 26 | * 运行在Hook App的进程 27 | * */ 28 | HOOK_APP, 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/res/menu/navigation.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 22 | 23 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # 17 | 18 | #Fri Oct 30 09:33:11 CST 2020 19 | distributionBase=GRADLE_USER_HOME 20 | distributionPath=wrapper/dists 21 | zipStoreBase=GRADLE_USER_HOME 22 | zipStorePath=wrapper/dists 23 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/xp/XpDataMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.xp; 19 | 20 | /** 21 | * 数据可访问的模式 22 | * 23 | * @author sanfengAndroid 24 | */ 25 | 26 | public enum XpDataMode { 27 | /** 28 | * 使用XSharedPreference,自身可访问也使用XSharedPreference 29 | */ 30 | X_SP, 31 | /** 32 | * App ContentProvider模式 33 | */ 34 | APP_CALL 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | Reply 22 | Reply to all 23 | 24 | 25 | 26 | reply 27 | reply_all 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/model/StackElementModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.model; 19 | 20 | public class StackElementModel extends LoadClassModel { 21 | 22 | @Override 23 | public boolean equals(Object o) { 24 | return super.equals(o); 25 | } 26 | 27 | @Override 28 | public int hashCode() { 29 | return super.hashCode(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 23 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20dp 20 | 16dp 21 | 16dp 22 | 260dp 23 | 55dp 24 | 105dp 25 | 8dp 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_state_warning_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 23 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_recycler_view.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/fakeinterface/NativeHookStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.fakeinterface; 19 | 20 | public enum NativeHookStatus { 21 | /* 22 | * 关闭 23 | * */ 24 | DISABLE(0), 25 | /** 26 | * 开启 27 | */ 28 | OPEN(1); 29 | 30 | private final int option; 31 | 32 | NativeHookStatus(int i) { 33 | this.option = i; 34 | } 35 | 36 | public int getOption() { 37 | return option; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | -dontusemixedcaseclassnames 24 | 25 | -keep public class com.sanfengandroid.fakeinterface.* { 26 | *; 27 | } 28 | -keep public class com.sanfengandroid.xp.XposedEntry{ 29 | 30 | } 31 | 32 | -keep public class com.sanfengandroid.datafilter.ui.fragments.MainFragment{ 33 | public static boolean isActive(); 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/model/base/DataModelFilterable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.model.base; 19 | 20 | public interface DataModelFilterable { 21 | /** 22 | * 查询是否匹配 23 | * 24 | * @param condition 过滤添加 25 | * @return 是否过滤 26 | */ 27 | boolean filter(String condition); 28 | 29 | /** 30 | * 查询系统App 31 | * 32 | * @return 是否是系统App 33 | */ 34 | boolean isSystemApp(); 35 | 36 | boolean isXposedApp(); 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/datafilter/listener/ICallExternal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter.listener; 19 | 20 | import android.content.Intent; 21 | 22 | public interface ICallExternal { 23 | 24 | default void callExternalIntent(Intent intent, int code) { 25 | } 26 | 27 | default void setExternalCallback(ICallExternal listener) { 28 | } 29 | 30 | default void callbackExternalResult(int requestCode, int resultCode, Intent data) { 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/Const.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common; 19 | 20 | import android.net.Uri; 21 | 22 | import com.sanfengandroid.datafilter.BuildConfig; 23 | 24 | public class Const { 25 | public static final String GLOBAL_PACKAGE = "all"; 26 | public static final int JAVA_MONITOR_STATE = 1; 27 | private static final String XP_REMOTE_PATH = "xp"; 28 | public static final Uri XP_CONTENT_URI = Uri.parse("content://" + BuildConfig.APPLICATION_ID + "/" + XP_REMOTE_PATH); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/test/java/com/sanfengandroid/datafilter/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter; 19 | 20 | import org.junit.Test; 21 | 22 | import static org.junit.Assert.*; 23 | 24 | /** 25 | * Example local unit test, which will execute on the development machine (host). 26 | * 27 | * @see Testing documentation 28 | */ 29 | public class ExampleUnitTest { 30 | @Test 31 | public void addition_isCorrect() { 32 | assertEquals(4, 2 + 2); 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_modify_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_state_normal_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_switch_layout.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_jni_native_interface.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/18. 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class JNIInterfaceMonitor { 13 | public: 14 | static void Init(const RemoteInvokeInterface *remote, JNIEnv *env); 15 | 16 | static JNIInterfaceMonitor *Get(); 17 | 18 | int InitHookJNIInterfaces(); 19 | 20 | /* 21 | * @param name so名称 22 | * @param contain true则只监听该库,false则监听除该库外的库,如果跟已存在的类型不同则会清空之前的类型 23 | **/ 24 | void AddLibraryMonitor(const char *name, bool contain); 25 | 26 | void RemoveLibraryMonitor(const char *name); 27 | 28 | void AddAddressMonitor(uintptr_t start, size_t end, bool contain); 29 | 30 | void RemoveAddressMonitor(uintptr_t start, size_t end); 31 | 32 | bool InMonitoring(uintptr_t addr); 33 | 34 | private: 35 | JNIInterfaceMonitor(const RemoteInvokeInterface *remote, JNIEnv *env); 36 | 37 | private: 38 | const RemoteInvokeInterface *const remote_; 39 | JNINativeInterface *original_interface; 40 | static JNIInterfaceMonitor *singleton; 41 | std::map monitors_; 42 | bool contain_ = true; 43 | DISALLOW_COPY_AND_ASSIGN(JNIInterfaceMonitor); 44 | }; -------------------------------------------------------------------------------- /framework-compile/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | plugins { 19 | id 'com.android.library' 20 | } 21 | 22 | android { 23 | compileSdkVersion 30 24 | 25 | defaultConfig { 26 | minSdkVersion 21 27 | targetSdkVersion 30 28 | versionCode 1 29 | versionName "1.0" 30 | 31 | consumerProguardFiles "consumer-rules.pro" 32 | } 33 | 34 | buildTypes { 35 | release { 36 | minifyEnabled false 37 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 38 | } 39 | } 40 | } 41 | 42 | dependencies { 43 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/select_add_view.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 22 | 23 | 27 | 28 | -------------------------------------------------------------------------------- /docs/en/app_changes.md: -------------------------------------------------------------------------------- 1 | # FakeXposed Changelog 2 | 3 | ### v1.1 4 | 5 | - Fix the error of creating ContextImpl in low version, which caused the subsequent failure to continue 6 | - Fix the problem of circular dependency recursive calls when libcutil.so below Android7 looks for attributes 7 | - Fix Java Hook System class issues below Android7 8 | - Fix maps rules not taking effect 9 | - Fix environment variables not taking effect 10 | - Fix the redirection path reverse reading problem 11 | - Fix missing syscall open call number 12 | - Change the new Runtime.exec matching rules and take effect 13 | - Add Android 25 support 14 | 15 | ### v1.3 16 | - Modify the data reading mode, adjust the targetSdk to 23, the old version needs to be uninstalled and installed, and use XsharedPreference directly below Android9 17 | - Change some Java Hooks to Native Java Hooks, which are more general and stable and anti-detection 18 | - Add the Edxposed package name to the blacklist by default, so that other applications can access it when you can’t access it 19 | - Partial code optimization 20 | 21 | ### v1.4 22 | - Modify package name and application introduction 23 | - Add test options 24 | 25 | ### v1.5 26 | - Fix the circular dependency issue below Android7 27 | - Fix some dynamic proxy errors 28 | - Fixed some cases where Android11 could not read the file path -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/model/SymbolBlacklistModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.model; 19 | 20 | import android.content.Context; 21 | 22 | import com.sanfengandroid.datafilter.R; 23 | 24 | public class SymbolBlacklistModel extends StringModel { 25 | @Override 26 | protected String getInputHint(Context context) { 27 | return context.getString(R.string.add_item_key_symbol_blacklist); 28 | } 29 | 30 | @Override 31 | public int hashCode() { 32 | return super.hashCode(); 33 | } 34 | 35 | @Override 36 | public boolean equals(Object o) { 37 | return super.equals(o); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_descriptor_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/model/ComponentKeywordModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.model; 19 | 20 | import android.content.Context; 21 | 22 | import com.sanfengandroid.datafilter.R; 23 | 24 | /** 25 | * @author sanfengAndroid 26 | */ 27 | public class ComponentKeywordModel extends StringModel { 28 | @Override 29 | public int hashCode() { 30 | return super.hashCode(); 31 | } 32 | 33 | @Override 34 | public boolean equals(Object o) { 35 | return super.equals(o); 36 | } 37 | 38 | @Override 39 | protected String getInputHint(Context context) { 40 | return context.getString(R.string.add_item_key_component_keyword); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /framework-compile/src/main/java/android/app/ActivityThread.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package android.app; 19 | 20 | import android.content.pm.ApplicationInfo; 21 | import android.content.res.CompatibilityInfo; 22 | 23 | public final class ActivityThread { 24 | 25 | public static ActivityThread currentActivityThread() { 26 | throw new UnsupportedOperationException("Stub"); 27 | } 28 | 29 | public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai, 30 | CompatibilityInfo compatInfo) { 31 | throw new UnsupportedOperationException("Stub"); 32 | } 33 | public static String currentProcessName() { 34 | throw new UnsupportedOperationException("Stub"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/recycle_progress_layout.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 22 | 23 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/datafilter/listener/DataModelItemClickListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter.listener; 19 | 20 | import android.view.View; 21 | 22 | import com.sanfengandroid.common.model.base.ShowDataModel; 23 | 24 | public interface DataModelItemClickListener { 25 | /** 26 | * 单击监听 27 | * 28 | * @param pos 位置 29 | */ 30 | default boolean onItemClick(View view, int pos, T data) { 31 | return false; 32 | } 33 | 34 | /** 35 | * 长按监听 36 | * 37 | * @param pos 位置 38 | */ 39 | default boolean onItemLongClick(View view, int pos, T data) { 40 | return false; 41 | } 42 | 43 | default boolean onItemAddClick() { 44 | return false; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/datafilter/listener/OnItemClickListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter.listener; 19 | 20 | import androidx.recyclerview.widget.RecyclerView; 21 | 22 | /** 23 | * @author sanfengAndroid 24 | */ 25 | public interface OnItemClickListener { 26 | /** 27 | * 单击监听 28 | * 29 | * @param pos 位置 30 | */ 31 | default boolean onItemClick(RecyclerView.Adapter adapter, int pos, Object data) { 32 | return false; 33 | } 34 | 35 | /** 36 | * 长按监听 37 | * 38 | * @param pos 位置 39 | */ 40 | default boolean onItemLongClick(RecyclerView.Adapter adapter, int pos, Object data) { 41 | return false; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/fakeinterface/MapsMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.fakeinterface; 19 | 20 | import android.text.TextUtils; 21 | 22 | public enum MapsMode { 23 | // 不操作 24 | MM_NONE("n"), 25 | // 增加行,暂未实现 26 | MM_ADD("a"), 27 | // 删除行 28 | MM_REMOVE("r"), 29 | // 修改行 30 | MM_MODIFY("m"); 31 | 32 | public final String key; 33 | 34 | MapsMode(String key) { 35 | this.key = key; 36 | } 37 | 38 | public static MapsMode stringToMapsMode(String key) { 39 | for (MapsMode mode : MapsMode.values()) { 40 | if (TextUtils.equals(mode.key, key)) { 41 | return mode; 42 | } 43 | } 44 | throw new UnsupportedOperationException("Unknown maps mode key: " + key); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/fakeinterface/FileAccessMask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.fakeinterface; 19 | 20 | /** 21 | * @author sanfengAndroid 22 | */ 23 | 24 | public enum FileAccessMask { 25 | /** 26 | * 文件权限 27 | */ 28 | SET_UID(04000), 29 | SET_GID(02000), 30 | SET_TX(01000), 31 | USR_READ(0400), 32 | USR_WRITE(0200), 33 | USR_EXEC(0100), 34 | GRP_READ(040), 35 | GRP_WRITE(020), 36 | GRP_EXEC(010), 37 | OTH_READ(04), 38 | OTH_WRITE(02), 39 | OTH_EXEC(01), 40 | ONLY_400(0400), 41 | ONLY_644(0644), 42 | ONLY_744(0744), 43 | ONLY_777(0777), 44 | ONLY_700(0700); 45 | 46 | public static final int MASK = 07777; 47 | public final int mode; 48 | 49 | FileAccessMask(int i) { 50 | mode = i; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/proxy/ProxyInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.proxy; 19 | 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | 23 | public class ProxyInputStream extends InputStream { 24 | private final byte[] input; 25 | private final int size; 26 | private int index = 0; 27 | 28 | public ProxyInputStream(String input) { 29 | if (input == null) { 30 | this.input = null; 31 | this.size = 0; 32 | } else { 33 | this.input = input.getBytes(); 34 | this.size = this.input.length; 35 | } 36 | } 37 | 38 | @Override 39 | public int read() throws IOException { 40 | if (index < size) { 41 | return input[index++]; 42 | } 43 | return -1; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sync_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/fakeinterface/NativeCall.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.fakeinterface; 19 | 20 | import com.sanfengandroid.common.Const; 21 | import com.sanfengandroid.common.bean.EnvBean; 22 | import com.sanfengandroid.common.util.LogUtil; 23 | 24 | /** 25 | * native回调java 26 | */ 27 | public class NativeCall { 28 | private static final String TAG = NativeCall.class.getSimpleName(); 29 | 30 | public static String nativeReplaceEnv(String name, String value) { 31 | EnvBean bean = GlobalConfig.getEnvBlacklistValue(name); 32 | if (bean != null) { 33 | String replace = bean.replace(value); 34 | LogUtil.w(Const.JAVA_MONITOR_STATE, "native get env name: %s, orig value: %s, replace: %s", name, value, replace); 35 | return replace; 36 | } 37 | return null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/appcompat_app_bar.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 25 | 26 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/model/base/ShowDataModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.model.base; 19 | 20 | import androidx.recyclerview.widget.RecyclerView; 21 | 22 | import org.json.JSONException; 23 | import org.json.JSONObject; 24 | 25 | 26 | /** 27 | * 子类应重写equals方法才能保证正常添加和删除 28 | * 29 | * @author sanfengAndroid 30 | */ 31 | public interface ShowDataModel { 32 | 33 | /** 34 | * 获取该数据源绑定的布局 35 | * 36 | * @return 布局资源id 37 | */ 38 | int getLayoutResId(); 39 | 40 | /** 41 | * 动态绑定视图 42 | * 43 | * @param vh 该项viewHolder 44 | */ 45 | void bindView(RecyclerView.ViewHolder vh); 46 | 47 | 48 | JSONObject serialization() throws JSONException; 49 | 50 | void unSerialization(JSONObject json) throws JSONException; 51 | 52 | void hookAvailable(boolean available); 53 | 54 | boolean isAvailable(); 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/proxy/ProxyOutStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.proxy; 19 | 20 | import java.io.IOException; 21 | import java.io.OutputStream; 22 | 23 | public class ProxyOutStream extends OutputStream { 24 | private final byte[] out; 25 | private final int size; 26 | private final OutputStream orig; 27 | 28 | private int index = 0; 29 | 30 | public ProxyOutStream(OutputStream orig, String out) { 31 | if (out == null) { 32 | this.out = null; 33 | this.size = 0; 34 | } else { 35 | this.out = out.getBytes(); 36 | this.size = this.out.length; 37 | } 38 | this.orig = orig; 39 | } 40 | 41 | 42 | @Override 43 | public void write(int b) throws IOException { 44 | if (index < size) { 45 | orig.write(out[index++]); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_wechat_public_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_edit.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 26 | 33 | 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/fakeinterface/NativeOption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.fakeinterface; 19 | 20 | /** 21 | * 对应native层几种黑名单 22 | * 23 | * @author sanfengAndroid 24 | */ 25 | public class NativeOption { 26 | 27 | public enum NativeIntOption { 28 | /** 29 | * 文件黑名单 30 | */ 31 | FILE_BLACKLIST, 32 | /** 33 | * 符号黑名单 34 | */ 35 | SYMBOL_BLACKLIST, 36 | /** 37 | * maps文件规则 38 | */ 39 | MAPS_RULE 40 | } 41 | 42 | public enum NativeStringOption { 43 | /** 44 | * 全局系统属性 45 | */ 46 | SYSTEM_PROPERTY, 47 | 48 | /** 49 | * 类黑名单 50 | */ 51 | CLASS_BLACKLIST, 52 | 53 | /** 54 | * 堆栈类黑名单 55 | */ 56 | STACK_CLASS_BLACKLIST, 57 | /** 58 | * 环境变量 59 | */ 60 | ENVIRONMENT, 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/sanfengandroid/datafilter/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter; 19 | 20 | import android.content.Context; 21 | 22 | import androidx.test.platform.app.InstrumentationRegistry; 23 | import androidx.test.ext.junit.runners.AndroidJUnit4; 24 | 25 | import org.junit.Test; 26 | import org.junit.runner.RunWith; 27 | 28 | import static org.junit.Assert.*; 29 | 30 | /** 31 | * Instrumented test, which will execute on an Android device. 32 | * 33 | * @see Testing documentation 34 | */ 35 | @RunWith(AndroidJUnit4.class) 36 | public class ExampleInstrumentedTest { 37 | @Test 38 | public void useAppContext() { 39 | // Context of the app under test. 40 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 41 | assertEquals("com.sanfengandroid.fakexposed", appContext.getPackageName()); 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/settings_activity.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 22 | 23 | 28 | 29 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/values/shape.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 29 | 30 | 31 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/main_fragment_item.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 26 | 27 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_shared_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/xp/hooks/XposedFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.xp.hooks; 19 | 20 | import com.sanfengandroid.common.util.LogUtil; 21 | 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | /** 26 | * @author sanfengAndroid 27 | * @date 2020/10/30 28 | */ 29 | public class XposedFilter implements IHook { 30 | public static final String TAG = XposedFilter.class.getSimpleName(); 31 | private final List hooks = new ArrayList<>(); 32 | 33 | public XposedFilter() { 34 | hooks.add(new HookDebugCheck()); 35 | hooks.add(new HookSystemClass()); 36 | hooks.add(new HookSystemComponent()); 37 | hooks.add(new HookClassLoad()); 38 | hooks.add(new HookNativeMethodChecked()); 39 | } 40 | 41 | @Override 42 | public void hook(ClassLoader loader) { 43 | for (IHook hook : hooks) { 44 | try { 45 | hook.hook(loader); 46 | } catch (Throwable e) { 47 | LogUtil.e(TAG, "Hook java error", e); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_github_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/model/FileBlacklistModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.model; 19 | 20 | import android.content.Context; 21 | import android.view.View; 22 | 23 | import com.google.android.material.textfield.TextInputLayout; 24 | import com.sanfengandroid.datafilter.R; 25 | import com.sanfengandroid.datafilter.ui.FileBrowseLayout; 26 | 27 | public class FileBlacklistModel extends StringModel { 28 | 29 | @Override 30 | protected String getInputHint(Context context) { 31 | return context.getString(R.string.add_item_key_file_blacklist); 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | return super.hashCode(); 37 | } 38 | 39 | @Override 40 | public boolean equals(Object o) { 41 | return super.equals(o); 42 | } 43 | 44 | @Override 45 | public View onCreateView(Context context) { 46 | View view = super.onCreateView(context); 47 | TextInputLayout tl = view.findViewById(R.id.item_key); 48 | FileBrowseLayout.setFileBrowse(context, tl, (success, path) -> et.setText(path)); 49 | return view; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/res/layout/recycle_add_item_layout.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 29 | 30 | 38 | 39 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # 17 | 18 | # Project-wide Gradle settings. 19 | # IDE (e.g. Android Studio) users: 20 | # Gradle settings configured through the IDE *will override* 21 | # any settings specified in this file. 22 | # For more details on how to configure your build environment visit 23 | # http://www.gradle.org/docs/current/userguide/build_environment.html 24 | # Specifies the JVM arguments used for the daemon process. 25 | # The setting is particularly useful for tweaking memory settings. 26 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 27 | # When configured, Gradle will run in incubating parallel mode. 28 | # This option should only be used with decoupled projects. More details, visit 29 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 30 | # org.gradle.parallel=true 31 | # AndroidX package structure to make it clearer which packages are bundled with the 32 | # Android operating system, and which are packaged with your app"s APK 33 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 34 | android.useAndroidX=true 35 | # Automatically convert third-party libraries to use AndroidX 36 | android.enableJetifier=true 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/model/base/EditDataModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.model.base; 19 | 20 | 21 | import android.content.Context; 22 | import android.view.View; 23 | import android.widget.Filter; 24 | 25 | /** 26 | * 添加数据模型 27 | * 28 | * @author sanfengAndroid 29 | */ 30 | public interface EditDataModel { 31 | 32 | /** 33 | * 对具体的模型创建布局 34 | * 35 | * @param context 上下文 36 | * @return 布局 37 | */ 38 | default View onCreateView(Context context) { 39 | return null; 40 | } 41 | 42 | /** 43 | * 保存数据回调,这里也做一些数据校验 44 | */ 45 | default void onSave() { 46 | } 47 | 48 | /** 49 | * 判断已经修改 50 | * 51 | * @return 已经改变返回true 52 | */ 53 | default boolean hasChange() { 54 | return false; 55 | } 56 | 57 | default void bindData(Context context, ShowDataModel data, int index) { 58 | } 59 | 60 | default boolean showFilter() { 61 | return false; 62 | } 63 | 64 | default boolean showFilterSystem() { 65 | return false; 66 | } 67 | 68 | default Filter getFilter() { 69 | return null; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/datafilter/viewmodel/SingleLiveData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter.viewmodel; 19 | 20 | import androidx.annotation.MainThread; 21 | import androidx.annotation.NonNull; 22 | import androidx.lifecycle.LifecycleOwner; 23 | import androidx.lifecycle.MutableLiveData; 24 | import androidx.lifecycle.Observer; 25 | 26 | import java.util.concurrent.atomic.AtomicBoolean; 27 | 28 | /** 29 | * @author sanfengAndroid 30 | */ 31 | public class SingleLiveData extends MutableLiveData { 32 | private final AtomicBoolean mPending = new AtomicBoolean(false); 33 | 34 | @MainThread 35 | @Override 36 | public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) { 37 | super.observe(owner, t -> { 38 | if (mPending.compareAndSet(true, false)) { 39 | observer.onChanged(t); 40 | } 41 | }); 42 | } 43 | 44 | @MainThread 45 | @Override 46 | public void setValue(T value) { 47 | mPending.set(true); 48 | super.setValue(value); 49 | } 50 | 51 | @MainThread 52 | public void call() { 53 | setValue(null); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook.map.txt: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | #dlfcn 4 | dlopen; 5 | dlsym; 6 | android_dlopen_ext; 7 | android_create_namespace; 8 | #exec 9 | execve; 10 | __execl; 11 | execl; 12 | execle; 13 | execlp; 14 | execvp; 15 | execvpe; 16 | fexecve; 17 | #io 18 | openat; 19 | openat64; 20 | __openat_2; 21 | open; 22 | open64; 23 | __open_2; 24 | fopen; 25 | fopen64; 26 | readdir; 27 | renameat; 28 | rename; 29 | #stat 30 | fchmodat; 31 | chmod; 32 | mkdirat; 33 | mkdir; 34 | fstatat; 35 | fstatat64; 36 | stat; 37 | stat64; 38 | fstat; 39 | fstat64; 40 | lstat; 41 | lstat64; 42 | mknodat; 43 | mknod; 44 | utimensat; 45 | #string 46 | strcasecmp; 47 | strcasestr; 48 | #syscall 49 | syscall; 50 | #time 51 | utimes; 52 | utime; 53 | lutimes; 54 | #unistd 55 | faccessat; 56 | access; 57 | linkat; 58 | link; 59 | unlinkat; 60 | unlink; 61 | rmdir; 62 | chdir; 63 | symlinkat; 64 | symlink; 65 | readlinkat; 66 | readlink; 67 | fchownat; 68 | chown; 69 | lchown; 70 | getcwd; 71 | __getcwd; 72 | truncate; 73 | truncate64; 74 | #vfs 75 | statfs; 76 | statfs64; 77 | __statfs64; 78 | statvfs; 79 | statvfs64; 80 | #environ 81 | getenv; 82 | #properties 83 | __system_property_get; 84 | __system_property_find; 85 | __system_property_read_callback; 86 | #module 87 | fake_load_library_init; 88 | local: 89 | *; 90 | }; -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/datafilter/listener/AppFilterable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter.listener; 19 | 20 | import java.util.UUID; 21 | 22 | /** 23 | * @author sanfengAndroid 24 | */ 25 | public class AppFilterable { 26 | public static final String SYSTEM_MASK = UUID.randomUUID().toString(); 27 | public static final String SYSTEM_UNMASK = UUID.randomUUID().toString(); 28 | public static final String XPOSED_MASK = UUID.randomUUID().toString(); 29 | public static final String XPOSED_UNMASK = UUID.randomUUID().toString(); 30 | public static final String ALL = UUID.randomUUID().toString(); 31 | 32 | public enum Option { 33 | /** 34 | * 显示所有 35 | */ 36 | ALL, 37 | /** 38 | * 显示匹配项 39 | */ 40 | THIS, 41 | /** 42 | * 显示非匹配项 43 | */ 44 | OTHER 45 | } 46 | 47 | public interface SystemAppFilter { 48 | /** 49 | * @param filter 50 | */ 51 | void filterSystemApp(Option filter); 52 | } 53 | 54 | public interface XposedAppFilter { 55 | /** 56 | * @param option 过滤选项 57 | */ 58 | void filterXposedApp(Option option); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_open_file_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 23 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_vfs.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #include "hook_vfs.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "hook_syscall.h" 12 | 13 | static __inline void __bionic_statfs_to_statvfs(const struct statfs *__src, struct statvfs *__dst) { 14 | __dst->f_bsize = __src->f_bsize; 15 | __dst->f_frsize = __src->f_frsize; 16 | __dst->f_blocks = __src->f_blocks; 17 | __dst->f_bfree = __src->f_bfree; 18 | __dst->f_bavail = __src->f_bavail; 19 | __dst->f_files = __src->f_files; 20 | __dst->f_ffree = __src->f_ffree; 21 | __dst->f_favail = __src->f_ffree; 22 | __dst->f_fsid = __src->f_fsid.__val[0] | __BIONIC_CAST(static_cast, uint64_t, __src->f_fsid.__val[1]) << 32; 23 | __dst->f_flag = __src->f_flags; 24 | __dst->f_namemax = __src->f_namelen; 25 | } 26 | 27 | 28 | // fstatfs 传入fd已更改 29 | USE_SYSCALL HOOK_DEF(int, statfs, const char *path, struct statfs *result) { 30 | #define ST_VALID 0x0020 31 | #if defined(__LP64__) 32 | int rc = syscall(__NR_statfs, path, result); 33 | #else 34 | int rc = syscall(__NR_statfs64, path, sizeof(*result), result); 35 | #endif 36 | if (rc != 0) { 37 | return rc; 38 | } 39 | result->f_flags &= ~ST_VALID; 40 | return 0; 41 | } 42 | __strong_alias(statfs64, statfs); 43 | 44 | USE_SYSCALL HOOK_DEF(int, __statfs64, const char *path, size_t size, struct statfs *result) { 45 | #if defined(__LP64__) 46 | int rc = syscall(__NR_statfs, path, result); 47 | #else 48 | int rc = syscall(__NR_statfs64, path, sizeof(*result), result); 49 | #endif 50 | return rc; 51 | } 52 | 53 | STUB_SYMBOL HOOK_DEF(int, statvfs, const char *__path, struct statvfs *__result) { 54 | struct statfs tmp; 55 | int rc = statfs(__path, &tmp); 56 | if (rc != 0) { 57 | return rc; 58 | } 59 | __bionic_statfs_to_statvfs(&tmp, __result); 60 | return 0; 61 | } 62 | __strong_alias(statvfs64, statvfs); -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/fakeinterface/NativeConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.fakeinterface; 19 | 20 | import java.util.ArrayList; 21 | import java.util.HashMap; 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | public enum NativeConfig { 26 | /* 27 | * Java层Runtime.exec调用execvp拦截, 28 | * 目前拦截它会导致子进程不返回 29 | * */ 30 | JAVA_EXECVP("java_execvp"), 31 | RELINK_SYMBOL_FILTER("relink_symbol_filter"); 32 | public static Map nativeConfigs = new HashMap<>(); 33 | 34 | static { 35 | nativeConfigs.put(JAVA_EXECVP.name, NativeHookStatus.DISABLE); 36 | } 37 | 38 | public final String name; 39 | 40 | NativeConfig(String name) { 41 | this.name = name; 42 | } 43 | 44 | public static List configToString() { 45 | List list = new ArrayList<>(); 46 | for (Map.Entry entry : nativeConfigs.entrySet()) { 47 | if (entry.getValue() instanceof NativeHookStatus) { 48 | list.add(entry.getKey() + "=" + ((NativeHookStatus) entry.getValue()).getOption()); 49 | } else if (entry.getValue() instanceof String) { 50 | list.add(entry.getKey() + "=" + entry.getValue()); 51 | } 52 | } 53 | return list; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/edit_item_dialog_fragment.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 26 | 27 | 32 | 33 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/cpp/common/maps_util.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/11/12. 3 | // 4 | #pragma once 5 | 6 | #include "gtype.h" 7 | #include "macros.h" 8 | 9 | struct PageProtect { 10 | gaddress start; 11 | gaddress end; 12 | uint32_t old_protect; 13 | uint32_t new_protect; 14 | PageProtect *next; 15 | }; 16 | 17 | class MapsUtil { 18 | public: 19 | MapsUtil(); 20 | 21 | ~MapsUtil(); 22 | 23 | explicit MapsUtil(const char *library_name); 24 | 25 | bool GetMemoryProtect(void *address); 26 | 27 | bool GetLibraryProtect(const char *library_name); 28 | 29 | bool UnlockAddressProtect(void *address); 30 | 31 | gaddress FindLibraryBase(const char *library_name, const char *mode); 32 | 33 | char *GetLibraryRealPath(const char *library_name); 34 | 35 | bool UnlockPageProtect() const; 36 | 37 | bool RecoveryPageProtect() const; 38 | 39 | bool Found() const { 40 | return page != nullptr; 41 | } 42 | 43 | gaddress GetStartAddress() const{ 44 | return start_address_; 45 | } 46 | 47 | PageProtect *CopyProtect(); 48 | 49 | static bool RecoveryPageProtect(PageProtect *protect); 50 | 51 | static void PageProtectFree(PageProtect *protect); 52 | 53 | private: 54 | inline bool GetMapsLine(); 55 | 56 | inline bool FormatLine(); 57 | 58 | inline int FormatProtect(); 59 | 60 | inline bool MatchPath(); 61 | 62 | inline bool OpenMaps(); 63 | 64 | inline void CloseMaps(); 65 | 66 | void MakeLibraryName(const char *library_name); 67 | 68 | bool CheckPage(); 69 | 70 | inline void PageProtectFree(); 71 | 72 | private: 73 | #define MAPS_LINE_LEG 1024 74 | char line_[MAPS_LINE_LEG]{}; 75 | char path_[MAPS_LINE_LEG]{}; 76 | FILE *maps_fd_ = nullptr; 77 | char library_name_[256]{}; 78 | gaddress start_address_ = 0; 79 | gaddress end_address_ = 0; 80 | char protect_[7]{}; 81 | bool copy_ = false; 82 | public: 83 | PageProtect *page = nullptr; 84 | 85 | DISALLOW_COPY_AND_ASSIGN(MapsUtil); 86 | }; -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/model/base/BaseShowDataModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.model.base; 19 | 20 | import androidx.recyclerview.widget.RecyclerView; 21 | 22 | import com.google.android.material.switchmaterial.SwitchMaterial; 23 | import com.sanfengandroid.datafilter.R; 24 | 25 | import org.json.JSONException; 26 | import org.json.JSONObject; 27 | 28 | public abstract class BaseShowDataModel implements ShowDataModel { 29 | private boolean available = true; 30 | 31 | @Override 32 | public JSONObject serialization() throws JSONException { 33 | JSONObject json = new JSONObject(); 34 | json.put("available", available); 35 | return json; 36 | } 37 | 38 | @Override 39 | public void unSerialization(JSONObject json) throws JSONException { 40 | available = json.getBoolean("available"); 41 | } 42 | 43 | @Override 44 | public void bindView(RecyclerView.ViewHolder vh) { 45 | SwitchMaterial open = vh.itemView.findViewById(R.id.item_switch); 46 | if (open != null) { 47 | open.setChecked(available); 48 | } 49 | } 50 | 51 | @Override 52 | public void hookAvailable(boolean available) { 53 | this.available = available; 54 | } 55 | 56 | @Override 57 | public boolean isAvailable() { 58 | return available; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/res/xml/setting_preferences.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | 26 | 30 | 34 | 38 | 42 | 46 | 47 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | 7 | jobs: 8 | build: 9 | # name: Build Apk on ${{ matrix.os }} 10 | # runs-on: ${{ matrix.os }} 11 | # strategy: 12 | # fail-fast: false 13 | # matrix: 14 | # os: [ ubuntu-latest, windows-latest, macOS-latest ] 15 | name: Build Apk on ubuntu-latest 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - name: Check out 20 | uses: actions/checkout@v2 21 | with: 22 | submodules: 'recursive' 23 | fetch-depth: 0 24 | 25 | - name: set up JDK 1.8 26 | uses: actions/setup-java@v1 27 | with: 28 | java-version: 1.8 29 | 30 | - name: Set up Python 3 31 | uses: actions/setup-python@v2 32 | with: 33 | python-version: '3.x' 34 | 35 | - name: Set up GitHub env (Windows) 36 | if: runner.os == 'Windows' 37 | run: | 38 | echo "ANDROID_SDK_ROOT=$env:ANDROID_SDK_ROOT" >> $env:GITHUB_ENV 39 | 40 | - name: Set up GitHub env (Unix) 41 | if: runner.os != 'Windows' 42 | run: | 43 | echo ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT >> $GITHUB_ENV 44 | 45 | - name: Cache Gradle 46 | uses: actions/cache@v2 47 | with: 48 | path: | 49 | ~/.gradle/caches 50 | ~/.gradle/wrapper 51 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} 52 | restore-keys: ${{ runner.os }}-gradle- 53 | 54 | - name: Grant execute permission for gradlew 55 | run: chmod +x gradlew 56 | 57 | - name: Build release 58 | run: python build.py -vrm -f ${{ secrets.storeFileBase64 }} -s ${{ secrets.signConfig }} -l 3 all 59 | 60 | - name: Build debug 61 | run: python build.py -vm -f ${{ secrets.storeFileBase64 }} -s ${{ secrets.signConfig }} all 62 | 63 | - name: Upload a Build Artifact 64 | if: runner.os == 'Linux' 65 | uses: actions/upload-artifact@v2.2.2 66 | with: 67 | name: ${{ github.sha }} 68 | path: out -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | #FFBB86FC 21 | #FF6200EE 22 | #FF3700B3 23 | #FF03DAC5 24 | #FF018786 25 | #FF000000 26 | #000000 27 | #FFFFFFFF 28 | #FFFFFF 29 | #FF29B6F6 30 | #FF039BE5 31 | #FFBDBDBD 32 | #FF757575 33 | @color/light_blue_400 34 | #cf6679 35 | #b00020 36 | 37 | #3f51b5 38 | #757de8 39 | #002984 40 | #ba68c8 41 | #ee98fb 42 | #883997 43 | #ffffff 44 | #000000 45 | #3DDC84 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/model/SystemPropertyModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.model; 19 | 20 | import android.text.TextUtils; 21 | 22 | import com.sanfengandroid.common.model.base.BaseKeyValueEditDataModel; 23 | import com.sanfengandroid.common.model.base.BaseKeyValueModel; 24 | import com.sanfengandroid.datafilter.R; 25 | import com.sanfengandroid.datafilter.XpApplication; 26 | 27 | public class SystemPropertyModel extends BaseKeyValueModel { 28 | 29 | @Override 30 | public int hashCode() { 31 | return super.hashCode(); 32 | } 33 | 34 | @Override 35 | public boolean equals(Object o) { 36 | return super.equals(o); 37 | } 38 | 39 | public static class SystemPropertyEditModel extends BaseKeyValueEditDataModel { 40 | 41 | @Override 42 | public void onSave() { 43 | String input = etKey.getText().toString(); 44 | if (TextUtils.isEmpty(input)) { 45 | XpApplication.getViewModel().setMessage(R.string.input_empty_content); 46 | return; 47 | } 48 | SystemPropertyModel addModel = new SystemPropertyModel(); 49 | addModel.setKey(input); 50 | addModel.setValue(etValue.getText().toString()); 51 | XpApplication.getViewModel().addDataValue(addModel, index); 52 | XpApplication.getViewModel().setSaveResult(true); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_string_item.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 26 | 27 | 30 | 31 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_donate_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/util/NetUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.util; 19 | 20 | import java.io.BufferedReader; 21 | import java.io.IOException; 22 | import java.io.InputStreamReader; 23 | import java.net.URL; 24 | 25 | import javax.net.ssl.HttpsURLConnection; 26 | 27 | public class NetUtil { 28 | 29 | public static String requestHttps(String path) { 30 | HttpsURLConnection connection = null; 31 | BufferedReader br = null; 32 | try { 33 | URL url = new URL(path); 34 | connection = (HttpsURLConnection) url.openConnection(); 35 | connection.setConnectTimeout(20 * 1000); 36 | connection.setDoInput(true); 37 | connection.setUseCaches(false); 38 | connection.connect(); 39 | 40 | br = new BufferedReader(new InputStreamReader(connection.getInputStream())); 41 | StringBuilder sb = new StringBuilder(); 42 | String line; 43 | while ((line = br.readLine()) != null) { 44 | sb.append(line); 45 | } 46 | return sb.toString(); 47 | } catch (Exception e) { 48 | e.printStackTrace(); 49 | } finally { 50 | if (connection != null) { 51 | connection.disconnect(); 52 | } 53 | if (br != null) { 54 | try { 55 | br.close(); 56 | } catch (IOException ignore) { 57 | } 58 | } 59 | } 60 | return ""; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/cpp/interface/variable_length_object.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/11/18. 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | template 12 | struct VarLengthObject { 13 | size_t len; 14 | T elements[0]; 15 | }; 16 | 17 | template 18 | VarLengthObject *VarLengthObjectAlloc(int len) { 19 | size_t size = sizeof(VarLengthObject) + sizeof(T) * len; 20 | auto *ret = reinterpret_cast *>(malloc(size)); 21 | memset(ret, 0, size); 22 | ret->len = len; 23 | return ret; 24 | } 25 | 26 | template 27 | void VarLengthObjectFree(VarLengthObject *var) { 28 | if (var != nullptr) { 29 | free(var); 30 | } 31 | } 32 | 33 | template 34 | class VarLengthRef { 35 | public: 36 | explicit VarLengthRef(VarLengthObject *_data) : data(_data) {} 37 | 38 | explicit VarLengthRef(int len) { 39 | data = VarLengthObjectAlloc(len); 40 | } 41 | 42 | VarLengthRef(VarLengthRef &&that) noexcept { 43 | data = that.data; 44 | that.data = nullptr; 45 | } 46 | 47 | ~VarLengthRef() { 48 | if (data != nullptr) { 49 | VarLengthObjectFree(data); 50 | } 51 | } 52 | 53 | VarLengthObject *data; 54 | #ifndef DISALLOW_COPY_AND_ASSIGN 55 | #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 56 | TypeName(const TypeName&) = delete; \ 57 | void operator=(const TypeName&) = delete 58 | #endif 59 | DISALLOW_COPY_AND_ASSIGN(VarLengthRef); 60 | }; 61 | 62 | 63 | template 64 | VarLengthObject *VaListToVarLengthObject(int len, va_list &list) { 65 | if (len < 1) { 66 | return nullptr; 67 | } 68 | VarLengthObject *vas = VarLengthObjectAlloc(len); 69 | for (int i = 0; i < len; ++i) { 70 | vas->elements[i] = va_arg(list, T); 71 | } 72 | return vas; 73 | } 74 | 75 | template 76 | VarLengthObject *VaArgsToVarLengthObject(int len, ...) { 77 | if (len < 1) { 78 | return nullptr; 79 | } 80 | va_list list; 81 | va_start(list, len); 82 | 83 | VarLengthObject *result = VaListToVarLengthObject(len, list); 84 | 85 | va_end(list); 86 | return result; 87 | } -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/fakeinterface/Installer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.fakeinterface; 19 | 20 | import android.content.Context; 21 | 22 | import com.sanfengandroid.fakelinker.FileInstaller; 23 | import com.sanfengandroid.datafilter.SPProvider; 24 | 25 | import java.io.File; 26 | 27 | /** 28 | * @author sanfengAndroid 29 | * @date 2020/11/20 30 | */ 31 | public class Installer { 32 | private static boolean root = true; 33 | 34 | public static boolean installHookFile(Context context) throws Exception { 35 | FileInstaller.setConfigPath(NativeHook.getConfigPath()); 36 | setRoot(true); 37 | File[] files = SPProvider.getAllConfigurationFiles(context); 38 | FileInstaller.installFile(context, files, root); 39 | return true; 40 | } 41 | 42 | public static boolean uninstallHookFile(Context context) throws Exception { 43 | FileInstaller.setConfigPath(NativeHook.getConfigPath()); 44 | setRoot(true); 45 | File[] files = SPProvider.getAllConfigurationFiles(context); 46 | if (files == null) { 47 | return true; 48 | } 49 | File[] configs = new File[files.length]; 50 | for (int i = 0; i < configs.length; i++) { 51 | configs[i] = new File(NativeHook.getConfigPath(), files[i].getName()); 52 | } 53 | FileInstaller.uninstallFile(context, configs, root); 54 | return true; 55 | } 56 | 57 | public static void setRoot(boolean root) { 58 | Installer.root = root; 59 | if (root) { 60 | FileInstaller.setFileOwner(0, 0); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/cpp/common/scoped_local_ref.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | 21 | #include 22 | 23 | #include "macros.h" 24 | #include "proxy_jni.h" 25 | 26 | 27 | template 28 | class ScopedLocalRef { 29 | public: 30 | ScopedLocalRef(JNIEnv *env, T localRef) : mEnv(env), proxy_(nullptr), mLocalRef(localRef) { 31 | } 32 | 33 | ScopedLocalRef(ProxyJNIEnv *proxy, T localRef) : mEnv(nullptr), proxy_(proxy), mLocalRef(localRef) { 34 | } 35 | 36 | ~ScopedLocalRef() { 37 | reset(); 38 | } 39 | 40 | void reset(T ptr = nullptr) { 41 | if (ptr != mLocalRef) { 42 | if (mLocalRef != nullptr) { 43 | if (proxy_ != nullptr) { 44 | proxy_->DeleteLocalRef(mLocalRef); 45 | } else { 46 | mEnv->DeleteLocalRef(mLocalRef); 47 | } 48 | } 49 | mLocalRef = ptr; 50 | } 51 | } 52 | 53 | T release() { 54 | T localRef = mLocalRef; 55 | mLocalRef = nullptr; 56 | return localRef; 57 | } 58 | 59 | T get() const { 60 | return mLocalRef; 61 | } 62 | 63 | // Allows "if (scoped_ref == nullptr)" 64 | bool operator==(std::nullptr_t) const { 65 | return mLocalRef == nullptr; 66 | } 67 | 68 | // Allows "if (scoped_ref != nullptr)" 69 | bool operator!=(std::nullptr_t) const { 70 | return mLocalRef != nullptr; 71 | } 72 | 73 | private: 74 | JNIEnv *const mEnv; 75 | T mLocalRef; 76 | ProxyJNIEnv *const proxy_; 77 | 78 | DISALLOW_COPY_AND_ASSIGN(ScopedLocalRef); 79 | }; 80 | 81 | 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/datafilter/XpApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter; 19 | 20 | import android.app.Application; 21 | import android.content.Context; 22 | 23 | import androidx.annotation.NonNull; 24 | import androidx.lifecycle.ViewModelProvider; 25 | import androidx.lifecycle.ViewModelStore; 26 | import androidx.lifecycle.ViewModelStoreOwner; 27 | 28 | import com.sanfengandroid.common.util.Util; 29 | import com.sanfengandroid.xp.ProcessMode; 30 | import com.sanfengandroid.datafilter.viewmodel.ApplicationViewModel; 31 | 32 | public class XpApplication extends Application implements ViewModelStoreOwner { 33 | private static final String TAG = XpApplication.class.getSimpleName(); 34 | private static XpApplication singleton = null; 35 | private ViewModelStore mStore; 36 | private ApplicationViewModel viewModel; 37 | 38 | public static XpApplication getInstance() { 39 | return singleton; 40 | } 41 | 42 | public static ApplicationViewModel getViewModel() { 43 | return singleton.viewModel; 44 | } 45 | 46 | @Override 47 | protected void attachBaseContext(Context base) { 48 | super.attachBaseContext(base); 49 | singleton = this; 50 | if (BuildConfig.APPLICATION_ID.equals(Util.getProcessName(base))) { 51 | mStore = new ViewModelStore(); 52 | viewModel = new ViewModelProvider(this).get(ApplicationViewModel.class); 53 | } 54 | SPProvider.setProcessMode(ProcessMode.SELF); 55 | } 56 | 57 | @NonNull 58 | @Override 59 | public ViewModelStore getViewModelStore() { 60 | return mStore; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/xp/hooks/HookSettingContentProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.xp.hooks; 19 | 20 | import android.content.ContentProvider; 21 | import android.os.Bundle; 22 | 23 | import com.sanfengandroid.common.util.LogUtil; 24 | import com.sanfengandroid.xp.ContentProviderAgent; 25 | import com.sanfengandroid.xp.RemoteCall; 26 | 27 | import de.robv.android.xposed.XC_MethodHook; 28 | import de.robv.android.xposed.XposedHelpers; 29 | 30 | /** 提供数据同步,暂时不使用,因为如果能Hook system_server则意味着拿的到root权限,通过root搬迁配置数据更加方便 31 | * @author sanfengAndroid 32 | */ 33 | public class HookSettingContentProvider implements IHook { 34 | private static final String TAG = HookSettingContentProvider.class.getSimpleName(); 35 | 36 | 37 | @Override 38 | public void hook(ClassLoader loader) throws Throwable { 39 | XposedHelpers.findAndHookMethod("com.android.providers.settings.SettingsProvider", loader, "call", String.class, String.class, Bundle.class, new XC_MethodHook() { 40 | @Override 41 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 42 | String method = (String) param.args[0]; 43 | if (!method.equals(RemoteCall.METHOD_HOOK_FLAG)) { 44 | return; 45 | } 46 | LogUtil.d(TAG, "system provider accept flag: %s, method: %s", param.args[0], param.args[1]); 47 | RemoteCall remoteCall = RemoteCall.nameToRemoteCall((String) param.args[1]); 48 | ContentProvider provider = (ContentProvider) param.thisObject; 49 | param.setResult(ContentProviderAgent.getInstance().invoke(provider.getContext(), remoteCall, (Bundle) param.args[2])); 50 | } 51 | }); 52 | LogUtil.v(TAG, "Hook system providers"); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/edit_string_view.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 23 | 24 | 32 | 33 | 43 | 44 | 45 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_wechat_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/datafilter/ui/FileBrowseLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter.ui; 19 | 20 | import android.app.Activity; 21 | import android.content.Context; 22 | import android.content.Intent; 23 | 24 | import com.google.android.material.textfield.TextInputLayout; 25 | import com.sanfengandroid.common.util.FileChooseUtil; 26 | import com.sanfengandroid.datafilter.R; 27 | import com.sanfengandroid.datafilter.listener.ICallExternal; 28 | 29 | public class FileBrowseLayout { 30 | 31 | public static void setFileBrowse(Context context, TextInputLayout layout, FileBrowseResult callback) { 32 | if (!(context instanceof ICallExternal)) { 33 | layout.setEndIconMode(TextInputLayout.END_ICON_NONE); 34 | return; 35 | } 36 | ICallExternal callExternal = (ICallExternal) context; 37 | layout.setEndIconMode(TextInputLayout.END_ICON_CUSTOM); 38 | layout.setEndIconDrawable(R.drawable.ic_open_file_24dp); 39 | layout.setEndIconOnClickListener(v -> { 40 | callExternal.setExternalCallback(new ICallExternal() { 41 | @Override 42 | public void callbackExternalResult(int requestCode, int resultCode, Intent data) { 43 | boolean success = resultCode == Activity.RESULT_OK && data != null && data.getData() != null; 44 | if (callback != null) { 45 | callback.onResult(success, success ? new FileChooseUtil(context).getChooseFileResultPath(data.getData()) : ""); 46 | } 47 | } 48 | }); 49 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT).setType("*/*"); 50 | callExternal.callExternalIntent(intent, 1); 51 | }); 52 | 53 | } 54 | 55 | public interface FileBrowseResult { 56 | void onResult(boolean success, String path); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_setting_24dp.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/datafilter/ui/activties/EditItemDialogActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter.ui.activties; 19 | 20 | import android.content.Intent; 21 | import android.os.Bundle; 22 | 23 | import androidx.annotation.Nullable; 24 | import androidx.appcompat.app.AppCompatActivity; 25 | 26 | import com.sanfengandroid.datafilter.listener.ICallExternal; 27 | import com.sanfengandroid.datafilter.ui.fragments.EditItemDialogFragment; 28 | 29 | public class EditItemDialogActivity extends AppCompatActivity implements ICallExternal { 30 | private EditItemDialogFragment fragment; 31 | private ICallExternal callback; 32 | 33 | @Override 34 | protected void onCreate(@Nullable Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | if (savedInstanceState == null) { 37 | fragment = new EditItemDialogFragment(); 38 | getSupportFragmentManager().beginTransaction() 39 | .replace(android.R.id.content, fragment, null) 40 | .commitNow(); 41 | } 42 | } 43 | 44 | @Override 45 | public void onBackPressed() { 46 | if (fragment != null && fragment.onBackPressed()) { 47 | return; 48 | } 49 | super.onBackPressed(); 50 | } 51 | 52 | @Override 53 | public void setExternalCallback(ICallExternal listener) { 54 | callback = listener; 55 | } 56 | 57 | @Override 58 | public void callExternalIntent(Intent intent, int code) { 59 | startActivityForResult(intent, code); 60 | } 61 | 62 | @Override 63 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 64 | if (callback != null) { 65 | callback.callbackExternalResult(requestCode, resultCode, data); 66 | } else { 67 | super.onActivityResult(requestCode, resultCode, data); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_properties.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2021/2/19. 3 | // 4 | 5 | #include "hook_properties.h" 6 | #include 7 | #include 8 | /* 9 | * Android 5.0 ~ 8.1 property_get --> __system_property_get 10 | * Android 9.0 ~ 10.0 android::base::GetProperty --> __system_property_find ,__system_property_read_callback 11 | * */ 12 | 13 | // 返回属性值长度,不存在则返回0 14 | FUN_INTERCEPT HOOK_DEF(int, __system_property_get, const char *name, char *value) { 15 | int ret = get_orig___system_property_get()(name, value); 16 | LOGMV("name: %s, value: %s", name, value); 17 | if (ret < 1) { 18 | return ret; 19 | } 20 | if (FXHandler::PropertyIsBlacklisted(name)) { 21 | value[0] = '\0'; 22 | return 0; 23 | } 24 | const char *new_value = FXHandler::PropertyReplace(name, value); 25 | if (new_value != nullptr) { 26 | LOGD("__system_property_get property place old value: %s, new value: %s", value, new_value); 27 | strcpy(value, new_value); 28 | ret = strlen(value); 29 | } 30 | return ret; 31 | } 32 | 33 | FUN_INTERCEPT HOOK_DEF(const prop_info *, __system_property_find, const char *name) { 34 | const prop_info *ret = get_orig___system_property_find()(name); 35 | // 修复Android 7及以下 libcutil 出现的循环依赖问题,会递归查找 36 | if (FXHandler::Get()->api > __ANDROID_API_O__){ 37 | LOGMV("name: %s, result: %p", name, ret); 38 | } 39 | return ret != nullptr && FXHandler::PropertyIsBlacklisted(name) ? nullptr : ret; 40 | } 41 | 42 | std::map callbacks; 43 | 44 | static void handle_system_property(void *cookie, const char *name, const char *value, uint32_t serial) { 45 | void (*callback)(void *, const char *, const char *, uint32_t) = callbacks[cookie]; 46 | const char *new_value = FXHandler::PropertyReplace(name, value); 47 | callback(cookie, name, new_value == nullptr ? value : new_value, serial); 48 | } 49 | 50 | FUN_INTERCEPT HOOK_DEF(void, __system_property_read_callback, 51 | const prop_info *pi, 52 | void (*callback)(void *__cookie, const char *__name, const char *__value, uint32_t __serial), 53 | void *cookie) __INTRODUCED_IN(26) { 54 | // LOGMV("prop_info: %p, cookie: %p", pi, cookie); 55 | if (cookie == nullptr) { 56 | get_orig___system_property_read_callback()(pi, callback, cookie); 57 | return; 58 | } 59 | callbacks[cookie] = callback; 60 | get_orig___system_property_read_callback()(pi, handle_system_property, cookie); 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/bean/EnvBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.bean; 19 | 20 | import android.text.TextUtils; 21 | 22 | import java.util.ArrayList; 23 | import java.util.Collections; 24 | import java.util.List; 25 | import java.util.Objects; 26 | 27 | public class EnvBean { 28 | public String name; 29 | public List regions = Collections.EMPTY_LIST; 30 | 31 | public EnvBean(String name) { 32 | this.name = name; 33 | } 34 | 35 | public EnvBean(String name, String region) { 36 | this.name = name; 37 | regions = new ArrayList<>(1); 38 | regions.add(region); 39 | } 40 | 41 | public EnvBean(String name, List regions) { 42 | this.name = name; 43 | if (regions != null) { 44 | this.regions = regions; 45 | } 46 | } 47 | 48 | public boolean contain(String value) { 49 | if (TextUtils.isEmpty(value)) { 50 | return false; 51 | } 52 | List newRegions = new ArrayList<>(); 53 | for (String region : regions) { 54 | if (value.matches(region)) { 55 | newRegions.add(region); 56 | } 57 | } 58 | if (!newRegions.isEmpty()) { 59 | regions = newRegions; 60 | return true; 61 | } 62 | return false; 63 | } 64 | 65 | public String replace(String value) { 66 | for (String region : regions) { 67 | value = value.replaceAll(region, ""); 68 | } 69 | return value; 70 | } 71 | 72 | @Override 73 | public boolean equals(Object o) { 74 | if (this == o) return true; 75 | if (o == null || getClass() != o.getClass()) return false; 76 | EnvBean bean = (EnvBean) o; 77 | return name.equals(bean.name); 78 | } 79 | 80 | @Override 81 | public int hashCode() { 82 | return Objects.hash(name); 83 | } 84 | } -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/model/base/BaseKeyValueEditDataModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.model.base; 19 | 20 | import android.content.Context; 21 | import android.view.LayoutInflater; 22 | import android.view.View; 23 | import android.widget.EditText; 24 | 25 | import com.google.android.material.textfield.TextInputLayout; 26 | import com.sanfengandroid.datafilter.R; 27 | import com.sanfengandroid.datafilter.viewmodel.ApplicationViewModel; 28 | 29 | public abstract class BaseKeyValueEditDataModel implements EditDataModel { 30 | protected EditText etKey; 31 | protected EditText etValue; 32 | protected int index = ApplicationViewModel.NO_INDEX; 33 | 34 | @Override 35 | public View onCreateView(Context context) { 36 | View view = LayoutInflater.from(context).inflate(R.layout.key_value_add_view_layout, null, false); 37 | TextInputLayout layout = view.findViewById(R.id.item_key); 38 | layout.setHint(getKeyHint(context)); 39 | layout = view.findViewById(R.id.item_value); 40 | layout.setHint(getValueHint(context)); 41 | etKey = view.findViewById(R.id.item_key_edit); 42 | etValue = view.findViewById(R.id.item_value_edit); 43 | return view; 44 | } 45 | 46 | protected String getKeyHint(Context context) { 47 | return context.getString(R.string.add_item_key_property); 48 | } 49 | 50 | protected String getValueHint(Context context) { 51 | return context.getString(R.string.add_item_value_property); 52 | } 53 | 54 | @Override 55 | public void bindData(Context context, ShowDataModel data, int index) { 56 | if (!(data instanceof BaseKeyValueModel)) { 57 | return; 58 | } 59 | BaseKeyValueModel model = (BaseKeyValueModel) data; 60 | this.index = index; 61 | etKey.setText(model.getKey()); 62 | etValue.setText(model.getValue()); 63 | } 64 | 65 | @Override 66 | public abstract void onSave(); 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/datafilter/viewmodel/AppBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter.viewmodel; 19 | 20 | import com.sanfengandroid.datafilter.BuildConfig; 21 | 22 | import org.json.JSONException; 23 | import org.json.JSONObject; 24 | 25 | public class AppBean { 26 | public static final String UPDATE_URL = "https://cdn.jsdelivr.net/gh/sanfengAndroid/service-configure@main/fakexposed.json"; 27 | private static final String KEY_APP_STANDARD = "app_standard_" + BuildConfig.APP_TYPE; 28 | private String version; 29 | private long versionCode; 30 | private String link; 31 | private String noteCN; 32 | private String noteEN; 33 | 34 | public AppBean(String data) { 35 | try { 36 | JSONObject json = new JSONObject(data); 37 | json = json.getJSONObject(KEY_APP_STANDARD); 38 | version = json.optString("version", ""); 39 | versionCode = json.optLong("versionCode", 0); 40 | link = json.optString("link", ""); 41 | noteCN = json.optString("noteCN", ""); 42 | noteEN = json.optString("noteEN", ""); 43 | } catch (JSONException e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | 48 | public String getVersion() { 49 | return version; 50 | } 51 | 52 | public long getVersionCode() { 53 | return versionCode; 54 | } 55 | 56 | public String getLink() { 57 | return link; 58 | } 59 | 60 | public String getNoteCN() { 61 | return noteCN; 62 | } 63 | 64 | public String getNoteEN() { 65 | return noteEN; 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | return "AppBean{" + 71 | "version='" + version + '\'' + 72 | ", versionCode=" + versionCode + 73 | ", link='" + link + '\'' + 74 | ", noteCN='" + noteCN + '\'' + 75 | ", noteEN='" + noteEN + '\'' + 76 | '}'; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/xp/hooks/HookDebugCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.xp.hooks; 19 | 20 | import android.content.ContentResolver; 21 | import android.os.Build; 22 | import android.provider.Settings; 23 | 24 | import com.sanfengandroid.common.Const; 25 | import com.sanfengandroid.common.model.base.DataModelType; 26 | import com.sanfengandroid.common.reflection.ReflectUtil; 27 | import com.sanfengandroid.common.util.LogUtil; 28 | import com.sanfengandroid.fakeinterface.GlobalConfig; 29 | 30 | import java.lang.reflect.Method; 31 | 32 | import de.robv.android.xposed.XC_MethodHook; 33 | import de.robv.android.xposed.XposedBridge; 34 | 35 | import static com.sanfengandroid.xp.hooks.XposedFilter.TAG; 36 | 37 | /** 38 | * @author sanfengAndroid 39 | * @date 2020/11/01 40 | */ 41 | public class HookDebugCheck implements IHook { 42 | @Override 43 | public void hook(ClassLoader loader) throws Exception { 44 | Method method = Settings.Global.class.getMethod("getString", ContentResolver.class, String.class); 45 | GlobalConfig.addHookMethodModifierFilter(method); 46 | XposedBridge.hookMethod(method, new XC_MethodHook() { 47 | @Override 48 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 49 | String setting = (String) param.args[1]; 50 | String value = GlobalConfig.getEqualBlacklistStringValue(setting, DataModelType.GLOBAL_HIDE); 51 | if (value != null) { 52 | param.setResult(value); 53 | LogUtil.w(Const.JAVA_MONITOR_STATE, "Modify Settings.Global name: %s, value: %s", setting, value); 54 | } 55 | } 56 | }); 57 | if (!"release-keys".equals(Build.TAGS)) { 58 | LogUtil.v(TAG, "Original build tags: " + Build.TAGS); 59 | ReflectUtil.setFieldNoException(Build.class, null, "TAGS", "release-keys"); 60 | LogUtil.v(TAG, "New build tags: " + Build.TAGS); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/xp/hooks/HookNativeMethodChecked.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.xp.hooks; 19 | 20 | import android.os.Build; 21 | 22 | import com.sanfengandroid.common.Const; 23 | import com.sanfengandroid.common.util.LogUtil; 24 | import com.sanfengandroid.common.util.Util; 25 | import com.sanfengandroid.fakeinterface.GlobalConfig; 26 | 27 | import java.lang.reflect.Member; 28 | import java.lang.reflect.Method; 29 | import java.lang.reflect.Modifier; 30 | 31 | import de.robv.android.xposed.XC_MethodHook; 32 | import de.robv.android.xposed.XposedBridge; 33 | 34 | public class HookNativeMethodChecked implements IHook { 35 | private static final String TAG = HookNativeMethodChecked.class.getSimpleName(); 36 | 37 | @Override 38 | public void hook(ClassLoader loader) throws Throwable { 39 | String name = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? "getModifiersInternal" : "getModifiers"; 40 | Method method = Method.class.getSuperclass().getDeclaredMethod(name); 41 | GlobalConfig.addHookMethodModifierFilter(method); 42 | XC_MethodHook callback = new XC_MethodHook() { 43 | 44 | @Override 45 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 46 | if (!GlobalConfig.isHookMember((Member) param.thisObject)) { 47 | return; 48 | } 49 | try { 50 | int modify = (int) param.getResult(); 51 | modify = modify & ~Modifier.NATIVE; 52 | LogUtil.w(Const.JAVA_MONITOR_STATE, "Fix Hook Native flag: %s", Util.getMemberFullName((Member) param.thisObject)); 53 | param.setResult(modify); 54 | } catch (Throwable e) { 55 | LogUtil.e(TAG, "replace native modify error", e); 56 | } 57 | } 58 | }; 59 | XposedBridge.hookMethod(method, callback); 60 | LogUtil.v(TAG, "Hook Method Native check success"); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/cpp/common/scoped_utf_chars.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/11/20. 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include "macros.h" 10 | #include "scoped_local_ref.h" 11 | 12 | inline bool JniThrowNullPointerException(JNIEnv *env, const char *msg) { 13 | if (env->ExceptionCheck()) { 14 | env->ExceptionClear(); 15 | } 16 | 17 | ScopedLocalRef exc_class(env, env->FindClass("java/lang/NullPointerException")); 18 | if (exc_class.get() == nullptr) { 19 | return -1; 20 | } 21 | 22 | return env->ThrowNew(exc_class.get(), msg) == JNI_OK; 23 | } 24 | 25 | class ScopedUtfChars { 26 | public: 27 | ScopedUtfChars(JNIEnv *env, jstring s) : env_(env), string_(s) { 28 | if (s == nullptr) { 29 | utf_chars_ = nullptr; 30 | JniThrowNullPointerException(env, nullptr); 31 | } else { 32 | utf_chars_ = env->GetStringUTFChars(s, nullptr); 33 | } 34 | } 35 | 36 | ScopedUtfChars(JNIEnv *env, jstring s, bool check_null) : env_(env), string_(s) { 37 | if (s == nullptr) { 38 | utf_chars_ = nullptr; 39 | if (check_null) { 40 | JniThrowNullPointerException(env, nullptr); 41 | } 42 | } else { 43 | utf_chars_ = env->GetStringUTFChars(s, nullptr); 44 | } 45 | } 46 | 47 | ScopedUtfChars(ScopedUtfChars &&rhs) : 48 | env_(rhs.env_), string_(rhs.string_), utf_chars_(rhs.utf_chars_) { 49 | rhs.env_ = nullptr; 50 | rhs.string_ = nullptr; 51 | rhs.utf_chars_ = nullptr; 52 | } 53 | 54 | ~ScopedUtfChars() { 55 | if (utf_chars_) { 56 | env_->ReleaseStringUTFChars(string_, utf_chars_); 57 | } 58 | } 59 | 60 | ScopedUtfChars &operator=(ScopedUtfChars &&rhs) { 61 | if (this != &rhs) { 62 | // Delete the currently owned UTF chars. 63 | this->~ScopedUtfChars(); 64 | 65 | // Move the rhs ScopedUtfChars and zero it out. 66 | env_ = rhs.env_; 67 | string_ = rhs.string_; 68 | utf_chars_ = rhs.utf_chars_; 69 | rhs.env_ = nullptr; 70 | rhs.string_ = nullptr; 71 | rhs.utf_chars_ = nullptr; 72 | } 73 | return *this; 74 | } 75 | 76 | const char *c_str() const { 77 | return utf_chars_; 78 | } 79 | 80 | size_t size() const { 81 | return strlen(utf_chars_); 82 | } 83 | 84 | const char &operator[](size_t n) const { 85 | return utf_chars_[n]; 86 | } 87 | 88 | private: 89 | JNIEnv *env_; 90 | jstring string_; 91 | const char *utf_chars_; 92 | 93 | DISALLOW_COPY_AND_ASSIGN(ScopedUtfChars); 94 | }; 95 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_card_view.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 27 | 28 | 34 | 35 | 43 | 44 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/package_add_item_layout.xml: -------------------------------------------------------------------------------- 1 | 17 | 24 | 25 | 30 | 31 | 37 | 38 | 46 | 47 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/xp/ObservableMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.xp; 19 | 20 | import android.util.Pair; 21 | 22 | import androidx.annotation.NonNull; 23 | import androidx.annotation.Nullable; 24 | 25 | import java.util.HashMap; 26 | import java.util.Map; 27 | import java.util.Observable; 28 | import java.util.Observer; 29 | 30 | /** 31 | * @author sanfengAndroid 32 | */ 33 | public class ObservableMap extends HashMap { 34 | private final MapObservable mObservable = new MapObservable<>(); 35 | 36 | @Nullable 37 | @Override 38 | public V put(K key, V value) { 39 | V ret = super.put(key, value); 40 | mObservable.update(key, value); 41 | return ret; 42 | } 43 | 44 | @Override 45 | public void putAll(@NonNull Map m) { 46 | super.putAll(m); 47 | mObservable.update(m); 48 | } 49 | 50 | public void addObserver(Observer observer) { 51 | mObservable.addObserver(observer, this); 52 | } 53 | 54 | public void deleteObserver(Observer observer) { 55 | mObservable.deleteObserver(observer); 56 | } 57 | 58 | public int countObservers() { 59 | return mObservable.countObservers(); 60 | } 61 | 62 | public void deleteObservers() { 63 | mObservable.deleteObservers(); 64 | } 65 | 66 | public boolean hasChanged() { 67 | return mObservable.hasChanged(); 68 | } 69 | 70 | private static class MapObservable extends Observable { 71 | public void update(K key, V value) { 72 | setChanged(); 73 | notifyObservers(new Pair<>(key, value)); 74 | } 75 | 76 | public void update(Map m) { 77 | if (!m.isEmpty()) { 78 | setChanged(); 79 | notifyObservers(m); 80 | } 81 | } 82 | 83 | public synchronized void addObserver(Observer o, Map m) { 84 | // 这里不过滤重复添加,代码保证只被添加一次 85 | super.addObserver(o); 86 | o.update(this, m); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/res/layout/key_value_add_view_layout.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 22 | 23 | 31 | 32 | 37 | 38 | 39 | 40 | 50 | 51 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 22 | 23 | 24 | 25 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 44 | 45 | 51 | 52 | 53 | 56 | 59 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_fragment.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 22 | 23 | 27 | 28 | 36 | 37 | 38 | 47 | 48 | 49 | 50 | 51 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /app/src/main/cpp/hook/hook_stat.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by beich on 2020/12/28. 3 | // 4 | 5 | #include 6 | #include 7 | #include "hook_stat.h" 8 | #include "io_redirect.h" 9 | 10 | FUN_INTERCEPT HOOK_DEF(int, fchmodat, int dirfd, const char *pathname, mode_t mode, int flags) { 11 | IS_BLACKLIST_FILE(pathname); 12 | return get_orig_fchmodat()(dirfd, IoRedirect::GetRedirect(pathname), mode, flags); 13 | } 14 | 15 | STUB_SYMBOL HOOK_DEF(int, chmod, const char *path, mode_t mode) { 16 | return fchmodat(AT_FDCWD, path, mode, 0); 17 | } 18 | 19 | FUN_INTERCEPT HOOK_DEF(int, mkdirat, int dir_fd, const char *path, mode_t mode) { 20 | return get_orig_mkdirat()(dir_fd, IoRedirect::GetRedirectDirectory(path), mode); 21 | } 22 | 23 | STUB_SYMBOL HOOK_DEF(int, mkdir, const char *path, mode_t mode) { 24 | return mkdirat(AT_FDCWD, path, mode); 25 | } 26 | 27 | FUN_INTERCEPT HOOK_DEF(int, fstatat, int dir_fd, const char *path, struct stat *buf, int flags) { 28 | IS_BLACKLIST_FILE(path); 29 | const char *redirect = IoRedirect::GetRedirect(path); 30 | int result = get_orig_fstatat()(dir_fd, redirect, buf, flags); 31 | if (result != 0) { 32 | return result; 33 | } 34 | const FileAccess *file_access = IoRedirect::GetFileAccess(redirect); 35 | if (file_access == nullptr) { 36 | return result; 37 | } 38 | LOGD("redirect file stat: %s, orig access: %d, modify access: %d", path, buf->st_mode & ~07777, file_access->access); 39 | buf->st_mode &= ~07777; 40 | 41 | buf->st_mode |= file_access->access; 42 | buf->st_uid = file_access->uid; 43 | buf->st_gid = file_access->gid; 44 | return result; 45 | } 46 | __strong_alias(fstatat64, fstatat); 47 | 48 | STUB_SYMBOL HOOK_DEF(int, stat, const char *path, struct stat *buf) { 49 | return fstatat(AT_FDCWD, path, buf, 0); 50 | } 51 | __strong_alias(stat64, stat); 52 | 53 | // fstat传入fd已经被更改 54 | FUN_INTERCEPT HOOK_DEF(int, fstat, int fd, struct stat *buf) { 55 | return get_orig_fstat()(fd, buf); 56 | } 57 | __strong_alias(fstat64, fstat); 58 | 59 | STUB_SYMBOL HOOK_DEF(int, lstat, const char *path, struct stat *buf) { 60 | return fstatat(AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW); 61 | } 62 | __strong_alias(lstat64, lstat); 63 | 64 | FUN_INTERCEPT HOOK_DEF(int, mknodat, int dir_fd, const char *path, mode_t mode, dev_t dev) { 65 | IS_BLACKLIST_FILE(path); 66 | return get_orig_mknodat()(dir_fd, IoRedirect::GetRedirect(path), mode, dev); 67 | } 68 | 69 | STUB_SYMBOL HOOK_DEF(int, mknod, const char *path, mode_t mode, dev_t dev) { 70 | return mknodat(AT_FDCWD, path, mode, dev); 71 | } 72 | 73 | // mkfifo 多数用于多进程通讯,更改本进程的路径可能会影响到其它进程使用,因此不拦截 74 | 75 | FUN_INTERCEPT HOOK_DEF(int, utimensat, int dirfd, const char *pathname, const struct timespec times[2], int flags) { 76 | IS_BLACKLIST_FILE(pathname); 77 | return get_orig_utimensat()(dirfd, IoRedirect::GetRedirect(pathname), times, flags); 78 | } -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/model/LoadClassModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.model; 19 | 20 | import android.text.TextUtils; 21 | 22 | import com.sanfengandroid.datafilter.R; 23 | import com.sanfengandroid.datafilter.XpApplication; 24 | 25 | /** 26 | * @author sanfengAndroid 27 | */ 28 | public class LoadClassModel extends StringModel { 29 | 30 | private static boolean validJavaFullClassName(String fullName) { 31 | String split = "."; 32 | if (fullName.endsWith(split)) { 33 | return false; 34 | } 35 | int index = fullName.indexOf(split); 36 | if (index == -1) { 37 | return validJavaIdentifier(fullName); 38 | } 39 | for (String name : fullName.split("\\.")) { 40 | if (!validJavaIdentifier(name)) { 41 | return false; 42 | } 43 | } 44 | return true; 45 | } 46 | 47 | private static boolean validJavaIdentifier(String className) { 48 | if (className.length() == 0 || !Character.isJavaIdentifierStart(className.charAt(0))) { 49 | return false; 50 | } 51 | int size = className.length(); 52 | for (int i = 1; i < size; i++) { 53 | if (!Character.isJavaIdentifierPart(className.charAt(i))) { 54 | return false; 55 | } 56 | } 57 | return true; 58 | } 59 | 60 | @Override 61 | public int hashCode() { 62 | return super.hashCode(); 63 | } 64 | 65 | @Override 66 | public boolean equals(Object o) { 67 | return super.equals(o); 68 | } 69 | 70 | @Override 71 | public void onSave() { 72 | String value = getInput(); 73 | if (TextUtils.isEmpty(value)) { 74 | XpApplication.getViewModel().setMessage(R.string.input_empty_content); 75 | return; 76 | } 77 | if (!validJavaFullClassName(value)) { 78 | XpApplication.getViewModel().setMessage(R.string.input_class_name_illegal); 79 | return; 80 | } 81 | LoadClassModel add = new LoadClassModel(); 82 | add.setValue(value); 83 | XpApplication.getViewModel().addDataValue(add, index); 84 | XpApplication.getViewModel().setSaveResult(true); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/common/model/base/BaseKeyValueModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.common.model.base; 19 | 20 | import android.widget.TextView; 21 | 22 | import androidx.recyclerview.widget.RecyclerView; 23 | 24 | import com.sanfengandroid.datafilter.R; 25 | 26 | import org.json.JSONException; 27 | import org.json.JSONObject; 28 | 29 | import java.util.Objects; 30 | 31 | public abstract class BaseKeyValueModel extends BaseShowDataModel { 32 | private String key; 33 | private String value; 34 | 35 | public String getKey() { 36 | return key; 37 | } 38 | 39 | public void setKey(String key) { 40 | this.key = key; 41 | } 42 | 43 | public String getValue() { 44 | return value; 45 | } 46 | 47 | public void setValue(String value) { 48 | this.value = value; 49 | } 50 | 51 | @Override 52 | public int getLayoutResId() { 53 | return R.layout.item_card_view; 54 | } 55 | 56 | @Override 57 | public void bindView(RecyclerView.ViewHolder vh) { 58 | super.bindView(vh); 59 | TextView title = vh.itemView.findViewById(R.id.item_title); 60 | if (title != null) { 61 | title.setText(getKey()); 62 | } 63 | title = vh.itemView.findViewById(R.id.item_sub_title); 64 | if (title != null) { 65 | title.setText(getValue()); 66 | } 67 | } 68 | 69 | @Override 70 | public JSONObject serialization() throws JSONException { 71 | JSONObject json = super.serialization(); 72 | json.put("name", getKey()); 73 | json.put("value", getValue()); 74 | return json; 75 | } 76 | 77 | @Override 78 | public void unSerialization(JSONObject json) throws JSONException { 79 | super.unSerialization(json); 80 | setKey(json.getString("name")); 81 | setValue(json.getString("value")); 82 | } 83 | 84 | @Override 85 | public boolean equals(Object o) { 86 | if (this == o) return true; 87 | if (o == null || getClass() != o.getClass()) return false; 88 | BaseKeyValueModel that = (BaseKeyValueModel) o; 89 | return getKey().equals(that.getKey()); 90 | } 91 | 92 | @Override 93 | public int hashCode() { 94 | return Objects.hash(getKey()); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/datafilter/ui/ViewAnimation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter.ui; 19 | 20 | import android.animation.Animator; 21 | import android.animation.AnimatorListenerAdapter; 22 | import android.view.View; 23 | 24 | import com.sanfengandroid.datafilter.R; 25 | 26 | /** 27 | * @author sanfengAndroid 28 | */ 29 | public class ViewAnimation { 30 | 31 | public static boolean rotateFab(final View v, boolean rotate) { 32 | v.animate().setDuration(200) 33 | .setListener(new AnimatorListenerAdapter() { 34 | @Override 35 | public void onAnimationEnd(Animator animation) { 36 | super.onAnimationEnd(animation); 37 | } 38 | }).rotation(rotate ? 135f : 0f); 39 | return rotate; 40 | } 41 | 42 | public static void hide(final View v, int index) { 43 | v.setVisibility(View.VISIBLE); 44 | v.setAlpha(1f); 45 | v.setTranslationY(-((index + 1) * v.getHeight() + v.getResources().getDimension(R.dimen.fab_interval))); 46 | v.animate().setDuration(200) 47 | .translationY(0) 48 | .setListener(new AnimatorListenerAdapter() { 49 | @Override 50 | public void onAnimationEnd(Animator animation) { 51 | super.onAnimationEnd(animation); 52 | } 53 | }) 54 | .alpha(0f) 55 | .start(); 56 | } 57 | 58 | public static void show(final View v, int index) { 59 | v.setVisibility(View.VISIBLE); 60 | v.setAlpha(0f); 61 | v.setTranslationY(0); 62 | v.animate().setDuration(200) 63 | .translationY(-((index + 1) * v.getHeight() + v.getResources().getDimension(R.dimen.fab_interval))) 64 | .setListener(new AnimatorListenerAdapter() { 65 | @Override 66 | public void onAnimationEnd(Animator animation) { 67 | super.onAnimationEnd(animation); 68 | } 69 | }).alpha(1f) 70 | .start(); 71 | } 72 | 73 | public static void init(final View v) { 74 | v.setVisibility(View.INVISIBLE); 75 | v.setTranslationY(0); 76 | v.setAlpha(0f); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/res/values/type.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 23 | 24 | 27 | 28 | 31 | 32 | 35 | 36 | 39 | 40 | 43 | 44 | 47 | 48 | 51 | 52 | 55 | 56 | 59 | 60 | 63 | 64 | 67 | 68 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/xp/RemoteCall.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.xp; 19 | 20 | /** 21 | * 插件通过ContentProvider调用 22 | * 23 | * @author sanfengAndroid 24 | */ 25 | 26 | public enum RemoteCall { 27 | 28 | /** 29 | * 远程调用是否激活 30 | */ 31 | IS_ACTIVE("activation"), 32 | 33 | GET_APP_CONFIG("get_config"), 34 | 35 | WRITE_APP_CONFIG("write_config"), 36 | 37 | SET_APP_ENABLE("set_app_enable"), 38 | 39 | SET_APP_STRING_CONFIG("set_app_string"), 40 | 41 | SYNC_CONFIGURATION("sync_config"); 42 | 43 | public static final String KEY_CALL_RESULT = "ret"; 44 | /** 45 | * 通用布尔参数名,根据不同方法解释不同 46 | */ 47 | public static final String KEY_COMMON_BOOLEAN = "common_boolean"; 48 | /** 49 | * 通用字符串参数,不同方法不同解析 50 | */ 51 | public static final String KEY_COMMON_STRING = "common_string"; 52 | public static final String KEY_ERROR_DESCRIPTION = "error_string"; 53 | public static final String KEY_HOOK_APP_ENABLE = "app_enable"; 54 | /** 55 | * 该方法未定义 56 | */ 57 | public static final int RESULT_VALUE_UNDEFINED = -1; 58 | /** 59 | * 调用方法出错 60 | */ 61 | public static final int RESULT_VALUE_CALL_ERROR = -2; 62 | public static final int RESULT_VALUE_PARAM_NULL_ERROR = -3; 63 | public static final int RESULT_VALUE_PARAM_ERROR = -4; 64 | /** 65 | * 内部执行出错 66 | */ 67 | public static final int RESULT_VALUE_EXEC_ERROR = -5; 68 | /** 69 | * 调用成功 70 | */ 71 | public static final int RESULT_VALUE_CALL_SUCCESS = 1; 72 | /** 73 | * 调用方传入的包名 74 | */ 75 | public static final String KEY_APP_PKG = "pkg"; 76 | public static final String KEY_DATA_TYPE = "data_type"; 77 | public static final String KEY_SYNC_FILE_NAME = "sync_name"; 78 | public static final String KEY_SYNC_FILE_DATA = "sync_data"; 79 | /** 80 | * 同步数据太大则需要分段 81 | */ 82 | public static final String KEY_SYNC_BLOCK_INDEX = "sync_block"; 83 | public static final String METHOD_HOOK_FLAG = "sanfengandroid"; 84 | public final String method; 85 | 86 | RemoteCall(String method) { 87 | this.method = method; 88 | } 89 | 90 | public static RemoteCall nameToRemoteCall(String name) { 91 | for (RemoteCall call : RemoteCall.values()) { 92 | if (call.method.equals(name)) { 93 | return call; 94 | } 95 | } 96 | return null; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/sanfengandroid/datafilter/XPContentProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 FakeXposed by sanfengAndroid. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.sanfengandroid.datafilter; 19 | 20 | import android.content.ContentProvider; 21 | import android.content.ContentValues; 22 | import android.database.Cursor; 23 | import android.net.Uri; 24 | import android.os.Bundle; 25 | 26 | import androidx.annotation.NonNull; 27 | import androidx.annotation.Nullable; 28 | 29 | import com.sanfengandroid.common.util.LogUtil; 30 | import com.sanfengandroid.xp.ContentProviderAgent; 31 | import com.sanfengandroid.xp.RemoteCall; 32 | 33 | 34 | /** 35 | * @author sanfengAndroid 36 | */ 37 | public class XPContentProvider extends ContentProvider { 38 | private static final String TAG = XPContentProvider.class.getSimpleName(); 39 | 40 | @Nullable 41 | @Override 42 | public Bundle call(@NonNull String authority, @NonNull String method, @Nullable String arg, @Nullable Bundle extras) { 43 | return call(method, arg, extras); 44 | } 45 | 46 | @Nullable 47 | @Override 48 | public Bundle call(@NonNull String method, @Nullable String arg, @Nullable Bundle extras) { 49 | if (!RemoteCall.METHOD_HOOK_FLAG.equals(method)) { 50 | return null; 51 | } 52 | RemoteCall remoteCall = RemoteCall.nameToRemoteCall(arg); 53 | return ContentProviderAgent.getInstance().invoke(getContext(), remoteCall, extras); 54 | } 55 | 56 | @Override 57 | public boolean onCreate() { 58 | LogUtil.v(TAG, "create self provider: %s", XpApplication.getInstance()); 59 | return true; 60 | } 61 | 62 | @Nullable 63 | @Override 64 | public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { 65 | return null; 66 | } 67 | 68 | @Nullable 69 | @Override 70 | public String getType(@NonNull Uri uri) { 71 | return null; 72 | } 73 | 74 | @Nullable 75 | @Override 76 | public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { 77 | return null; 78 | } 79 | 80 | @Override 81 | public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { 82 | return 0; 83 | } 84 | 85 | @Override 86 | public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { 87 | return 0; 88 | } 89 | } --------------------------------------------------------------------------------